How to get custom metrics in APM?

I have setup application performance monitoring in my Nodejs application. I can see my metrics coming through for CPU / memory etc but can't seem to get things to work for custom metrics.

I am following the docs on adding a metric for tracking the clients connected to our web socket server but can't see the metrics in the Elastic dashboard anywhere:

I have the following code:

apm.registerMetric('ws.connections', () => socketClients.length);

Under APM -> Services -> Metrics I am searching for ws.connections but no results are showing up.

Do I need to add anything else to get the custom metrics to pull through?

Am I correct in thinking I should see these under APM -> Services -> Metrics

Hi @stretch0. Thanks for the question.

Am I correct in thinking I should see these under APM -> Services -> Metrics

No. The APM > Services > $serviceName > Metrics page only shows visualizations for a strict set of well-known metrics -- specifically some of the system.* metrics described at Metrics | APM Node.js Agent Reference [4.x] | Elastic that are always collected by the Node.js APM agent. Eventually we hope to add visualizations for some of the nodejs.* runtime metrics there.

There has been some discussion in the past for allowing user-defined metrics visualizations on this page, but I am not aware of current plans for that.

Do I need to add anything else to get the custom metrics to pull through?

Ultimately, the best way to visualize custom metrics is by building your own dashboard.

First, however, let's take an aside to look at the raw "metricset" documents that the Node.js APM agent should be sending to verify that your custom metric is getting through. In my example I used the following Node.js script. I used foo.connections to have a different metric name:

// example-registerMetric.js
const apm = require('elastic-apm-node').start({
  serviceName: 'example-registerMetric',
  serverUrl: 'XXX',
  secretToken: 'XXX',
  metricsInterval: '5s',
  apiRequestTime: '5s',
})

const socketClients = []

apm.registerMetric('foo.connections', () => socketClients.length);

// Randomly change the length of socketClients every 1s.
setInterval(function () {
  if (Math.random() < 0.75) {
    socketClients.push({type: 'socket', startTime: Date.now()})
  } else {
    socketClients.pop()
  }
}, 1000)

I ran that for a while. Then I went to "Discover" in Kibana and searched for documents with that metric field using foo.connections: *. That verifies that documents with my custom metric are getting into Elasticsearch.

Then I went to "Dashboard" in Kibana and created a dashboard with a visualization of "foo.connections". For example:

Please let me know if that doesn't answer your question.

2 Likes

Hi @trentm

Ok that makes more sense as to why I couldn't see the metrics automatically pulling through.

I have tried following your example of searching for ws.connections: * in Kibana but seems like the metric isn't even pulling through to there

I noticed you've included the following attributes when starting APM node

metricsInterval: '5s',
apiRequestTime: '5s',

I have updated mine to include these now too which didn't seem to make any difference but I can't find any docs on these and wasn't sure if they are required?

My start config is as follows:

apm.start({
  serverUrl: env.ELASTIC_SERVER_URL,
  secretToken: env.ELASTIC_SECRET_TOKEN,
  environment: env.NODE_ENV,
  active: true,
  metricsInterval: '5s',
  apiRequestTime: '5s',
});

Is there anything else I am missing that would cause the metrics not to show up for me?

I have tried following your example of searching for ws.connections: * in Kibana but seems like the metric isn't even pulling through to there

It looks like you are searching in the "functionbeat-7.11.1*" index, which will only hold data from the separate functionbeat tool. You will need to change to the appropriate apm index. I don't know off hand the exact name of the index for version 7.11 of the stack. In version 7.15 it is this index pattern: traces-apm*,logs-apm*,metrics-apm*.

Those aren't required, but they tell the APM agent to (a) gather and send metrics every 5s instead of the usual 30s and (b) forward data on to the APM server every 5s instead of the usual ~10s. I added these to my demo to get a faster turn around while playing. Generally you would not want to use these settings for production. They are both documented on this page: Configuration options | APM Node.js Agent Reference [4.x] | Elastic

Ok that makes sense. I can now see the metrics pulling through into functionbeat so I will go ahead and setup a dashboard for that data being pulled in. Thanks for your help there.

One more question, is there an advantage of doing it this way with registering metrics vs if I was to just add an info level log and create a dashboard based on filtering of that log?

Currently with apm.registerMetric() there probably wouldn't be much difference. The registerMetric() API does support adding a set of labels which could be used for segmentation (e.g. collecting latency for requests that are 500 errors vs. successful responses). However, you could manually accomplish the same with structured log records.

The APM agent's handling will ensure a regular interval of collection of the metrics, which can be important for sanely aggregating metrics over time periods in Elasticsearch later. Doing this manually with a setInterval is straightforward as well, though.

The APM system will setup the Elasticsearch index templates so that the types for your metric fields are appropriate. Doing this via logs might require manually setting up index templates appropriately.

The current apm.registerMetric() is limited to a simple Gauge metric type. We eventually will support counters and histograms -- likely based on the OpenTelemetry Metrics SDK. The latter (histograms) would be much more complex to manually handle with log records.

Ok thanks for the detailed response. That makes sense.

Seems like I've got things working with your help now so really appreciate that.

Sounds like registerMetric still has some more development to go so I look forward to seeing more features and functionality being built around it.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.