systemd service on a Linux host: it tails files under /var/log/, shapes each line into the OTLP wire format with a remap transform, and ships the result to Logwiz’s OTLP endpoint with a Bearer token. Records land in your otel-logs-v0_9 index, the same index every OpenTelemetry SDK writes to. Vector’s opentelemetry sink is currently in beta upstream — stable enough for production logs, but worth tracking the Vector changelog for breaking changes.
Setup
Pick the target index and create an ingest token
The default index for OTLP traffic is
otel-logs-v0_9 — see Indexes for its
schema. In Administration → Tokens, click Create Token, pick otel-logs-v0_9, and
copy the token value from the new row. Tokens are scoped to one index — you cannot reuse a
token across indexes.Install Vector
On Debian and Ubuntu:On RHEL, Rocky, AlmaLinux, and Fedora:For other Linux distributions, see Vector’s installation
docs.
Write the Vector config
Save the following at
/etc/vector/vector.yaml. Replace <your-logwiz> with your Logwiz base
URL, <your-ingest-token> with the token you copied in step 1, /var/log/myapp/*.log with
the glob that matches your application’s log files, and myapp with your service name.read_from: end skips existing content on first start, so installing Vector against an
existing log file does not replay everything that was already there. Flip it to beginning
if you want a one-time backfill. batch.max_bytes is set to 8 MiB — comfortably below
Logwiz’s 10 MB OTLP body limit even after gzip variance.Restart Vector
active (running) and the most recent log lines should not
contain config-parse or sink-startup errors.Send a test log line
Create the application log directory if it doesn’t exist yet and append a single line:
What the remap does
The OTLP wire format is nested: aresourceLogs array, each entry containing a scopeLogs
array, each of those containing a logRecords array. Vector’s file source emits a flat event
with .message, .file, .host, .source_type, and .timestamp at the top level, so the
remap transform builds the nested envelope itself and then deletes the original top-level
fields — the opentelemetry sink rejects any event with stray fields outside the OTLP shape.
Field-by-field:
service.name(resource attribute) — lands in Quickwit’sservice_namecolumn. Replace the hard-codedmyappwith whatever you want shown in the Logwiz service filter.host.name(resource attribute) — populated fromget_hostname!()so it’s non-empty without any further config.body.stringValue— the raw log line. Lands inbody.messageinotel-logs-v0_9. To parse structured fields out of the line (JSON, regex), insert anotherremaptransform upstream ofto_otlpand assign the parsed fields toattributesinstead.severityTextandseverityNumber— currently hard-coded toINFO/9. Real configs should derive these from the log line; the simplest derivation is aremapthat pattern-matches on the message and overrides both fields.timeUnixNanoandobservedTimeUnixNano— both use the time Vector reads the line, not the timestamp embedded in the line itself. Use a regex or JSON parse to populatetimeUnixNanofrom your log format if the read time is too coarse for your needs.
Troubleshooting
401from Logwiz — theAuthorizationheader is missing or malformed. Confirm the value undersinks.logwiz.protocol.request.headers.Authorizationreads exactlyBearer <token>, with a single space betweenBearerand the token.403from Logwiz — the token’s index scope does not matchotel-logs-v0_9, or the token was revoked. Mint a fresh token forotel-logs-v0_9in Administration → Tokens.413from Logwiz — a single batch exceeded 10 MB on the wire. Lowersinks.logwiz.protocol.batch.max_bytes.415from Logwiz — encoding is misconfigured. Theencoding.codecvalue must beotlp; any other value sends a content type Logwiz rejects.- Vector starts cleanly but no logs appear in Logwiz —
read_from: endskipped the existing file content. Either append a new line to trigger a read, or setread_from: beginningfor a one-time replay (Vector remembers the offset across restarts after the first read). permission deniedreading/var/log/...— the Vector package installs avectoruser that owns the service. Eithersudo chmod a+rthe log files, or addvectorto the group that owns them.- Records arrive but
bodyis empty — confirm the literalbody.stringValueassignment in theto_otlpremap reads the same field thefilesource emits (default:.message). If you reordered the remap, make suredel(.message)runs after the assignment, not before.
Related
- OTLP reference — endpoint URL, response codes, body limits.
- Indexes — the
otel-logs-v0_9schema, so you know what you can search. - Manage indexes — token lifecycle and per-index permissions.
