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

# Ingesting with Vector

> Send data to self-managed ClickHouse Observability using the Vector ClickHouse sink.

> [tab] Self-managed
>
> > [!NOTE]
> >
> > This guide applies only to **self-managed ClickHouse Observability**. Vector's ClickHouse sink writes directly to tables that you manage. Fully managed ClickHouse Observability requires OTLP ingestion; see [Ingesting with OpenTelemetry](https://clickhouse.com/docs/clickstack/observability/ingesting-data/opentelemetry.md#fully-managed) for endpoint and authentication settings.
>
> [Vector](https://vector.dev) is a high-performance, vendor-neutral observability data pipeline. It is commonly used to collect, transform, and route logs and metrics from a wide range of sources, and is especially popular for log ingestion due to its flexibility and low resource footprint.
>
> When using Vector with Self-managed ClickHouse Observability, users are responsible for defining their own schemas. These schemas may follow OpenTelemetry conventions, but they can also be entirely custom, representing user-defined event structures. In practice, Vector ingestion is most commonly used for **logs**, where users want full control over parsing and enrichment before data is written to ClickHouse.
>
> This guide focuses on onboarding data into Self-managed ClickHouse Observability using Vector. For simplicity, it doesn't cover Vector sources or pipeline configuration in depth. Instead, it focuses on configuring the **sink** that writes data into ClickHouse and ensuring the resulting schema is compatible with Self-managed ClickHouse Observability.
>
> The only strict requirement for the service is that the data includes a **timestamp column** (or equivalent time field), which can be declared when configuring the data source in the observability UI.
>
> ## Sending data with Vector
>
> The following guide assumes you have already created a Self-managed ClickHouse Observability service and recorded your service credentials. If you haven't, follow the [Getting Started](https://clickhouse.com/docs/clickstack/self-configured/getting-started/managed.md) guide for Self-managed ClickHouse Observability until prompted to configure Vector.
>
> **1. Create a database and table**
>
> Vector requires a table and schema to be defined prior to data ingestion.
>
> First create a database. This can be done via the [ClickHouse Cloud console](https://clickhouse.com/docs/products/cloud/features/sql-console-features/sql-console.md).
>
> In the example below, we use `logs`:
>
> ```sql theme={null}
> CREATE DATABASE IF NOT EXISTS logs
> ```
>
> Create a table for your data. This should match the output schema of your data. The example below assumes a classic Nginx structure. Adjust accordingly to your data, adhering to [schema best practices](https://clickhouse.com/docs/concepts/best-practices/select-data-type.md). We **strongly recommend** familiarizing yourself with the [concept of Primary keys](https://clickhouse.com/docs/concepts/core-concepts/primary-indexes.md), selecting your primary key based on the guidelines outlined [here](https://clickhouse.com/docs/clickstack/self-configured/managing/performance-tuning.md#choosing-a-primary-key).
>
> ```sql theme={null}
> CREATE TABLE logs.nginx_logs
> (
>     `time_local` DateTime,
>     `remote_addr` IPv4,
>     `remote_user` LowCardinality(String),
>     `request` String,
>     `status` UInt16,
>     `body_bytes_sent` UInt64,
>     `http_referer` String,
>     `http_user_agent` String,
>     `http_x_forwarded_for` LowCardinality(String),
>     `request_time` Float32,
>     `upstream_response_time` Float32,
>     `http_host` String
> )
> ENGINE = MergeTree
> ORDER BY (toStartOfMinute(time_local), status, remote_addr)
> ```
>
> > [!NOTE]
> >
> > **Nginx primary key**
> >
> > The primary key above assumes typical access patterns in the observability UI for Nginx logs, but may need to be adjusted depending on your workload in production environments.
>
> **2. Add ClickHouse sink to vector configuration**
>
> Modify your Vector configuration to include the ClickHouse sink, updating the `inputs` field to receive events from your existing pipelines.
>
> This configuration assumes that your upstream Vector pipeline has already **prepared the data to match the target ClickHouse schema**, meaning that fields are parsed, named correctly, and typed appropriately for insertion. See the [**Nginx example below**](#example-dataset-with-vector-self-configured) for a complete illustration of parsing and normalizing raw log lines into a schema suitable for the service.
>
> ```yaml theme={null}
> sinks:
>   clickhouse:
>     type: clickhouse
>     inputs:
>       - your_input
>     endpoint: "<CLICKHOUSE_ENDPOINT>"
>     database: logs
>     format: json_each_row
>     table: nginx_logs
>     skip_unknown_fields: true
>     auth:
>       strategy: "basic"
>       user: "default"
>       password: "<CLICKHOUSE_PASSWORD>"
> ```
>
> By default, we recommend using the **`json_each_row`** format, which encodes each event as a single JSON object per row. This is the default and recommended format for the service when ingesting JSON data, and should be preferred over alternative formats such as JSON objects encoded as strings.
>
> The ClickHouse sink also supports **Arrow stream encoding** (currently in beta). This can offer higher throughput but comes with important constraints: the database and table must be static, as the schema is fetched once at startup, and dynamic routing isn't supported. For this reason, Arrow encoding is best suited for fixed, well-defined ingestion pipelines.
>
> We recommend reviewing the available sink configuration options in the [Vector documentation](https://vector.dev/docs/reference/configuration/sinks/clickhouse):
>
> > [!NOTE]
> >
> > The example above uses the default user for Self-managed ClickHouse Observability. For production deployments, we recommend [creating a dedicated ingestion user](https://clickhouse.com/docs/clickstack/self-configured/ingesting-data/collector.md#creating-an-ingestion-user-self-configured) with appropriate permissions and limits.
>
> **3. Navigate to the observability UI**
>
> Navigate to your Self-managed ClickHouse Observability service and select "ClickStack" from the left-hand menu. If you’ve already completed the onboarding, this will launch the observability UI in a new tab, and you will be automatically authenticated. If not, you can proceed through the onboarding and select “Launch ClickStack” once you’ve selected Vector as your input source.
>
> ![Launch ClickStack for vector](https://mintcdn.com/private-7c7dfe99/y4_YksnkJMz9sseb/images/clickstack/launch-clickstack-vector.webp?fit=max\&auto=format\&n=y4_YksnkJMz9sseb\&q=85\&s=2263f97bcf1e752bbaca2fd31b2b5258)
>
> **4. Create a datasource**
>
> Create a logs data source. If no data sources exist, you will be prompted to create one on your first login. Otherwise, navigate to Team Settings and add a new data source.
>
> ![Create datasource - vector](https://mintcdn.com/private-7c7dfe99/LCIbqddLfKHZZnfk/images/clickstack/create-vector-datasource.webp?fit=max\&auto=format\&n=LCIbqddLfKHZZnfk\&q=85\&s=7feae655627fc68cc21ced5c34c04097)
>
> The configuration above assumes an Nginx-style schema with a `time_local` column used as the timestamp. This should be, where possible, the timestamp column declared in the primary key. This column is mandatory.
>
> We also recommend updating the `Default SELECT` to explicitly define which columns are returned in the logs view. If additional fields are available, such as service name, log level, or a body column, these can also be configured. The timestamp display column can also be overridden if it differs from the column used in the table's primary key and configured above.
>
> In the example above, a `Body` column doesn't exist in the data. Instead, it is defined using a SQL expression that reconstructs an Nginx log line from the available fields.
>
> For other possible options, see the [configuration reference](https://clickhouse.com/docs/clickstack/self-configured/managing/config.md).
>
> **5. Explore the data**
>
> Navigate to the logs view to explore the data and begin using the service.
>
> ![Nginx logs in the observability UI](https://mintcdn.com/private-7c7dfe99/y4_YksnkJMz9sseb/images/clickstack/nginx-logs-vector-search.webp?fit=max\&auto=format\&n=y4_YksnkJMz9sseb\&q=85\&s=6c3e6c1bf8a177a9955d2b457d10fccd)
>
> ## Example dataset with Vector
>
> For a more complete example, we use an **Nginx log file** below.
>
> The following guide assumes you have already created a Self-managed ClickHouse Observability service and recorded your service credentials. If you haven't, follow the [Getting Started](https://clickhouse.com/docs/clickstack/self-configured/getting-started/managed.md) guide for Self-managed ClickHouse Observability until prompted to configure Vector.
>
> **1. Installing Vector**
>
> Before proceeding, ensure that **Vector is installed** on the system where you plan to run your ingestion pipeline. Follow the [official Vector installation guide](https://vector.dev/docs/setup/installation/) to install a prebuilt binary or package appropriate for your environment:
>
> Once installed, verify that the `vector` binary is available on your path before continuing with the configuration steps below.
>
> This can be installed on the same instance as your ClickStack OTel collector.
>
> Follow best practices for architecture and security when [moving Vector to production](https://vector.dev/docs/setup/going-to-prod/).
>
> **2. Download the sample data**
>
> If you wish to experiment with a sample dataset, download the following example nginx sample.
>
> ```bash theme={null}
> curl -O https://datasets-documentation.s3.eu-west-3.amazonaws.com/clickstack-integrations/access.log
> ```
>
> > [!NOTE]
> >
> > This data has been collected from an Nginx instance configured to output logs in JSON format for easier parsing. For the Nginx configuration for these logs, see ["Monitoring Nginx Logs with ClickStack"](https://clickhouse.com/docs/clickstack/integration-examples/nginx-logs.md#configure-nginx).
>
> **3. Create a database and table**
>
> Vector requires a table and schema to be defined prior to data ingestion.
>
> First create a database. This can be done via the [ClickHouse Cloud console](https://clickhouse.com/docs/products/cloud/features/sql-console-features/sql-console.md).
>
> Create a database `logs`:
>
> ```sql theme={null}
> CREATE DATABASE IF NOT EXISTS logs
> ```
>
> Create a table for your data.
>
> ```sql theme={null}
> CREATE TABLE logs.nginx_logs
> (
>     `time_local` DateTime,
>     `remote_addr` IPv4,
>     `remote_user` LowCardinality(String),
>     `request` String,
>     `status` UInt16,
>     `body_bytes_sent` UInt64,
>     `http_referer` String,
>     `http_user_agent` String,
>     `http_x_forwarded_for` LowCardinality(String),
>     `request_time` Float32,
>     `upstream_response_time` Float32,
>     `http_host` String
> )
> ENGINE = MergeTree
> ORDER BY (toStartOfMinute(time_local), status, remote_addr)
> ```
>
> > [!NOTE]
> >
> > **Nginx primary key**
> >
> > The primary key above assumes typical access patterns in the observability UI for Nginx logs, but may need to be adjusted depending on your workload in production environments.
>
> **4. Copy Vector configuration**
>
> Copy the vector configuration and create a file `nginx.yaml`, setting the `CLICKHOUSE_ENDPOINT` and `CLICKHOUSE_PASSWORD`.
>
> ```yaml theme={null}
> data_dir: ./.vector-data
> sources:
>   nginx_logs:
>     type: file
>     include:
>       - access.log
>     read_from: beginning
>
> transforms:
>   decode_json:
>     type: remap
>     inputs:
>       - nginx_logs
>     source: |
>       . = parse_json!(to_string!(.message))
>       ts = parse_timestamp!(.time_local, format: "%d/%b/%Y:%H:%M:%S %z")
>       # ClickHouse-friendly DateTime format
>       .time_local = format_timestamp!(ts, format: "%F %T")
>
> sinks:
>   clickhouse:
>     type: clickhouse
>     inputs:
>       - decode_json
>     endpoint: "<CLICKHOUSE_ENDPOINT>"
>     database: logs
>     format: json_each_row
>     table: nginx_logs
>     skip_unknown_fields: true
>     auth:
>       strategy: "basic"
>       user: "default"
>       password: "<CLICKHOUSE_PASSWORD>"
> ```
>
> > [!NOTE]
> >
> > The example above uses the default user for Self-managed ClickHouse Observability. For production deployments, we recommend [creating a dedicated ingestion user](https://clickhouse.com/docs/clickstack/self-configured/ingesting-data/collector.md#creating-an-ingestion-user-self-configured) with appropriate permissions and limits.
>
> **5. Start Vector**
>
> Start Vector with the following command, creating the data directory first to record file offsets.
>
> ```bash theme={null}
> mkdir ./.vector-data
> vector --config nginx.yaml
> ```
>
> **6. Navigate to the observability UI**
>
> Navigate to your Self-managed ClickHouse Observability service and select "ClickStack" from the left-hand menu. If you’ve already completed the onboarding, this will launch the observability UI in a new tab, and you will be automatically authenticated. If not, you can proceed through the onboarding and select “Launch ClickStack” once you’ve selected Vector as your input source.
>
> ![Launch ClickStack for vector](https://mintcdn.com/private-7c7dfe99/y4_YksnkJMz9sseb/images/clickstack/launch-clickstack-vector.webp?fit=max\&auto=format\&n=y4_YksnkJMz9sseb\&q=85\&s=2263f97bcf1e752bbaca2fd31b2b5258)
>
> **7. Create a datasource**
>
> Create a logs data source. If no data sources exist, you will be prompted to create one on first login. Otherwise, navigate to Team Settings and add a new data source.
>
> ![Create datasource - vector](https://mintcdn.com/private-7c7dfe99/LCIbqddLfKHZZnfk/images/clickstack/create-vector-datasource.webp?fit=max\&auto=format\&n=LCIbqddLfKHZZnfk\&q=85\&s=7feae655627fc68cc21ced5c34c04097)
>
> The configuration assumes the Nginx schema with a `time_local` column used as the timestamp. This is the timestamp column declared in the primary key. This column is mandatory.
>
> We have also specified the default select to be `time_local, remote_addr, status, request`, which defines which columns are returned in the logs view.
>
> In the example above, a `Body` column doesn't exist in the data. Instead, it is defined as the SQL expression:
>
> ```sql theme={null}
> concat(
>   remote_addr, ' ',
>   remote_user, ' ',
>   '[', formatDateTime(time_local, '%d/%b/%Y:%H:%M:%S %z'), '] ',
>   '"', request, '" ',
>   toString(status), ' ',
>   toString(body_bytes_sent), ' ',
>   '"', http_referer, '" ',
>   '"', http_user_agent, '" ',
>   '"', http_x_forwarded_for, '" ',
>   toString(request_time), ' ',
>   toString(upstream_response_time), ' ',
>   '"', http_host, '"'
> )
> ```
>
> This reconstructs the log line from the structured fields.
>
> For other possible options, see the [configuration reference](https://clickhouse.com/docs/clickstack/self-configured/managing/config.md).
>
> **8. Explore the data**
>
> Navigate to the search view for `October 20th, 2025` to explore the data and begin using the service.
>
> ![Observability UI](https://mintcdn.com/private-7c7dfe99/y4_YksnkJMz9sseb/images/clickstack/nginx-logs-vector-search.webp?fit=max\&auto=format\&n=y4_YksnkJMz9sseb\&q=85\&s=6c3e6c1bf8a177a9955d2b457d10fccd)
