/var/log/, shapes each line into the OTLP wire format with a remap transform, and ships the result to Rootprint’s OTLP endpoint with a Bearer token. Records land in the index your ingest token is scoped to: otel-logs-v0_9 in this guide. Run Vector on bare metal or in Docker — pick the tab below. Vector’s opentelemetry sink is currently in beta upstream: stable enough for production logs, but worth tracking the Vector changelog for breaking changes.
Prerequisites
- A running Rootprint instance and its base URL — you’ll substitute it for
<your-rootprint>. - A Linux host. The Bare Metal tab uses
systemd; the Docker tab uses Docker Compose. - An ingest API key scoped to your target index. In Settings → API keys, click Create ingest key, give it a name, and pick the index (
otel-logs-v0_9here; see Indexes for its schema). See API keys.
- Bare Metal
- Docker
Install Vector
Install the Vector package for your platform from the official installation
page. Per-distro instructions (Debian/Ubuntu apt,
RHEL/Fedora dnf, macOS, Windows) are maintained upstream.
Write the Vector config
Save the following at
/etc/vector/vector.yaml. Replace <your-rootprint> with your Rootprint base
URL, <your-ingest-token> with the API key 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, a conservative size that
stays well within typical reverse-proxy and upstream limits even after gzip variance.Grant Vector read access to the log files
Vector runs as the Alternatively
vector user, which may not be able to read files under /var/log/.
Add vector to the group that owns them (for example adm on Debian/Ubuntu):sudo chmod a+r the log files, which loosens permissions for every user on
the host.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 Rootprint 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 Rootprint: theAuthorizationheader is missing or malformed. Confirm the value undersinks.rootprint.protocol.request.headers.Authorizationreads exactlyBearer <token>, with a single space betweenBearerand the token.403from Rootprint: the API key’s index scope does not matchotel-logs-v0_9, or the key has been deleted. Mint a fresh ingest API key forotel-logs-v0_9in Settings → API keys.413from a proxy in front of Rootprint: a single batch was too large on the wire. Rootprint itself sets no OTLP body-size limit, but a reverse proxy may. Lowersinks.rootprint.protocol.batch.max_bytes.415from Rootprint: encoding is misconfigured. Theencoding.codecvalue must beotlp; any other value sends a content type Rootprint rejects.- Vector starts cleanly but no logs appear in Rootprint:
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
- Send logs from Docker: collect every container’s stdout via the Docker daemon, rather than tailing specific files.
- Send logs from Kubernetes: run the Collector as a DaemonSet across a cluster.
- OTLP reference: endpoint URL, response codes, body limits.
- Indexes: the
otel-logs-v0_9schema, so you know what you can search. - Manage indexes: API key lifecycle and per-index permissions.
