--- title: OpenTelemetry export description: Send query telemetry to an OpenTelemetry collector instead of ClickHouse --- pg_stat_ch can export query telemetry as OpenTelemetry logs and metrics instead of inserting directly into ClickHouse. This lets you route data through your existing observability pipeline (Grafana, Datadog, Honeycomb, etc.) without running a separate ClickHouse instance. ## Enable OpenTelemetry mode Set these parameters in `postgresql.conf` and restart PostgreSQL: ```ini pg_stat_ch.use_otel = on pg_stat_ch.otel_endpoint = 'localhost:4317' ``` When `use_otel` is enabled, the ClickHouse connection parameters are ignored. The background worker sends events to the OTel collector via gRPC. ## How it works The OTel exporter maps pg_stat_ch events to OpenTelemetry semantic conventions: - **Logs**: Each query execution becomes an OTel log record with attributes following the [database semantic conventions](https://opentelemetry.io/docs/specs/semconv/database/) (`db.name`, `db.user`, `db.operation.name`, `db.statement`). - **Metrics**: Query duration is exported as a histogram metric at a configurable interval, allowing you to view latency distributions in your metrics backend. The exporter uses a batch log processor internally: events are buffered in a queue and flushed in batches to reduce gRPC overhead. ## Configuration All OTel-specific parameters require a PostgreSQL restart. | Parameter | Default | Description | |---|---|---| | `pg_stat_ch.otel_endpoint` | `localhost:4317` | OTel collector gRPC endpoint (`host:port`) | | `pg_stat_ch.otel_log_queue_size` | `65536` | Max log records buffered before dropping | | `pg_stat_ch.otel_log_batch_size` | `8192` | Records per gRPC export call | | `pg_stat_ch.otel_log_max_bytes` | `3145728` (3 MiB) | Max gRPC message size | | `pg_stat_ch.otel_log_delay_ms` | `100` | Delay between batch exports | | `pg_stat_ch.otel_metric_interval_ms` | `5000` | Metric histogram export interval | See the [configuration reference](/reference/configuration#opentelemetry) for details on each parameter. ## Example: OTel Collector to ClickHouse You can use the OpenTelemetry Collector as a middle layer between pg_stat_ch and ClickHouse. This is useful when you want to fan out data to multiple backends or apply transformations. ```yaml # otel-collector-config.yaml receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 exporters: clickhouse: endpoint: tcp://clickhouse:9000 database: pg_stat_ch otlphttp: endpoint: https://your-observability-platform.com service: pipelines: logs: receivers: [otlp] exporters: [clickhouse, otlphttp] metrics: receivers: [otlp] exporters: [otlphttp] ``` ## Example: Grafana with Tempo/Loki Route pg_stat_ch logs to Loki and metrics to Prometheus/Mimir for Grafana dashboards: ```yaml exporters: loki: endpoint: http://loki:3100/loki/api/v1/push prometheusremotewrite: endpoint: http://mimir:9009/api/v1/push service: pipelines: logs: receivers: [otlp] exporters: [loki] metrics: receivers: [otlp] exporters: [prometheusremotewrite] ``` ## Verify data is flowing Check export health the same way as with ClickHouse: ```sql SELECT exported_events, send_failures, last_error_text, queue_usage_pct FROM pg_stat_ch_stats(); ``` If `send_failures` is increasing, check: 1. The OTel collector is running and reachable at the configured endpoint 2. The collector's gRPC receiver is listening on port 4317 3. PostgreSQL logs for connection error details