/docs/opentelemetry-signals
logs + traces + metrics
free plan / 1 gb-mo
telemtra.io
// opentelemetry guide

OpenTelemetry signals:
logs, traces, and metrics.

OpenTelemetry organizes telemetry into three signal types. Each captures a different shape of data, and together they let you investigate any production question without switching tools.

The three signals at a glance

Each OpenTelemetry signal answers a different category of question. Backends like Telemtra store all three under the same resource attributes, so the same service name lights up logs, traces, and metrics together.

  • Traces — "What happened during this slow request, and which downstream call caused it?" Distributed traces capture the causal chain of operations across services.
  • Metrics — "How many requests per second are we serving, and what's the p99 latency?" Aggregated numeric values over time, used for dashboards and threshold alerts.
  • Logs — "What did this service actually print when the error happened?" Individual structured records carrying severity, body, and attributes.

Most production incidents touch all three: a metric alert fires, you open a trace to find the slow span, then read the log lines from the span to see the error message. OpenTelemetry's value is that the three signals share resource attributes and trace context, so you do not have to manually correlate them.

Traces and spans

A trace is a directed graph of spans representing one logical operation across one or more services. A span represents a single unit of work inside a service: an HTTP request handler, a database query, a function call.

Each span carries:

  • trace_id (128-bit) and span_id (64-bit) — identifiers that link spans together.
  • parent_span_id — the span that caused this one, or null for root spans.
  • name — a short operation label (e.g. HTTP POST /checkout, SELECT users).
  • start_time and end_time — nanosecond-precision timestamps.
  • Attributes — structured key/value pairs (e.g. http.method=POST, db.statement=SELECT ...).
  • Events — timestamped points inside the span (used for exceptions, log messages, or phase transitions).
  • Status — OK, ERROR, or UNSET.
  • Links — references to spans in other traces (used for batch processing and fan-out patterns).

Spans across services link through W3C trace context: an HTTP header (traceparent) propagates the trace_id and parent span_id from caller to callee, so a single trace can span many services and runtimes. See OpenTelemetry glossary for the precise definitions.

Sampling decides what fraction of traces are kept. The two common strategies are head-based sampling (the SDK decides at trace start, fast but uninformed) and tail-based sampling (the Collector decides after seeing the whole trace, informed but stateful).

Metrics: counters, gauges, histograms

OpenTelemetry metrics are aggregated numeric values. Four instrument shapes:

  • Counter — monotonically increasing values. Used for rates (requests per second, bytes sent). Example: orders_total.
  • UpDownCounter — values that go up and down. Used for resource counts (active connections, queue depth).
  • Gauge — the current observed value. Used for instantaneous measurements (CPU temperature, free memory).
  • Histogram — values bucketed into fixed ranges so the backend can compute percentiles. Used for latency, request size, payload size. Example: checkout_latency_ms.
  • Exponential Histogram — histogram with auto-scaled buckets. Better for wide-range distributions where you do not know the bucket layout in advance.

Every metric measurement carries attribute dimensions — key/value pairs that produce separate time series. checkout_latency_ms{plan="team", region="eu-west-1"} is one series; checkout_latency_ms{plan="free", region="eu-west-1"} is another. Avoid high-cardinality attributes (request IDs, user IDs, full URLs) in metrics — they explode the series count and the cost.

Aggregation temporality matters: Delta reports the change since the last export; Cumulative reports the total since the start. SDKs default to Cumulative for Prometheus-style backends and Delta for stateless backends. Telemtra accepts both.

Logs

OpenTelemetry treats logs as structured records, not free-form text. Each log record carries:

  • severity_number (1–24) and severity_text (DEBUG, INFO, WARN, ERROR, FATAL).
  • body — a message string or structured value.
  • Attributes — structured key/value pairs (e.g. user.id=42, order.id=ord_xyz).
  • timestamp — nanosecond-precision event time.
  • trace_id and span_id — auto-attached when the log is emitted inside an active span. This is what links logs to their parent trace.
  • resource — the producing service's resource attributes (service.name, host.name, deployment.environment).

You usually do not write OpenTelemetry log calls directly. Instead, the standard library logger for your language gets bridged: Python logging via the OTel logging handler, Node.js pino/winston/bunyan via the matching instrumentation, .NET ILogger via builder.Logging.AddOpenTelemetry, Go slog via the otelslog bridge. Your existing log statements become OTLP log records with trace context attached.

Resource attributes

A Resource describes the producer of telemetry — the service, host, or container the signals come from. Resource attributes apply to every signal a producer emits, set once at SDK startup, and are how backends group, filter, and scope telemetry.

Standard resource attributes (see the semantic conventions):

  • service.name — the logical service identifier. The single most important attribute — this is what becomes the service selector in your backend.
  • deployment.environment — production, staging, dev. Lets you scope dashboards and alerts by environment.
  • host.name / host.id — the host the process runs on.
  • k8s.pod.name / k8s.namespace.name / k8s.cluster.name — Kubernetes identifiers.
  • cloud.provider / cloud.region / cloud.availability_zone — cloud placement.

Set these via OTEL_RESOURCE_ATTRIBUTES=key1=value1,key2=value2 at SDK startup, or use the language SDK's resource builder. Do not change them per request — resource attributes are about the producer, not the operation.

Context propagation

Context propagation is what makes traces work across services. When service A calls service B, the OpenTelemetry SDK injects the active trace_id and span_id into outbound request headers; service B's SDK reads them and continues the trace.

The default propagator is W3C tracecontext (the traceparent and tracestate HTTP headers) plus W3C baggage (the baggage header for arbitrary key/value pairs that should flow downstream). Every OpenTelemetry SDK uses these by default, and Telemtra and every other OTel-compatible backend expects them.

For non-HTTP propagation (Kafka, RabbitMQ, gRPC, AWS SDK), the matching auto-instrumentation handles serialization into and out of the carrier — you do not need to write code for it as long as the auto-instrumentation is registered.

Cross-signal correlation

OpenTelemetry was designed so the three signals correlate without manual work:

  • Logs ↔ traces. Logs emitted inside an active span carry the trace_id and span_id, so a backend can show all log lines for a trace and jump from a log to its trace.
  • Metrics ↔ traces. Histogram metrics can carry exemplars — trace_id pointers to representative samples. A slow p99 datapoint can link to an example trace that caused it.
  • Traces ↔ resource. Every span carries the producing service's resource attributes, so spans are automatically grouped by service.name, deployment.environment, and host.

In Telemtra this shows up as one-click jumps: a trace links to its log lines; a slow histogram cell opens the matching trace; the Service Map is drawn entirely from trace data with no separate configuration.

Semantic conventions

OpenTelemetry defines stable semantic conventions for common attribute names so the same kind of data looks the same across languages and frameworks. Examples:

  • HTTP: http.request.method, http.response.status_code, url.path, server.address.
  • Database: db.system, db.statement, db.name, server.address, server.port.
  • Messaging: messaging.system, messaging.destination.name, messaging.operation.
  • RPC: rpc.system, rpc.service, rpc.method.

Following the conventions makes your traces interoperable with any backend's built-in dashboards, filters, and alerts. If you use the auto-instrumentation libraries, semantic conventions are applied for you.

OpenTelemetry signals FAQ

What are the three OpenTelemetry signals?

Logs, traces, and metrics. Each captures a different shape of telemetry: traces describe causal chains of operations across services, metrics describe aggregated numeric values over time, and logs describe individual events with structured attributes.

Can OpenTelemetry signals be correlated with each other?

Yes. Logs emitted inside an active span carry the trace_id and span_id automatically, so you can jump from a slow trace to its log lines. Exemplars attached to histogram metrics carry trace_ids too, letting you jump from a slow p99 datapoint to a representative trace.

What is a span in OpenTelemetry?

A span represents a single operation inside a service: an HTTP request handler, a database query, a function call. Spans carry a name, start and end timestamps, attributes, events, status, and a link to their parent span. A trace is the directed graph of spans for one logical operation across services.

What is the difference between OpenTelemetry counters, gauges, and histograms?

Counters monotonically increase (e.g. orders_total). Gauges report the current value (e.g. queue_depth). Histograms bucket values to compute percentiles and averages (e.g. checkout_latency_ms). Exponential histograms are a newer variant with auto-scaled buckets, useful for wide-range latency distributions.

What are resource attributes?

Resource attributes describe the producer of telemetry: service.name, deployment.environment, host.name, k8s.pod.name. They apply to every signal a producer emits and are how backends group telemetry by service, environment, and host. Set them once at SDK startup, not per signal.

Does OpenTelemetry replace structured logging libraries?

Not entirely. OpenTelemetry provides a logging API and an OTLP log exporter, but most code still uses the language's standard logger (Python logging, Node pino/winston, .NET ILogger, Go slog). Bridges send those logs through OpenTelemetry so you do not have to rewrite log statements.

Further reading