Vector Setup

Learn how to set up Vector to forward logs to Sentry via OpenTelemetry.

You can configure Vector to forward logs to Sentry using its OpenTelemetry sink.

Before you begin, ensure you have:

  • Vector installed and running (version 0.51.0 or higher for otlp codec support)
  • A Sentry project you want to send data to

Find these in Sentry Project Settings under Client Keys (DSN) > OpenTelemetry (OTLP).

Copied
# Logs endpoint
___OTLP_LOGS_URL___

# Auth header (include in all requests)
x-sentry-auth: sentry sentry_key=___PUBLIC_KEY___

Choose your configuration based on your data source:

  • Option A: Forwarding existing OTLP data (simplest)
  • Option B: Transforming non-OTLP data (files, syslog, etc.)

If you're receiving data that's already in OTLP format (from an OpenTelemetry SDK or collector), you can forward it directly to Sentry using the otlp codec without any transformation.

vector.yaml
Copied
sources:
  otel_source:
    type: opentelemetry
    grpc:
      address: 0.0.0.0:4317
    http:
      address: 0.0.0.0:4318
    use_otlp_decoding: true

sinks:
  sentry_logs:
    inputs:
      - otel_source.logs
    type: opentelemetry
    protocol:
      type: http
      uri: ___OTLP_LOGS_URL___
      method: post
      headers:
        x-sentry-auth: "sentry sentry_key=___PUBLIC_KEY___"
      encoding:
        codec: otlp

If your logs come from non-OTLP sources (files, syslog, etc.), you need to use a remap transform with VRL (Vector Remap Language) to convert your data into the OTEL format before sending to Sentry.

The OpenTelemetry log format requires a specific structure with resourceLogs, scopeLogs, and logRecords:

Copied
{
  "resourceLogs": [
    {
      "resource": {
        "attributes": [
          {
            "key": "service.name",
            "value": { "stringValue": "your-service" }
          }
        ]
      },
      "scopeLogs": [
        {
          "scope": { "name": "scope-name" },
          "logRecords": [
            {
              "timeUnixNano": 1234567890000000000,
              "body": { "stringValue": "Your log message" },
              "severityText": "INFO",
              "attributes": []
            }
          ]
        }
      ]
    }
  ]
}

This example reads logs from a file and forwards them to Sentry.

The remap transform:

  • Converts the timestamp to nanoseconds
  • Builds the OTEL resourceLogs structure
  • Maps file metadata to attributes
  • Cleans up original fields
vector.yaml
Copied
sources:
  app_logs:
    type: file
    include:
      - /var/log/app/*.log

transforms:
  remap_to_otel:
    inputs: ["app_logs"]
    type: remap
    source: |
      # Get the current timestamp in nanoseconds
      timestamp_nanos = to_unix_timestamp!(now(), unit: "nanoseconds")

      # Build the OTEL resourceLogs structure
      .resourceLogs = [{
        "resource": {
          "attributes": [
            { "key": "source_type", "value": { "stringValue": .source_type } },
            { "key": "service.name", "value": { "stringValue": "my-application" } },
            { "key": "host.name", "value": { "stringValue": .host } }
          ]
        },
        "scopeLogs": [{
          "scope": {
            "name": "vector"
          },
          "logRecords": [{
            "timeUnixNano": timestamp_nanos,
            "body": { "stringValue": .message },
            "severityText": "INFO",
            "attributes": [
              { "key": "file", "value": { "stringValue": .file } }
            ]
          }]
        }]
      }]

      # Clean up original fields
      del(.message)
      del(.timestamp)
      del(.source_type)
      del(.host)
      del(.file)

sinks:
  sentry_logs:
    inputs: ["remap_to_otel"]
    type: opentelemetry
    protocol:
      type: http
      uri: ___OTLP_LOGS_URL___
      method: post
      headers:
        x-sentry-auth: "sentry sentry_key=___PUBLIC_KEY___"
      encoding:
        codec: otlp

For syslog data, you can map severity levels to OTEL severity.

The remap transform:

  • Maps syslog severity to OTEL severity text
  • Preserves syslog metadata as attributes
  • Handles the syslog-specific fields
vector.yaml
Copied
sources:
  syslog_input:
    type: syslog
    address: "0.0.0.0:514"
    mode: tcp

transforms:
  remap_syslog:
    inputs: ["syslog_input"]
    type: remap
    source: |
      # Map syslog severity to OTEL severity
      severity_text = if includes(["emerg", "err", "crit", "alert"], .severity) {
        "ERROR"
      } else if .severity == "warning" {
        "WARN"
      } else if .severity == "debug" {
        "DEBUG"
      } else if includes(["info", "notice"], .severity) {
        "INFO"
      } else {
        .severity
      }

      timestamp_nanos = to_unix_timestamp!(.timestamp, unit: "nanoseconds")

      .resourceLogs = [{
        "resource": {
          "attributes": [
            { "key": "source_type", "value": { "stringValue": .source_type } },
            { "key": "service.name", "value": { "stringValue": .appname } },
            { "key": "host.hostname", "value": { "stringValue": .hostname } }
          ]
        },
        "scopeLogs": [{
          "scope": {
            "name": .msgid
          },
          "logRecords": [{
            "timeUnixNano": timestamp_nanos,
            "body": { "stringValue": .message },
            "severityText": severity_text,
            "attributes": [
              { "key": "syslog.procid", "value": { "stringValue": to_string(.procid) } },
              { "key": "syslog.facility", "value": { "stringValue": .facility } },
              { "key": "syslog.version", "value": { "stringValue": to_string(.version) } }
            ]
          }]
        }]
      }]

      del(.message)
      del(.timestamp)
      del(.source_type)
      del(.severity)
      del(.appname)
      del(.hostname)
      del(.msgid)
      del(.procid)
      del(.facility)
      del(.version)

sinks:
  sentry_logs:
    inputs: ["remap_syslog"]
    type: opentelemetry
    protocol:
      type: http
      uri: ___OTLP_LOGS_URL___
      method: post
      headers:
        x-sentry-auth: "sentry sentry_key=___PUBLIC_KEY___"
      encoding:
        codec: otlp

Here are the key VRL functions you'll use when building OTEL log records:

FunctionDescriptionExample
to_unix_timestamp!()Convert timestamp to Unix timeto_unix_timestamp!(now(), unit: "nanoseconds")
to_string()Convert value to stringto_string(.procid)
includes()Check if array contains valueincludes(["error", "warn"], .level)
del()Delete a fielddel(.message)

OptionDescriptionRequired
typeMust be opentelemetryYes
inputsSource or transform IDs to receive data fromYes
protocol.typeTransport protocol (http)Yes
protocol.uriYour Sentry OTLP logs endpointYes
protocol.headersHTTP headers including authenticationYes
protocol.encoding.codecMust be otlp for OpenTelemetry encodingYes

FieldDescriptionRequired
timeUnixNanoTimestamp in nanoseconds since Unix epochYes
body.stringValueThe log message bodyYes
severityTextLog level (DEBUG, INFO, WARN, ERROR)Recommended
attributesAdditional key-value metadataOptional

  1. Check Vector version: The otlp codec requires Vector 0.51.0+. Run vector --version to verify.

  2. Check the OTEL structure: If using remap, ensure your transform creates the correct resourceLogs structure with all required nested fields.

  3. Verify timestamps: The timeUnixNano field must be a valid Unix timestamp in nanoseconds.

  4. Enable Vector debug logging: Run Vector with debug logging to see the transformed events:

    Copied
    VECTOR_LOG=debug vector --config /path/to/vector.yaml
    
  5. Validate your VRL: Use Vector's VRL playground to test your remap logic.

For more information on Vector configuration options, see the Vector documentation.

Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").