Define instruments
UsedefineMeter to bind one instrumentation scope for a file of instruments. Define at module scope.
- A definition resolves the real instrument on the first record after
start(). Records beforestart()or afterstop()are dropped, not broken. No method throws. - The scope name is the
ScopeNameof the metric in Sherlock. - The standalone functions
defineCounter,defineHistogram, anddefineGaugetake the same options plusmeterName. They return the same objects.
Units and boundaries
- A histogram’s unit defaults to
s. Record durations in seconds. Do not name a metric*_ms. - A histogram that measures something else declares its unit:
m.histogram('app.payload.size', { unit: 'By' }). - Counters and gauges have no default unit.
boundariesis optional. The default depends on the unit:
- An explicit list always wins:
m.histogram('app.batch.duration', { boundaries: [1, 5, 30, 120, 600] }). - Extend a default when you need headroom:
boundaries: [...DEFAULT_DURATION_BOUNDARIES_S, 30, 60]. Both defaults are exported. - Do not transcribe a boundary list into your code. Use the default or extend it.
- The histogram and its exemplar reservoir get the same list, so an exemplar lands in the bucket its count landed in.
Attributes on the series and attributes on the exemplar
recordWithExemplar(value, attrs, exemplarAttrs) records the value and samples one exemplar into the bucket the value falls in.
attrsdefines the series. Keep it low cardinality: a provider, a route, a status.exemplarAttrsrides only on the exemplar and never widens the series. Put high-cardinality keys here: an order id, a job id, a customer id.- Record inside the span you want the exemplar to link to. The SDK reads the active span at the moment of the call.
What an exemplar carries
Whenever a span is active, the exemplar gets that span’s trace id and span id, plus atrace_flags attribute with the W3C flags byte as two hex digits. This happens at any sampling decision.
- Your own
exemplarAttrskey always wins,trace_flagsincluded. - With no span in scope, the exemplar has no trace keys and no
trace_flags. - An exemplar with neither a trace context nor an attribute is dropped. There is nothing to click into.
Two exemplar paths, one limit
- Your histograms get exemplars at any sampling.
trace_flagstells you whether the trace was exported. - The auto-instrumented
http.server.request.durationandhttp.client.request.durationget exemplars only for sampled requests. An unsampled request has a non-recording span with no attributes, so the SDK cannot rebuild the metric’s attribute set for the exemplar.
Log correlation
- The pino instrumentation stamps
trace_id,span_id, andtrace_flagson every log line written inside a request. - Every exemplar carries the same three: the ids as its own
traceIdandspanId, the flags as thetrace_flagsattribute. - The join from a chart to the logs is one filter on
trace_id. Nothing to configure.
A request gets
00 in two cases: the sample ratio is below 1, or traces are off through the kill switch.
HTTP server metrics in one line
For Express or Koa, the adapter adds three instruments with exemplars, tagged with the route template.routeis the framework’s route template./users/:idstays one series.- Options:
ignoreRequest(req)skips a request, for SSE, websockets, long polls, and health checks. The adapter does not read the SDK’signorePaths, so/healthzis counted here unless you skip it.routeName(req)overrides the template.recordExemplarsdefaults totrue.
- The auto-instrumented
http.server.request.durationuses different attribute keys for the same ideas:http.route,http.request.method,http.response.status_code,error.type. One label expression cannot filter both families.
Reservoirs
- Each histogram bucket keeps
metrics.exemplarsPerBucketexemplars per export interval, five by default. - Reservoirs clear on export.
- A service that serves a few requests per interval still gets exemplars. One that serves none in an interval exports no data points and no exemplars. This is not a bug.
How an exemplar finds its data point
At export, an exemplar attaches to a data point by an exact match on metric name plus attributes. A miss is not an error: the data point ships, the chart looks normal, and the exemplar disappears. The SDK logs a throttled drift warning when exemplars for a metric match no data point on two consecutive exports. That warning is the signal. WithrecordWithExemplar this cannot happen. One call feeds one value and one attribute set to both the histogram and the reservoir.
Test your metrics with a local sink
You can check names, units, buckets, attributes, and exemplars without Sherlock.- Write a
node:httpserver that acceptsPOST /v1/metricsandPOST /v1/tracesand stores the JSON bodies. - Call
start()withendpointpointed at it andinstrumentations: []. - Record.
- Call
stop(). It forces the final flush. - Read the bodies. Each metric carries its scope, unit, boundaries, data points, and exemplars.
Related topics
Custom spans
Record inside the span you want the exemplar to link to.
Exemplars in Sherlock
Follow a spike to the request and its logs.

