> ## 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.

# Local logs & metrics

> Collect local logs and system metrics with ClickHouse Observability

Collect local logs and system metrics and send them to **ClickHouse Observability** for visualization and analysis.

This example uses Docker on Linux or Docker Desktop on macOS. Before you begin, install and start Docker and create a ClickHouse Observability service using the [fully managed getting started guide](https://clickhouse.com/docs/clickstack/observability/getting-started.md) or the [self-managed getting started guide](https://clickhouse.com/docs/clickstack/self-configured/getting-started/managed.md).

## Collect local data

Choose your deployment below to configure and start the collector. After setup, both deployments use the same exploration steps.

> [tab] Fully managed
>
> [Beta offering](https://clickhouse.com/docs/reference/settings/beta-and-experimental-features.md#beta-features)
>
> In your ClickHouse Observability service, open **Team Settings → Data** and copy the OTLP HTTP endpoint and API key.
>
> **1. Create a custom OpenTelemetry configuration**
>
> Create a `custom-local-config.yaml` file with the following content:
>
> ```yaml theme={null}
> receivers:
>   file_log:
>     include:
>       - /host/var/log/**/*.log
>       - /host/var/log/syslog
>       - /host/var/log/messages
>     start_at: end
>     resource:
>       service.name: system-logs
>
>   host_metrics:
>     root_path: ${env:HOST_METRICS_ROOT_PATH}
>     collection_interval: 30s
>     scrapers:
>       cpu:
>         metrics:
>           system.cpu.utilization:
>             enabled: true
>       memory:
>         metrics:
>           system.memory.utilization:
>             enabled: true
>       filesystem:
>       paging:
>       disk:
>       load:
>       network:
>
> processors:
>   memory_limiter:
>     check_interval: 1s
>     limit_mib: 256
>     spike_limit_mib: 64
>   resource:
>     attributes:
>       - key: host.name
>         value: ${env:HOST_NAME}
>         action: upsert
>   batch:
>     timeout: 5s
>     send_batch_size: 1024
>
> exporters:
>   otlp_http:
>     endpoint: ${env:OTEL_EXPORTER_OTLP_ENDPOINT}
>     headers:
>       authorization: "Bearer ${env:OTEL_EXPORTER_OTLP_API_KEY}"
>
> service:
>   pipelines:
>     logs:
>       receivers: [file_log]
>       processors: [memory_limiter, resource, batch]
>       exporters: [otlp_http]
>     metrics:
>       receivers: [host_metrics]
>       processors: [memory_limiter, resource, batch]
>       exporters: [otlp_http]
> ```
>
> The `file_log` receiver tails local log files, and the `host_metrics` receiver collects system metrics. Both pipelines send data to your managed telemetry endpoint over HTTPS.
>
> > [!NOTE]
> >
> > This example reads new log entries only (`start_at: end`). It does not parse timestamps from the log body. Add a timestamp parser to the file receiver if you need to preserve the original event time. Use `start_at: beginning` to also ingest existing entries in newly discovered files.
>
> For more details on the OpenTelemetry (OTel) configuration structure, we recommend [the official guide](https://opentelemetry.io/docs/collector/configuration/).
>
> **2. Start the OpenTelemetry collector**
>
> Set the endpoint and API key copied from **Team Settings → Data**:
>
> ```shell theme={null}
> export OTEL_EXPORTER_OTLP_ENDPOINT='https://YOUR_OTEL_ENDPOINT:4318'
> printf "API key: "
> read -r -s OTEL_EXPORTER_OTLP_API_KEY
> printf "\n"
> export OTEL_EXPORTER_OTLP_API_KEY
> ```
>
> The endpoint is the base OTLP HTTP URL, without `/v1/logs` or `/v1/metrics`. The collector appends the appropriate path.
>
> > [tab] Linux
> >
> > Mount the host filesystem read-only so the collector can read host metrics and log files:
> >
> > ```shell theme={null}
> > docker run -d --name local-otel-collector \
> >   --user 0:0 \
> >   -e OTEL_EXPORTER_OTLP_ENDPOINT \
> >   -e OTEL_EXPORTER_OTLP_API_KEY \
> >   -e HOST_NAME="$(hostname)" \
> >   -e HOST_METRICS_ROOT_PATH=/hostfs \
> >   -v "$(pwd)/custom-local-config.yaml:/etc/otelcol-contrib/config.yaml:ro" \
> >   -v /:/hostfs:ro \
> >   -v /var/log:/host/var/log:ro \
> >   otel/opentelemetry-collector-contrib:0.161.0
> > ```
>
> > [tab] macOS (Docker Desktop)
> >
> > Mount the macOS log directory read-only. Metrics describe the Docker Desktop Linux VM and use a corresponding host label:
> >
> > ```shell theme={null}
> > docker run -d --name local-otel-collector \
> >   --user 0:0 \
> >   -e OTEL_EXPORTER_OTLP_ENDPOINT \
> >   -e OTEL_EXPORTER_OTLP_API_KEY \
> >   -e HOST_NAME="$(hostname)-docker-desktop" \
> >   -e HOST_METRICS_ROOT_PATH=/ \
> >   -v "$(pwd)/custom-local-config.yaml:/etc/otelcol-contrib/config.yaml:ro" \
> >   -v /private/var/log:/host/var/log:ro \
> >   otel/opentelemetry-collector-contrib:0.161.0
> > ```
> >
> > Docker Desktop must have permission to share `/private/var/log`.
>
> Check that the collector starts without configuration or export errors:
>
> ```shell theme={null}
> docker logs local-otel-collector
> ```
>
> Metrics are collected every 30 seconds. Logs appear when new entries are appended to a matching file. Keep the collector running while you explore the data in the following steps.

> [tab] Self-managed
>
> Use the connection credentials for your ClickHouse Cloud service, as described in the [self-managed getting started guide](https://clickhouse.com/docs/clickstack/self-configured/getting-started/managed.md#next-steps).
>
> **1. Create a custom OpenTelemetry configuration**
>
> Create a `custom-local-config.yaml` file with the following content:
>
> ```yaml theme={null}
> receivers:
>   file_log:
>     include:
>       - /host/var/log/**/*.log        # Linux logs from host
>       - /host/var/log/syslog
>       - /host/var/log/messages
>     start_at: beginning
>     resource:
>       service.name: "system-logs"
>
>   host_metrics:
>     root_path: ${env:HOST_METRICS_ROOT_PATH}
>     collection_interval: 1s
>     scrapers:
>       cpu:
>         metrics:
>           system.cpu.time:
>             enabled: true
>           system.cpu.utilization:
>             enabled: true
>       memory:
>         metrics:
>           system.memory.usage:
>             enabled: true
>           system.memory.utilization:
>             enabled: true
>       filesystem:
>         metrics:
>           system.filesystem.usage:
>             enabled: true
>           system.filesystem.utilization:
>             enabled: true
>       paging:
>         metrics:
>           system.paging.usage:
>             enabled: true
>           system.paging.utilization:
>             enabled: true
>           system.paging.faults:
>             enabled: true
>       disk:
>       load:
>       network:
>       processes:
>
> service:
>   pipelines:
>     logs/local:
>       receivers: [file_log]
>       processors:
>         - memory_limiter
>         - batch
>       exporters:
>         - clickhouse
>     metrics/hostmetrics:
>       receivers: [host_metrics]
>       processors:
>         - memory_limiter
>         - batch
>       exporters:
>         - clickhouse
> ```
>
> This configuration collects system logs and metrics for macOS and Linux systems, sending the results to your service. The configuration extends the ClickStack collector by adding new receivers and pipelines—you reference the existing `clickhouse` exporter and processors (`memory_limiter`, `batch`) that are already configured in the base ClickStack collector.
>
> > [!NOTE]
> >
> > **Ingestion timestamps**
> >
> > This configuration adjusts timestamps at ingest, assigning an updated time value to each event. You should ideally [preprocess or parse timestamps](https://clickhouse.com/docs/clickstack/self-configured/ingesting-data/collector.md#processing-filtering-transforming-enriching-self-configured) using OTel processors or operators in their log files to ensure accurate event time is retained.
> >
> > With this example setup, if the receiver or file processor is configured to start at the beginning of the file, all existing log entries will be assigned the same adjusted timestamp - the time of processing rather than the original event time. Any new events appended to the file will receive timestamps approximating their actual generation time.
> >
> > To avoid this behavior, you can set the start position to `end` in the receiver configuration. This ensures only new entries are ingested and timestamped near their true arrival time.
>
> For more details on the OpenTelemetry (OTel) configuration structure, we recommend [the official guide](https://opentelemetry.io/docs/collector/configuration/).
>
> **2. Start the OpenTelemetry collector**
>
> Run a standalone collector with your exported `CLICKHOUSE_ENDPOINT`, `CLICKHOUSE_USER`, and `CLICKHOUSE_PASSWORD` values:
>
> > [tab] Linux
> >
> > Mount the host filesystem read-only so the collector can read host metrics and log files:
> >
> > ```shell theme={null}
> > docker run -d --name local-otel-collector \
> >   --user 0:0 \
> >   -e CUSTOM_OTELCOL_CONFIG_FILE=/etc/otelcol-contrib/custom.config.yaml \
> >   -e CLICKHOUSE_ENDPOINT \
> >   -e CLICKHOUSE_USER \
> >   -e CLICKHOUSE_PASSWORD \
> >   -e HOST_METRICS_ROOT_PATH=/hostfs \
> >   -v "$(pwd)/custom-local-config.yaml:/etc/otelcol-contrib/custom.config.yaml:ro" \
> >   -v /:/hostfs:ro \
> >   -v /var/log:/host/var/log:ro \
> >   clickhouse/clickstack-otel-collector:latest
> > ```
>
> > [tab] macOS (Docker Desktop)
> >
> > Mount the macOS log directory read-only. Metrics describe the Docker Desktop Linux VM, not the macOS host:
> >
> > ```shell theme={null}
> > docker run -d --name local-otel-collector \
> >   --user 0:0 \
> >   -e CUSTOM_OTELCOL_CONFIG_FILE=/etc/otelcol-contrib/custom.config.yaml \
> >   -e CLICKHOUSE_ENDPOINT \
> >   -e CLICKHOUSE_USER \
> >   -e CLICKHOUSE_PASSWORD \
> >   -e HOST_METRICS_ROOT_PATH=/ \
> >   -v "$(pwd)/custom-local-config.yaml:/etc/otelcol-contrib/custom.config.yaml:ro" \
> >   -v /private/var/log:/host/var/log:ro \
> >   clickhouse/clickstack-otel-collector:latest
> > ```
> >
> > Docker Desktop must have permission to share `/private/var/log`.
>
> Check that the collector starts without configuration or export errors:
>
> ```shell theme={null}
> docker logs local-otel-collector
> ```
>
> The collector will immediately begin collecting local system logs and metrics.

## Explore your data

Keep the collector running while you explore the data. The screenshots show the same Search and Chart Explorer interface used by both deployment modes.

**1. Explore system logs**

In the ClickHouse Cloud console, select your service and open ClickHouse Observability.

Open [Search](https://clickhouse.com/docs/clickstack/observability/features/search.md) and select the **Logs** source. Choose a time range that includes when the collector was running, then filter **ServiceName** to `system-logs`.

Expand an event to inspect its attributes. The screenshot shows example data; your log messages and host attributes will differ.

![Local sample log in ClickHouse Observability, showing the log file name and host attributes](https://mintcdn.com/private-7c7dfe99/dW6bcEakZdn3a5oP/images/clickstack/observability-local-logs.png?fit=max\&auto=format\&n=dW6bcEakZdn3a5oP\&q=85\&s=06fd4d106dac4445aa172c03e337f92d)

**2. Explore system metrics**

Open **Chart Explorer** and select **Time Series** and the **Metrics** source. Choose **Maximum** as the aggregation, then select `system.memory.utilization`. Leave **Delta** unchecked.

In the **Where** field, use `Attributes.state:"used"` to show used memory. If you collect metrics from multiple hosts, also filter by the host attribute present in your data.

Select a time range that includes when the collector was running, then select **Run**. The screenshot shows example data filtered to a single host. The metric is a ratio from 0 to 1: a value of `0.62` represents 62% utilization.

![Memory utilization filtered to used memory on an example host in ClickHouse Observability](https://mintcdn.com/private-7c7dfe99/dW6bcEakZdn3a5oP/images/clickstack/observability-local-memory-utilization.png?fit=max\&auto=format\&n=dW6bcEakZdn3a5oP\&q=85\&s=2e2ecd9d6b3257e7cd2e0d239fb8885c)

To display utilization as a percentage, open **Display Settings** and choose **Percentage** from **Output format**.

![Chart Explorer Display Settings with Percentage selected as the output format](https://mintcdn.com/private-7c7dfe99/dW6bcEakZdn3a5oP/images/clickstack/observability-local-memory-display-settings.png?fit=max\&auto=format\&n=dW6bcEakZdn3a5oP\&q=85\&s=7b00f720c9cccf88b215a8f23694ef65)

Select **Apply** to update the chart.

![Memory utilization displayed as a percentage for an example host](https://mintcdn.com/private-7c7dfe99/dW6bcEakZdn3a5oP/images/clickstack/observability-local-memory-percentage.png?fit=max\&auto=format\&n=dW6bcEakZdn3a5oP\&q=85\&s=e29e47dc1691ee36b1578a0137bbee56)

## Stop collection

When you finish, stop collection and remove the container:

```shell theme={null}
docker stop local-otel-collector
docker rm local-otel-collector
```
