Prerequisites
- A running Rootprint instance. Substitute its host for
<your-rootprint>. - An ingest API key scoped to
otel-logs-v0_9. Create one in Settings → API keys with Create ingest key, then substitute it for<your-ingest-api-key>. See API keys. - A Kubernetes cluster with
kubectlandhelmconfigured against it.
1
Add the OpenTelemetry Helm repo
2
Create values.yaml
Save this as
values.yaml. Replace <your-rootprint> and <your-ingest-api-key>.processorsandexcludeare replaced, not merged. List every entry you want, including the preset-injectedmemory_limiter,k8s_attributesandbatch.file_logandotlp_httpneed Collector v0.149 or newer.
3
Install the chart
exclude covers both. Otherwise Rootprint’s and Quickwit’s own logs feed back into the index.4
Send a test log line
kubectl delete pod rootprint-smoke-test.5
Verify in Rootprint
Open Logs, pick
otel-logs-v0_9 from the index selector, and search for
hello from rootprint. Allow up to a minute. resource_attributes.k8s.pod.name reads
rootprint-smoke-test.What you get in Rootprint
Thek8s.* keys are OTLP resource attributes, so query them under resource_attributes:
The
transform sets a log level only on records that arrive without one. It matches error, fatal, panic, or exception as ERROR, warn, warning, or deprecated as WARN, and everything else as INFO. DEBUG is never inferred.
Choose what to collect
logsCollection tails every pod on the node. Exclude what you don’t want before you point it at a busy cluster.
Workloads that already send OTLP
Exclude the namespaces whose services report over OTLP:filter processor after k8s_attributes and drop on resource_attributes.
Collect selectively instead
To have workloads opt in, use annotation-based discovery and drop thefile_log block. The preset collects every pod unless you set its default annotation to "false":
Multi-line logs
The preset’scontainer operator rejoins lines split by the container runtime, not multi-line output from the application. A stack trace arrives as one record per line.
Add a recombine operator. Restate the container parser too, because operators is replaced, not merged:
is_first_entry marks where a record starts: here, any line that doesn’t start with whitespace, which covers indented stack frames. Match a timestamp or level prefix instead if that fits your output better.
Cluster events (optional)
To also collect cluster events such as scheduling, image pulls, and OOMKills, deploy a second Collector with thekubernetesEvents preset. Use a single-replica Deployment, not a DaemonSet, so each event arrives once:
rootprint-otel-events.
Troubleshooting
helm installfails with[ERROR] 'image.repository' must be set: add theimage.repositoryblock from the values above.- A DaemonSet pod stays
Pendingwithdidn't have free ports: another Collector holds the default hostPorts. Disable them as in the values above. - Every event appears twice: a workload both exports OTLP and prints to stdout. Compare
attributes.log.file.path:*withNOT attributes.log.file.path:*to see the split, then exclude that namespace. - Logs arrive without
k8s.*attributes: thekubernetesAttributespreset needs RBAC to read pod metadata. The chart creates theClusterRole. If you disabled RBAC creation, grantget,list, andwatchonpodsandnamespaces. - 401/403/413/415: see Response codes.
Related
- Send logs from Docker: container logs on a single Linux host.
- Send logs with the OpenTelemetry Collector: the same Collector tailing files on a host.
- OTLP reference: endpoint, response codes, limits.
- Indexes: the
otel-logs-v0_9schema.

