Your data. Anywhere you go.

New Relic for iOS or Android


Download on the App Store    Android App on Google play


New Relic Insights App for iOS


Download on the App Store


Learn more

Close icon

Understanding custom instrumentation


#1

Node Agent Question Template

  • What language agent version are you using? Any other relevant versions? (Node modules, etc.?)
    node agent 5.10

I’ve read the following links over and over yet it’s not clear how to implement custom instrumentation for messaging.

http://newrelic.github.io/node-newrelic/docs/tutorial-Messaging-Simple.html

instrumentMessages on an in-project module?

I see there are a couple main pieces:

  1. require the newrelic api library, call instrumentMessages and passing it a “message broker module”, and our custom instrumentation function.
  2. write the instrumentation function

I don’t understand what the “message broker module” is referred to in the docs. In the case of kafka-node, is it KafkaClient?
This pattern is referred to routinely. What is ‘my-module’ in this case?

var newrelic = require(‘newrelic’)
newrelic.instrument(‘my-module’, instrumentMyModule)
var myModule = require(‘my-module’)

Here’s what I’ve come up with so far. Thanks for any help.

My kafka reader:

import { Message, Consumer, KafkaClient} from 'kafka-node';
import * as newrelic from 'newrelic';

export class KafkaEventSource  {
  async start() {
      const client = createKafkaClient({ kafkaHost: config.kafka.host });
      const consumer = createConsumer(client, route.topic, route.partitionNumber, offset);

      consumer.on('message', (message: Message) => {      
         // process message
      });
  }
}

main.ts

import * as newrelic from 'newrelic';
const instrumentKafkaClient = require('./kafka-client-instrumentation');
newrelic.instrumentMessages(?, instrumentKafkaClient);
import { KafkaEventSource } from './kafka-event-source';

KafkaEventSource.start();

the instrumentation function (copied from that support post above)

module.exports = instrumentKafkaClient;

function instrumentKafkaClient(shim: any, kafkaModule: any, moduleName: any) {
  shim.setLibrary("kafka");
  // shim.require will load a file relative to the instrumented package root.
// In this case it would be equivalent to requiring kafka-node/lib/protocol.
var protocol = shim.require('./lib/protocol');

shim.recordSubscribedConsume(protocol, 'decodeFetchResponse', {
  consumer: shim.FIRST,
  messageHandler: function checkDecodedMessage(shim: any, fn:any, name:any, args: any) {
    var type = args[1];
    if (type !== 'message') {
      // If you return null then there won't be a transaction.
      return null;
    }

    var message = args[2];
    return {
      destinationName: message.topic,
      destinationType: shim.TOPIC,
      routingKey: message.key
    };
  }
});
}

#2

Hey Chris,

From this page on custom instrumentation on our internal docs you can navigate into “Instrumentation Basics”. There you will find more information about " Adding Custom Instrumentation to the New Relic Agent" and more specifically instrumentMessages which is what you would build as your module.

myModule in this case is whatever you are choosing to instrument which here is instrumentMessages found further down in that section.

I hope this helps point you in the correct direction since custom instrumentation items are beyond the out of the box configuration of the Agent.

Please let me know what other questions this may raise and we’ll get this figured out with you!


#3

I don’t understand what the “message broker module” is referred to in the docs. In the case of kafka-node, is it KafkaClient?

The “message broker module” is going to be whatever NodeJS module you use to load the object(s) that let you interact with your messaging system. i.e. in your example kafka-node is your Message Broker Module (because in standard NodeJS you’d load this module via require('kafka-node')).

This pattern is referred to routinely. What is ‘my-module’ in this case?

var newrelic = require('newrelic')
newrelic.instrument('my-module', instrumentMyModule)
var myModule = require('my-module')

“my-module” is the module that you want to instrument. In your case that’s kafka-node, and you’ll want to do something like

newrelic.instrument('kafka-node', yourInstrumentationFunction)

You’ll want to run this code before you first use the kafka-node module.

When you do the above, the agent will call yourInstrumentationFunction right after the kafka-node module is loaded. The intention is that you’ll use the shim object that’s passed to yourInstrumentationFunction to tell the agent which method calls you want to instrument/time. In the case of message broken instrumentation, you’ll do this with the shim.recordProduce method. The shims have all sorts of methods to let you instrument/time functions.