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
otlpcodec support) - A Sentry project you want to send data to
Find these in Sentry Project Settings under Client Keys (DSN) > OpenTelemetry (OTLP).
# 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.yamlsources:
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:
{
"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
resourceLogsstructure - Maps file metadata to attributes
- Cleans up original fields
vector.yamlsources:
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.yamlsources:
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:
| Function | Description | Example |
|---|---|---|
to_unix_timestamp!() | Convert timestamp to Unix time | to_unix_timestamp!(now(), unit: "nanoseconds") |
to_string() | Convert value to string | to_string(.procid) |
includes() | Check if array contains value | includes(["error", "warn"], .level) |
del() | Delete a field | del(.message) |
| Option | Description | Required |
|---|---|---|
type | Must be opentelemetry | Yes |
inputs | Source or transform IDs to receive data from | Yes |
protocol.type | Transport protocol (http) | Yes |
protocol.uri | Your Sentry OTLP logs endpoint | Yes |
protocol.headers | HTTP headers including authentication | Yes |
protocol.encoding.codec | Must be otlp for OpenTelemetry encoding | Yes |
| Field | Description | Required |
|---|---|---|
timeUnixNano | Timestamp in nanoseconds since Unix epoch | Yes |
body.stringValue | The log message body | Yes |
severityText | Log level (DEBUG, INFO, WARN, ERROR) | Recommended |
attributes | Additional key-value metadata | Optional |
Check Vector version: The
otlpcodec requires Vector 0.51.0+. Runvector --versionto verify.Check the OTEL structure: If using remap, ensure your transform creates the correct
resourceLogsstructure with all required nested fields.Verify timestamps: The
timeUnixNanofield must be a valid Unix timestamp in nanoseconds.Enable Vector debug logging: Run Vector with debug logging to see the transformed events:
CopiedVECTOR_LOG=debug vector --config /path/to/vector.yamlValidate your VRL: Use Vector's VRL playground to test your remap logic.
For more information on Vector configuration options, see the Vector documentation.
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").