trace_flags attribute on each exemplar, and Sherlock’s histogram boundaries. One file, sherlock.go, takes care of them. This page adds it to a net/http service.
The file comes in two variants that send the same data. In the first, every Sherlock setting is written in the file, so a reader sees all of them in one place. In the second, the standard OTEL_* environment variables carry the settings, which suits a team that already configures OpenTelemetry that way, and the file is shorter. Step 2 has both.
Configuration covers production settings such as health checks, custom histograms, sampling, and logs. Differences from Node.js lists what the Go setup does differently from the Sherlock SDK for Node.js.
What you’ll learn
- Which modules to add, at which versions
- The two places the Sherlock settings can live, and what stays in code either way
- What
sherlock.gosets, and why each setting is there - Where the first traces and metrics show up
Prerequisites
- Go 1.22 or later, for
ServeMuxmethod-and-path patterns. Tested with Go 1.25. - A Sherlock organization and its bearer token from Settings → Collector. Get started shows where.
- A service on
net/http. For other routers, see Routers and nested muxes.
Steps
1
Add the modules
otelhttp.WithRouteTag was removed and the OTEL_SEMCONV_STABILITY_OPT_IN switch is gone. Keep the pins until you have tested an upgrade.2
Add sherlock.go and set the environment
Pick one variant. Save the file next to your What it sets, and why:Settings → Collector shows the Endpoint and the Bearer Token for your organization; copy both, since the endpoint differs by organization.
main.go and export the variables it expects. Nothing in either file is specific to your routes.- Settings in the file
- Settings in environment variables
sherlock.go
The file reads four variables:
env selects the source the data lands in, so use the value you chose in Get started. A value that matches no source is not shown.3
Wrap your server
Call Register handlers with method-and-path patterns, such as
Setup before the server starts, wrap the mux with otelhttp.NewHandler, and on shutdown stop the server first, then flush telemetry. This main.go is complete and works with either variant.main.go
GET /work. The span name and the http.route metric attribute come from the pattern. A handler registered as a bare path gives a span named GET with no route, and a mux mounted behind http.StripPrefix reports its mount pattern for every inner route. See Routers and nested muxes.4
Run
5
Open Sherlock
- Traces. Open Traces, switch to the Spans view, and pick
checkout-api. Spans leave in batches of a few seconds. Each request from thismain.gois one span named by its pattern,GET /work, withhttp.response.status_codeon it. The Traces view lists only traces with more than one span, so it stays empty until a request makes a nested call. - Metrics. Open Metrics and choose
http.server.request.duration. It appears after the first export, 60 seconds by default. Group byhttp.routeto see the two routes apart. Each bucket carries an exemplar; click one to open the request’s trace. - Runtime. With the settings-in-the-file variant,
go.goroutine.countandgo.memory.usedare on the same page.
What arrives
Outbound calls through an
otelhttp.NewTransport client add http.client.request.duration with the same boundaries. Logs are not sent by this setup. Logs with trace ids adds them over OTLP with the same bearer token, or stamps stdout lines for a collector.
Troubleshooting
Nothing arrives
Nothing arrives
Export errors go to stderr through the SDK’s error handler, prefixed with
traces export: or failed to upload metrics:. A 401 means the token is wrong or missing. Check that the endpoint and token variables are set in the shell that runs the service, that both match Settings → Collector, and that the endpoint has no trailing path.Data arrives but the service is not in the source I expected
Data arrives but the service is not in the source I expected
The
env value in OTEL_RESOURCE_ATTRIBUTES did not match a source. Compare it with the source’s match value under Settings → Collector.A span named GET with no route, or health checks in the metrics
A span named GET with no route, or health checks in the metrics
A request matched no pattern, or a health checker hit the service. Requests that match no pattern get no
http.route. Health checks need a filter; there is no default ignore list. See Skip health checks.Metrics appear a minute late
Metrics appear a minute late
The periodic reader exports every 60 seconds by default. Set
OTEL_METRIC_EXPORT_INTERVAL=30000 for 30 seconds. The catalog refreshes every 60 seconds on top of that.Related topics
Configuration
Health checks, custom histograms, sampling, kill switches, logs, shutdown.
Differences from Node.js
What to expect if you know the Sherlock SDK for Node.js.
Traces
Find a request, read the waterfall, jump to its logs.
Exemplars
From a spike on a chart to the request behind it.

