Skip to content

0007. Emit OpenTelemetry and stop there

Status: Accepted Date: 2026-09-02

Context

M2 adds observability to the service. Every organisation generating a service from PyFr already sends telemetry somewhere — Datadog, an in-house Grafana stack, a managed vendor — so the template has to decide how much of an observability platform, if any, it ships alongside the service itself.

Decision

We emit standard OTLP (OpenTelemetry Protocol — the wire format for traces, metrics and logs) traces, metrics and, optionally, logs, and bundle no observability platform of our own. The compose stack's grafana/otel-lgtm image — Grafana, Prometheus, Tempo, Loki and a collector in one container — is a local development convenience behind a compose profile, verifying that the instrumentation and the shipped dashboards actually work; it is never a deployment target.

Alternatives considered

  • Bundling an observability platform. Rejected: teams adopting PyFr already have somewhere telemetry goes. A second platform arriving with the template is not a gift — it is a second thing to operate, secure and eventually decommission.
  • Vendor-specific SDKs. Rejected: instrumenting directly against one vendor's SDK makes the telemetry unportable, which is the one problem OpenTelemetry exists to solve. A service instrumented that way can only ever be pointed at the vendor it was written for.

Consequences

The generated service's telemetry works with whatever the adopting team already runs, because OTLP is the interface, not a specific backend. Telemetry also costs nothing when unwanted: OtelSettings.enabled defaults to false, and with it off the process builds no providers, opens no socket and starts no background task — a service that wants none of this pays nothing for carrying the capability.

The cost is that PyFr cannot promise a working dashboard out of the box beyond the local o11y compose profile. The three provisioned dashboards and the burn-rate alerting rules are real and tested, but they are Grafana-shaped: a team on a different platform gets correctly-shaped OpenTelemetry data and has to build their own panels and rules against it, not a working import.

Full reasoning: spec section 7.1.