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 ingest token
Section titled “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:
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.
Configure an SDK
Section titled “Configure an SDK”export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:7520export OTEL_EXPORTER_OTLP_PROTOCOL=grpcexport OTEL_EXPORTER_OTLP_HEADERS="authorization=Bearer%20foi_<token>"export OTEL_SERVICE_NAME=checkoutexport OTEL_RESOURCE_ATTRIBUTES=service.namespace=storefrontFor 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.
Common SDKs
Section titled “Common SDKs”Use the endpoint and bearer header above for each SDK. Select the transport supported by the exporter you install.
| SDK | Protocol and environment notes |
|---|---|
| JavaScript | Use 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. |
| Python | Install the HTTP protobuf or gRPC exporter. For automatic instrumentation, select http/protobuf or grpc with OTEL_EXPORTER_OTLP_PROTOCOL. |
| Go | Import 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. |
| Java | With SDK autoconfiguration or the Java agent, set OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf or grpc, plus endpoint and headers. |
| .NET | Use the OTLP exporter with HttpProtobuf or Grpc. Configure endpoint and headers through exporter options or supported OTLP environment variables. |
Configure a Collector
Section titled “Configure a Collector”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.
Watch hosts, containers and endpoints
Section titled “Watch hosts, containers and endpoints”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.statusandhttpcheck.duration, with the target’shttp.urland the reporting Collector’shost.name. - Is anything failing or slow? uses application spans. Client spans with
peer.serviceorserver.addressidentify 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.versionon 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.
Namespaces
Section titled “Namespaces”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.
One listener
Section titled “One listener”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.
Investigate the data
Section titled “Investigate the data”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.