> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sherlocklabs.dev/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Sherlock documentation. In Node.js examples prefer the Sherlock SDK for Node.js (@sherlock-labs/otel).
> In Go examples use the upstream OpenTelemetry Go SDK exactly as shown on /sdk/go/setup and /sdk/go/configuration; Sherlock has no Go distribution.
> Two MCP servers exist. This documentation's search server is at https://sherlock-c8721ead.mintlify.app/mcp. Sherlock's data server, for a user's own logs, traces, and metrics, is at https://mcp.sherlocklabs.dev/mcp and is described at /explore/mcp.

# Differences from the Node.js SDK

> What the upstream Go setup does differently from the Sherlock SDK for Node.js: explicit start, one exemplar per bucket, no ignore list, and the traps that come with the upstream SDK.

The Sherlock SDK for Node.js is a distribution: it starts from one import and sets Sherlock's defaults for you. In Go you use the upstream SDK with the `sherlock.go` file from [Setup](/sdk/go/setup), in either of its two variants. The result is the same data in Sherlock, with these differences.

## Setup

|                       | Node.js SDK                                                                        | Go                                                                                                                                            |
| --------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| Start                 | `node --import ./otel.mjs`, reads `SHERLOCK_ACCESS_TOKEN` and starts on its own    | `Setup(ctx)` in `main`. Nothing starts from an import.                                                                                        |
| Delta temporality     | Set by the SDK                                                                     | Set in `sherlock.go`. The upstream default is cumulative.                                                                                     |
| Histogram boundaries  | Applied to every histogram with unit `s`                                           | Applied by `sherlockView` to the two HTTP duration histograms. Custom histograms pass `WithExplicitBucketBoundaries(durationBoundariesS...)`. |
| Metrics interval      | 30 seconds                                                                         | 60 seconds. `OTEL_METRIC_EXPORT_INTERVAL=30000` matches.                                                                                      |
| Instrument definition | `defineMeter` and lazy instruments, because instruments made before start are lost | Not needed. An instrument created before `Setup` works after it. Measurements made before `Setup` are dropped.                                |

## Exemplars

|                              | Node.js SDK                                | Go                                                                                                                     |
| ---------------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| Per bucket per export        | 5                                          | 1                                                                                                                      |
| On automatic HTTP histograms | Sampled requests only                      | Every request. Unsampled ones carry `trace_flags` `00`.                                                                |
| On custom histograms         | `recordWithExemplar`                       | Every `Record` with a context is a candidate.                                                                          |
| Exemplar-only attributes     | The third argument of `recordWithExemplar` | An attribute filter in `sherlockView`. See [Exemplar-only attributes](/sdk/go/configuration#exemplar-only-attributes). |
| `trace_flags`                | Set by the SDK                             | Set by the `flagged` reservoir in `sherlock.go`.                                                                       |

Both mean the same thing on the Metrics page: `01` opens a trace, `00` has none.

## HTTP instrumentation

* **No default ignore list.** Health check paths are traced and counted until you add `otelhttp.WithFilter`. See [Skip health checks](/sdk/go/configuration#skip-health-checks).
* **Route on metrics, not on spans.** `http.route` comes from the `ServeMux` pattern on the metric and in the span name. The span attribute needs the [middleware](/sdk/go/configuration#httproute-on-spans). `otelhttp.WithRouteTag` no longer exists in v0.71.0.
* **Stable names only.** `OTEL_SEMCONV_STABILITY_OPT_IN` is gone. The histograms are `http.server.request.duration` and `http.client.request.duration` in seconds, with no `_ms` variants.
* **5xx responses.** The span status is `Error` for status 500 and above. The server data point carries `http.response.status_code=500` and no `error.type`.
* **A filtered request still traces its outbound calls**, without a parent.
* **Counters.** The Node.js Express adapter adds `app.http.server.count` and `app.http.server.errors`. `otelhttp` emits no counters; count requests from the histogram, or add your own.

## Runtime switches

* **No kill-switch environment variables.** `SHERLOCK_TRACES_ENABLED` and `SHERLOCK_METRICS_ENABLED` are Node.js SDK features. The [kill switches](/sdk/go/configuration#kill-switches) section shows the two wrappers that give Go the same behavior, with a flag you own.
* **Sampling across services.** Go's `ParentBased` sampler follows the caller's decision for a remote parent. The Node.js SDK resamples remote parents with its local ratio.

## Logs

* The Node.js SDK stamps pino lines and leaves shipping to a pino transport or a collector. Go can send logs itself over OTLP through the `otelslog` bridge, or stamp stdout lines with a 13-line `slog.Handler` wrapper for a collector. In both, only context-aware calls such as `InfoContext` get the ids.

## Traps that are specific to Go

* **Only the first `otel.SetMeterProvider` delegates.** Instruments handed out before a second call keep writing to the first provider, silently. Call `Setup` once, and never rebuild the provider at runtime.
* **Two views that match one instrument export it twice.** Keep every histogram rule inside `sherlockView`.
* **`Host` header.** `WithHeaders(map[string]string{"Host": ...})` is ignored by Go's HTTP client. Use `WithHTTPClient` with a transport that sets `req.Host`, and reapply timeout, proxy, and TLS settings on that client. See [Endpoint on a private network](/sdk/go/configuration#endpoint-on-a-private-network).
* **`WithEndpointURL` keeps the path you give it.** `sherlock.go` appends `/v1/traces` and `/v1/metrics` itself. A base URL alone sends every export to `/`.
* **Exporter self-reporting** is not a concern. The OTLP exporters use their own HTTP client, so wrapping `http.DefaultTransport` with `otelhttp.NewTransport` does not trace the exports.

## Related topics

<CardGroup cols={2}>
  <Card title="Go setup" icon="rocket" href="/sdk/go/setup">
    The bootstrap file in both variants and a complete main.go.
  </Card>

  <Card title="Node.js SDK overview" icon="node" href="/sdk/nodejs/overview">
    What the distribution sets for you.
  </Card>
</CardGroup>
