Zum Inhalt springen

Diese Seite ist noch nicht übersetzt und wird auf Englisch angezeigt.

Correlation, propagation, and baggage

How Elide links logs, errors, metrics, and profiles to the active span, continues W3C trace context across HTTP, and propagates W3C baggage only when you allow it.

Auf dieser Seite

The span active where a signal is produced links that signal to its trace. Elide applies this to everything it records, with no code changes.

SignalLinked to the active span by
Log recordsTrace id, span id, and trace flags on the record
ErrorsAn exception log record and span event on the span, and an elide.errors exemplar
MetricsExemplars on histogram buckets and sums
ProfilesA link from each CPU sample to its span

Request handlers run inside the request’s server span, so anything they log, throw, measure, or call joins the request’s trace.

Logs

Every log record emitted inside a span carries its trace id, span id, and trace flags: records from the OpenTelemetry logs API, captured console.* and Python logging output, and Elide’s own log records.

// handler.ts
export default {
  async fetch(request: Request): Promise<Response> {
    console.log("looking up order"); // exported with the request span's ids
    return new Response("ok");
  },
};

Errors

One error produces three records that share a timestamp and the same exception.type, exception.message, and exception.stacktrace:

RecordWhere
Log record, severity ERROR, event.name = exceptionLinked to the active span
exception event on the span, and ERROR status when the failure ends the spanThe active span
elide.errors increment, with an exemplar pointing at the spanerror.type, elide.error.origin

With no active span, the log record and counter are still emitted. OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN=logs drops the span events; the default, logs/dup, keeps both. Uncaught exceptions, unhandled rejections, failing request handlers, and span.recordException(…) all take this path; recordException never changes span status.

A process that crashes cannot export. The next Elide process on the machine that has telemetry configured exports the crash report as a FATAL error record: up to 16 reports per run, from the last 7 days, each sent once. See Emitted telemetry.

Only reports from a process with the same service.name are exported; a crash in a process without telemetry configured is never exported.

Metrics and exemplars

A counter or histogram measurement recorded inside a sampled span carries an exemplar: the trace id, span id, value, and time. Backends that read exemplars link a latency bucket to an example trace.

OTEL_METRICS_EXEMPLAR_FILTERExemplars from
trace_based (default)Measurements inside a sampled span
always_onEvery measurement
always_offNone

Elide keeps the latest exemplar per histogram bucket and per sum in each export. http.server.request.duration and http.client.request.duration carry exemplars of their own request spans.

Profiles

Each guest CPU sample links to the span active on the sampled thread when the sample was taken, including after await, in promise callbacks, and across Python asyncio tasks. See Profiles.

Trace context over HTTP

Elide’s HTTP server and clients use W3C Trace Context in both directions:

DirectionBehavior
InboundA valid traceparent (with tracestate) on a served request becomes the parent of the server span. An invalid one starts a new trace.
Outboundfetch sends traceparent and tracestate for its client span. A header the caller set is never replaced.
curl -H 'traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01' http://localhost:8080/

traces.propagators (or OTEL_PROPAGATORS) chooses what propagation.inject and propagation.extract do in your code: tracecontext, baggage, or none. Removing tracecontext also stops Elide’s HTTP clients from sending traceparent. node:http client requests and Python HTTP clients do not send it yet; inject it with the API:

import { context, propagation } from "@opentelemetry/api";
import http from "node:http";

const headers: Record<string, string> = {};
propagation.inject(context.active(), headers);
http.get("http://localhost:8081/inventory", { headers });

Baggage

W3C baggage carries key-value pairs alongside a trace. Your code can always read, set, and send baggage through the OpenTelemetry API. Elide’s HTTP server and clients pass the baggage header only for directions you turn on, because baggage from a client is untrusted input:

opentelemetry {
  propagation {
    baggage {
      inbound = true
      outbound = true
      allow { "tenant"; "region" }
      spanAttributes { "tenant" }
    }
  }
}
PropertyVariableEffectDefault
inboundELIDE_OTEL_BAGGAGE_INBOUNDA served request’s baggage header becomes the handler’s baggage.false
outboundELIDE_OTEL_BAGGAGE_OUTBOUNDfetch sends the current baggage, unless the request sets baggage itself.false
allowELIDE_OTEL_BAGGAGE_ALLOWOnly these keys pass, in both directions.all keys
spanAttributes—These inbound keys are recorded on the server span as baggage.<key>; each must be in allow.none
  • A header over 8,192 bytes or 180 members, or with any malformed member, is dropped whole.
  • Baggage received on a request reaches outgoing requests only when both directions are on.
  • OTEL_PROPAGATORS does not turn baggage on for Elide’s HTTP server and clients; it affects only the API in your code.

Read inbound baggage in a handler:

import { context, propagation } from "@opentelemetry/api";

export default {
  async fetch(): Promise<Response> {
    const tenant = propagation.getBaggage(context.active())?.getEntry("tenant")?.value;
    return new Response(`tenant: ${tenant ?? "none"}\n`);
  },
};

Samples

War diese Seite hilfreich?