logsCollection preset wires up the filelog receiver; the kubernetesAttributes preset enriches each record with the pod, namespace, node, and container it came from. A small transform infers severity from the message body, the same way the Docker path does.
Prerequisites
- A running Rootprint instance and its base URL — you’ll substitute it for
<your-rootprint>. - A Kubernetes cluster with
kubectlandhelmconfigured against it. The DaemonSet schedules on every node whose pods you want collected. - 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.
Create values.yaml
Save this as
values.yaml. Replace <your-rootprint> with your Rootprint base URL and
<your-ingest-token> with the API key you copied above.The service.pipelines.logs.processors list is spelled out on purpose. The chart replaces
this array rather than merging it, so the preset-injected processors (memory_limiter,
k8sattributes, batch) have to be listed alongside transform — drop one and the chart drops
it from the pipeline.Send a test log line
Run a throwaway pod that prints one line and exits. The Collector on that pod’s node tails it and
ships it with the pod’s metadata attached.Clean up afterwards with
kubectl delete pod rootprint-smoke-test.What you get in Rootprint
ThekubernetesAttributes preset attaches cluster context to every record:
| OTLP attribute | Value |
|---|---|
k8s.pod.name | pod the log came from |
k8s.namespace.name | pod’s namespace |
k8s.node.name | node the pod is scheduled on |
k8s.container.name | container within the pod |
k8s.pod.uid | pod UID |
| severity | inferred from the message body |
Severity inference
Thetransform lowercases the body and matches two pattern families:
error,fatal,panic, orexception(word-boundary) →severityText: ERROR(severity number 17).warn/warning,deprecated, orretry→severityText: WARN(13).- Everything else →
severityText: INFO(9).
DEBUG is not inferred — \bdebug\b against arbitrary pod output false-positives constantly. Apps that need debug-level visibility should emit it via an OpenTelemetry SDK that sets severityNumber itself; that record carries through unchanged because the SDK writes to the same endpoint.
Cluster events (optional)
The steps above collect pod logs. To also capture cluster-level events — scheduling, image pulls, OOMKills — deploy a second Collector as a single-replicaDeployment (not a DaemonSet, to avoid duplicate events) with the kubernetesEvents preset:
rootprint-otel-events) so it doesn’t collide with the DaemonSet.
Troubleshooting
- No pods in the DaemonSet: nodes may carry taints the Collector doesn’t tolerate. Add the matching
tolerationstovalues.yaml, or checkkubectl describe daemonset -n rootprint. 401from Rootprint: theAuthorizationheader is missing or the token is wrong. Check the token value invalues.yaml.403from Rootprint: the API key exists but is not scoped tootel-logs-v0_9. Create a new key scoped to that index.413from Rootprint: the batch is too large. Addsend_batch_max_sizeto thebatchprocessor.415from Rootprint: theContent-Typeis notapplication/x-protobuf. The Collector sets this automatically; if you see a 415, check for a proxy stripping headers.- Logs arrive without
k8s.*attributes: thekubernetesAttributespreset needs RBAC to read pod metadata. The chart creates theClusterRoleautomatically — if you disabled RBAC creation, grantget/list/watchonpodsandnamespaces.
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 URL, response codes, body limits.
- Indexes: the
otel-logs-v0_9schema.
