> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Generate synthetic OpenTelemetry data with telemetrygen

> Use telemetrygen to send diverse synthetic logs, traces and metrics to fully managed ClickHouse Observability

> [tab] Fully managed
>
> [Beta offering](https://clickhouse.com/docs/reference/settings/beta-and-experimental-features.md#beta-features)
>
> [`telemetrygen`](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/cmd/telemetrygen) is the OpenTelemetry Collector Contrib data generator. It emits synthetic OTLP logs, traces and metrics, and exposes flags that let you shape the data: multiple services, log severities, span statuses and child spans, and different metric types. Use it to send test data to fully managed ClickHouse Observability and explore the results in Search and Chart Explorer.
>
> **1. Prerequisites**
>
> You need an existing fully managed ClickHouse Observability service and network access to its managed telemetry endpoint. See the [fully managed Getting Started guide](https://clickhouse.com/docs/clickstack/observability/getting-started.md).
>
> **2. Install telemetrygen**
>
> With Docker installed and running, define a wrapper to run `telemetrygen` from its official container image:
>
> ```shell theme={null}
> telemetrygen() {
>   docker run --rm \
>     ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest "$@"
> }
> ```
>
> Or install the binary with Go:
>
> ```shell theme={null}
> go install github.com/open-telemetry/opentelemetry-collector-contrib/cmd/telemetrygen@latest
> ```
>
> **3. Set environment variables**
>
> Open your ClickHouse Observability service and go to **Team Settings → Managed Telemetry**. Copy the **OTLP HTTP endpoint** and **API key**.
>
> ![Managed Telemetry in Team Settings showing the masked OTLP HTTP endpoint and API key](https://mintcdn.com/private-7c7dfe99/Zk1feNn6fCQBpold/images/clickstack/getting-started/observability-managed-telemetry.png?fit=max\&auto=format\&n=Zk1feNn6fCQBpold\&q=85\&s=e63a2ac2e6ab996d3fc360ebe0f487a5)
>
> Set the endpoint to its host and port, removing the `https://` prefix. For example, `https://YOUR_OTEL_ENDPOINT:4318` becomes `YOUR_OTEL_ENDPOINT:4318`. Do not append a signal path such as `/v1/logs`.
>
> ```shell theme={null}
> export OTEL_ENDPOINT='YOUR_OTEL_ENDPOINT:4318'
> printf "API key: "
> read -r -s OTEL_API_KEY
> printf "\n"
> export OTEL_API_KEY
> ```
>
> Define a small `tg` helper so each command only specifies what varies (service, severity, status, attributes):
>
> ```shell theme={null}
> tg() { local signal=$1; shift; telemetrygen "$signal" \
>   --otlp-endpoint "${OTEL_ENDPOINT}" --otlp-http \
>   --otlp-header "authorization=\"Bearer ${OTEL_API_KEY}\"" \
>   --rate 5 --duration 30s "$@"; }
> ```
>
> The helper uses OTLP HTTP over TLS with certificate verification. Omit `--otlp-insecure` and `--otlp-insecure-skip-verify`. Each command runs for 30 seconds and authenticates with your managed telemetry API key.
>
> **4. Generate logs**
>
> Send informational, warning, and error logs from three services:
>
> ```shell theme={null}
> tg logs --service frontend --severity-text Info  --severity-number 9  --body "GET /api/products 200" \
>   --otlp-attributes 'deployment.environment="production"' \
>   --telemetry-attributes 'http.method="GET"' --telemetry-attributes 'http.status_code="200"'
> tg logs --service checkout --severity-text Warn  --severity-number 13 --body "retrying payment authorization" \
>   --otlp-attributes 'deployment.environment="production"' \
>   --telemetry-attributes 'http.method="POST"'
> tg logs --service payment  --severity-text Error --severity-number 17 --body "payment gateway timeout" \
>   --otlp-attributes 'deployment.environment="production"' \
>   --telemetry-attributes 'http.status_code="500"'
> ```
>
> The most useful log flags:
>
> * `--service` sets `service.name` so events are attributable to a service.
> * `--severity-text` and `--severity-number` set the level (`severity-number` ranges from 1 to 24).
> * `--body` sets the log message.
> * `--otlp-attributes` sets resource-level attributes (`key="value"`, `key=true`, or `key=<integer>`).
> * `--telemetry-attributes` sets per-record attributes.
>
> **5. Generate traces**
>
> Send multi-span traces with successful and error statuses from several services. Each command generates independent traces; these examples do not create calls between services:
>
> ```shell theme={null}
> # Healthy services: the bulk of the traffic, all spans Ok
> for svc in frontend checkout cart; do
>   tg traces --service "$svc" --child-spans 3 --span-duration 80ms --status-code Ok \
>     --otlp-attributes 'deployment.environment="production"' \
>     --telemetry-attributes "http.route=\"/$svc\""
> done
>
> # A service with slower spans and errors
> tg traces --service payment --child-spans 3 --span-duration 450ms --span-links 1 --status-code Error \
>   --otlp-attributes 'deployment.environment="production"' \
>   --telemetry-attributes 'http.route="/charge"'
> ```
>
> The most useful trace flags:
>
> * `--child-spans` generates that many child spans per trace, giving each trace real depth.
> * `--span-duration` sets how long each span lasts (for example `120ms`, `2s`).
> * `--status-code` is one of `Unset`, `Error`, `Ok` (or `0`, `1`, `2`). Use `Error` to exercise error views.
> * `--span-links` adds links between spans.
> * `--workers` runs several generators in parallel for a higher, more varied volume.
>
> **6. Generate metrics**
>
> Send a sum, a gauge, and a histogram. These are synthetic values, not measurements of your system. Each command stops automatically after 30 seconds:
>
> ```shell theme={null}
> tg metrics --service frontend --metric-type Sum       --otlp-metric-name http.server.requests --aggregation-temporality cumulative
> tg metrics --service frontend --metric-type Gauge     --otlp-metric-name system.memory.usage
> tg metrics --service payment  --metric-type Histogram --otlp-metric-name http.server.duration
> ```
>
> `--metric-type` accepts `Gauge`, `Sum`, `Histogram`, or `ExponentialHistogram`. `--otlp-metric-name` names the series so you can find it in the UI, and `--aggregation-temporality` is `delta` or `cumulative`.
>
> **7. Verify in ClickHouse Observability**
>
> Open your ClickHouse Observability service. In the `Search` view, set the time range to `Last 15 minutes` and switch the source between `Logs` and `Traces`. Filter on `ServiceName` to see the `frontend`, `checkout`, `cart`, and `payment` services, and on `SeverityText` to find the warning and error log lines. Open a `payment` trace to see the child spans and the error status. Open the `Chart Explorer`, select `Metrics`, and chart one of the metric names you set above (for example `http.server.requests`) to verify metrics ingestion.

> [tab] Self-managed
>
> [`telemetrygen`](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/cmd/telemetrygen) is the OpenTelemetry Collector Contrib data generator. It emits synthetic OTLP logs, traces and metrics, and exposes flags that let you shape the data: multiple services, log severities, span statuses and child spans, and different metric types. Use it to confirm that a ClickStack OpenTelemetry collector is accepting data and that varied, realistic events surface in the observability UI.
>
> This guide assumes the collector is already running with OTLP endpoints on `4317` (gRPC) and `4318` (HTTP).
>
> **1. Prerequisites**
>
> This guide assumes you have completed the [Getting Started Guide for ClickHouse Observability — Self-managed](https://clickhouse.com/docs/clickstack/self-configured/getting-started/managed.md) and have an OpenTelemetry collector running with the OTLP gRPC (`4317`) and HTTP (`4318`) endpoints reachable from the machine you run `telemetrygen` on. If you [secured the collector](https://clickhouse.com/docs/clickstack/self-configured/ingesting-data/collector.md#securing-the-collector-self-configured) with an `OTLP_AUTH_TOKEN`, keep that value handy.
>
> **2. Install telemetrygen**
>
> Run `telemetrygen` from its Docker image (no install required). Define a small wrapper so the commands below stay readable; `--add-host` lets the container reach a collector listening on the host:
>
> ```shell theme={null}
> telemetrygen() {
>   docker run --rm --add-host=host.docker.internal:host-gateway \
>     ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest "$@"
> }
> export OTEL_ENDPOINT=host.docker.internal:4317
> ```
>
> Or install the binary with Go and target `localhost` instead:
>
> ```shell theme={null}
> go install github.com/open-telemetry/opentelemetry-collector-contrib/cmd/telemetrygen@latest
> export OTEL_ENDPOINT=localhost:4317
> ```
>
> **3. Set environment variables**
>
> Export the auth token if the collector is secured:
>
> ```shell theme={null}
> export OTLP_AUTH_TOKEN=<your_otlp_auth_token>
> ```
>
> > [!NOTE]
> >
> > **Unsecured collector**
> >
> > The ClickStack OpenTelemetry collector is unauthenticated by default. If you haven't followed [Securing the collector](https://clickhouse.com/docs/clickstack/self-configured/ingesting-data/collector.md#securing-the-collector-self-configured) to set an `OTLP_AUTH_TOKEN`, drop the `--otlp-header` line from the helper below.
>
> Define a small `tg` helper so each command only specifies what varies (service, severity, status, attributes):
>
> ```shell theme={null}
> tg() { local signal=$1; shift; telemetrygen "$signal" \
>   --otlp-endpoint ${OTEL_ENDPOINT} --otlp-insecure \
>   --otlp-header "authorization=\"${OTLP_AUTH_TOKEN}\"" \
>   --rate 5 --duration 30s "$@"; }
> ```
>
> **4. Generate logs**
>
> Send logs as a realistic mix of severities across services, mostly informational with a warning and an error rather than one uniform stream:
>
> ```shell theme={null}
> tg logs --service frontend --severity-text Info  --severity-number 9  --body "GET /api/products 200" \
>   --otlp-attributes 'deployment.environment="production"' \
>   --telemetry-attributes 'http.method="GET"' --telemetry-attributes 'http.status_code="200"'
> tg logs --service checkout --severity-text Warn  --severity-number 13 --body "retrying payment authorization" \
>   --otlp-attributes 'deployment.environment="production"' \
>   --telemetry-attributes 'http.method="POST"'
> tg logs --service payment  --severity-text Error --severity-number 17 --body "payment gateway timeout" \
>   --otlp-attributes 'deployment.environment="production"' \
>   --telemetry-attributes 'http.status_code="500"'
> ```
>
> The most useful log flags:
>
> * `--service` sets `service.name` so events are attributable to a service.
> * `--severity-text` and `--severity-number` set the level (`severity-number` ranges from 1 to 24).
> * `--body` sets the log message.
> * `--otlp-attributes` sets resource-level attributes (`key="value"`, `key=true`, or `key=<integer>`).
> * `--telemetry-attributes` sets per-record attributes.
>
> **5. Generate traces**
>
> Send multi-span traces from several healthy services plus one failing dependency. This gives the Service Map a realistic shape, mostly healthy with one erroring service, and populates the error views:
>
> ```shell theme={null}
> # Healthy services: the bulk of the traffic, all spans Ok
> for svc in frontend checkout cart; do
>   tg traces --service "$svc" --child-spans 3 --span-duration 80ms --status-code Ok \
>     --otlp-attributes 'deployment.environment="production"' \
>     --telemetry-attributes "http.route=\"/$svc\""
> done
>
> # One slow dependency returning errors
> tg traces --service payment --child-spans 3 --span-duration 450ms --span-links 1 --status-code Error \
>   --otlp-attributes 'deployment.environment="production"' \
>   --telemetry-attributes 'http.route="/charge"'
> ```
>
> The most useful trace flags:
>
> * `--child-spans` generates that many child spans per trace, giving each trace real depth.
> * `--span-duration` sets how long each span lasts (for example `120ms`, `2s`).
> * `--status-code` is one of `Unset`, `Error`, `Ok` (or `0`, `1`, `2`). Use `Error` to exercise error views.
> * `--span-links` adds links between spans.
> * `--workers` runs several generators in parallel for a higher, more varied volume.
>
> **6. Generate metrics**
>
> Send the three common metric types so dashboards have counters, gauges, and a distribution. Unlike some generators, `telemetrygen` honors `--duration` for metrics, so no manual stop is needed:
>
> ```shell theme={null}
> tg metrics --service frontend --metric-type Sum       --otlp-metric-name http.server.requests --aggregation-temporality cumulative
> tg metrics --service frontend --metric-type Gauge     --otlp-metric-name system.memory.usage
> tg metrics --service payment  --metric-type Histogram --otlp-metric-name http.server.duration
> ```
>
> `--metric-type` accepts `Gauge`, `Sum`, `Histogram`, or `ExponentialHistogram`. `--otlp-metric-name` names the series so you can find it in the UI, and `--aggregation-temporality` is `delta` or `cumulative`.
>
> **7. Verify in the observability UI**
>
> Open the observability UI from the ClickHouse Cloud console. In the `Search` view, set the time range to `Last 15 minutes` and switch the source between `Logs` and `Traces`. Filter on `ServiceName` to see the `frontend`, `checkout`, `cart`, and `payment` services, and on `SeverityText` to find the warning and error log lines. Open a `payment` trace to see the child spans and the error status. Open the `Chart Explorer`, select `Metrics`, and chart one of the metric names you set above (for example `http.server.requests`) to verify metrics ingestion.
