Skip to content

Send your first telemetry

Pitot accepts traces, logs and metrics over OTLP/gRPC and OTLP/HTTP on the same port as the application: 7520 by default. Both require the ingest token.

The raw ingest token is shown once, immediately after you create the first administrator. It is foi_ followed by 43 unpadded base64url characters (32 random bytes). Pitot stores only its SHA-256 digest. Existing fo_ tokens are rejected; create a token in Connect telemetry → Ingest tokens and update every collector.

An administrator can hold up to 50 active tokens, each named, at /settings/ingest (also linked from Connect telemetry in the account menu), or with POST /api/settings/ingest/tokens. Each value is shown once. To rotate without downtime, create a replacement, move the Collector to it, then revoke the old token. Revocation takes effect on the next request. Revoking the last active token stops ingest until you create another.

An automated install can accept telemetry as soon as it starts, before any administrator exists. Generate a token in the same format and pass it as PITOT_INGEST_TOKEN, or PITOT_INGEST_TOKEN_FILE for a mounted secret:

Terminal window
printf 'foi_%s\n' "$(openssl rand -base64 32 | tr '+/' '-_' | tr -d '=')"

Pitot stores the token’s hash at startup under the name configuration only when no token has ever existed, and setup then shows no token. Any token that has existed, including a revoked one, makes the setting ignored, so a restart cannot bring back a token you revoked and changing the setting replaces nothing. A value in any other format fails startup with an error naming the setting.

Send it as a bearer token; this is the only accepted ingest credential form:

Authorization: Bearer foi_<token>

Ingest is available after administrator setup, or as soon as Pitot starts when PITOT_INGEST_TOKEN set the token. Exporters require an active ingest token; browser sessions and MCP OAuth tokens cannot authorize exports.

Terminal window
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:7520
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_HEADERS="authorization=Bearer%20foi_<token>"
export OTEL_SERVICE_NAME=checkout
export OTEL_RESOURCE_ATTRIBUTES=service.namespace=storefront

For OTLP/HTTP, keep the same endpoint and set OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf. Use https:// when Pitot or a proxy terminates TLS. A general OTLP endpoint is a base URL; signal-specific variables such as OTEL_EXPORTER_OTLP_TRACES_ENDPOINT must include their path (/v1/traces, /v1/metrics or /v1/logs).

OTLP/HTTP requires Content-Type: application/x-protobuf. JSON payloads return HTTP 415 after authentication. The JavaScript *-otlp-http exporter packages send JSON. Choose @opentelemetry/exporter-trace-otlp-proto for traces and the matching *-otlp-proto packages for metrics and logs. Setting a protocol variable does not change an explicitly constructed JSON exporter.

Use the endpoint and bearer header above for each SDK. Select the transport supported by the exporter you install.

SDKProtocol and environment notes
JavaScriptUse the *-otlp-proto packages for HTTP protobuf, or *-otlp-grpc in Node.js. For SDK-managed exporter selection, set OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf.
PythonInstall the HTTP protobuf or gRPC exporter. For automatic instrumentation, select http/protobuf or grpc with OTEL_EXPORTER_OTLP_PROTOCOL.
GoImport otlptracehttp for protobuf HTTP or otlptracegrpc for gRPC, and the matching metric/log packages. These read endpoint and header environment variables; the imported package selects the transport.
JavaWith SDK autoconfiguration or the Java agent, set OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf or grpc, plus endpoint and headers.
.NETUse the OTLP exporter with HttpProtobuf or Grpc. Configure endpoint and headers through exporter options or supported OTLP environment variables.
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
exporters:
otlp/pitot:
endpoint: "https://pitot.example.com:443"
headers:
Authorization: "Bearer ${env:INGEST_TOKEN}"
service:
pipelines:
traces:
receivers: [otlp]
exporters: [otlp/pitot]
logs:
receivers: [otlp]
exporters: [otlp/pitot]
metrics:
receivers: [otlp]
exporters: [otlp/pitot]

The gRPC exporter requires an explicit port. Use https:// for TLS and :443 for a proxy serving standard HTTPS.

If nothing in front of Pitot terminates TLS (a local instance, or one on a private network), the endpoint is http://pitot.example.com:7520 and the exporter needs tls: { insecure: true } under otlp/pitot, or it will fail to connect. Connect telemetry in the application generates this block with your own endpoint already in it, and includes that line when it applies.

SDKs can export directly to Pitot. Use a Collector for sampling, enrichment or forwarding to several backends.

The default System overview dashboard combines application traces with Collector metrics. Use the Collector contrib distribution for hostmetrics, docker_stats and httpcheck. Run one Collector on each observed host, with access to the host filesystem and Docker socket:

receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
hostmetrics:
collection_interval: 30s
scrapers:
cpu: {}
memory: {}
filesystem: {}
docker_stats:
endpoint: unix:///var/run/docker.sock
collection_interval: 30s
httpcheck:
collection_interval: 30s
targets:
- endpoint: https://app.example.com/health
method: GET
processors:
resourcedetection:
detectors: [system]
system:
hostname_sources: [os]
resource:
attributes:
- key: service.namespace
value: storefront
action: upsert
batch: {}
exporters:
otlp/pitot:
endpoint: https://pitot.example.com:443
headers:
Authorization: "Bearer ${env:INGEST_TOKEN}"
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp/pitot]
logs:
receivers: [otlp]
processors: [batch]
exporters: [otlp/pitot]
metrics:
receivers: [otlp, hostmetrics, docker_stats, httpcheck]
processors: [resourcedetection, resource, batch]
exporters: [otlp/pitot]

Set INGEST_TOKEN in the Collector environment. Use your Pitot address and namespace, and the plaintext exporter settings above when TLS is absent. If the Collector runs in a container, mount the host filesystem read-only and set hostmetrics.root_path to that mount; give the Collector the observed host’s host.name, rather than its own container hostname. Mount the Docker socket only where container metrics are needed.

Run httpcheck from a second machine outside the observed stack. On that Collector, reuse the exporter and resource processors, but use a metrics pipeline with receivers: [httpcheck]. Its host.name identifies where the check ran. A check on the application host cannot see every DNS, CDN or proxy failure that outside visitors encounter; the dashboard warns when all checks run on hosts that also run observed services.

  • Is it reachable? uses httpcheck.status and httpcheck.duration, with the target’s http.url and the reporting Collector’s host.name.
  • Is anything failing or slow? uses application spans. Client spans with peer.service or server.address identify uninstrumented dependencies; error status makes their failures visible.
  • Is anything running out? uses host CPU counters, memory and filesystem usage by state and mountpoint, plus container CPU and memory usage and limits. Capacity warns at 80% and is bad at 90%.
  • What changed? uses service.version on application resources, along with runtime and SDK attributes. Send a new version when deploying a service.

After two reporting intervals, an endpoint with no result shows no recent result, and a host or container shows not reporting, both in the bad state. A receiver that has never sent data shows an empty panel. If the machine running Pitot fails, Pitot cannot report that failure on its own page: monitor Pitot itself from outside that machine.

Each user owns a saved copy of System overview. Changes to the default specification apply when a copy is created; saved dashboards retain their spec. See dashboard defaults for edits.

Pitot reads service.namespace from each OTLP resource, falling back to PITOT_DEFAULT_NAMESPACE (default) when it is absent. Namespaces let one instance hold several services’ telemetry without them running together.

A query with no namespace filter spans all namespaces. Add a namespace filter to narrow the result.

See namespace access limits.

PITOT_ADDR controls the shared listener. The native default is 127.0.0.1:7520; the image sets :7520. Set PITOT_ADDR=:7520 for remote clients, or publish 7520:7520 in Docker. There are no separate ingest address settings.

When using a reverse proxy, enable HTTP/2 to the backend for gRPC. Plaintext Pitot accepts prior-knowledge HTTP/2 (h2c); a TLS listener negotiates HTTP/2 through ALPN. HTTP/1.1 forwarding works for OTLP/HTTP, but cannot carry gRPC. See terminate TLS.

With an AI provider configured, open chat and ask a question such as “Why is checkout slower in the last hour?” The agent queries telemetry and displays its evidence in interactive views. Ask it to build a dashboard to save a view for repeated use.

To use your own agent, connect over MCP. MCP does not require Pitot’s built-in AI provider.