Skip to content

Collect Kubernetes container logs in Osuite

The osuite-k8s Helm chart can collect the stdout and stderr of every container in the cluster. Collection runs in the node collector (otel-daemon), which reads each pod’s log files from the node, enriches them with workload identity, assigns a severity, and forwards them to Osuite. Because a busy cluster produces a large volume of logs, the chart lets you scope collection down to the namespaces, pods, and severities you care about.

Container logs are off by default. Turn them on under otel_daemon.containerlogs:

otel_daemon:
containerlogs:
enabled: true
namespaces: []

With namespaces left empty, the chart collects logs from all namespaces, all pods, and all severity levels. Enabling collection also deploys the DaemonSet if it was not already running for host metrics.

Each log line is enriched before it leaves the node:

  • Workload identity — the k8sattributes processor attaches k8s.namespace.name, k8s.pod.name, and the owning deployment, statefulset, or daemonset. service.name is derived from that workload, so logs line up with the same service in APM.
  • Severity — a transform derives severity_text from the log body (ERROR, WARN, or INFO), falling back to INFO for stdout and ERROR for stderr when the body carries no level keyword.
  • Environment — when you set the top-level environment value, it is attached as service.environment.

To restrict collection, add entries under namespaces. Each entry names one namespace and optionally narrows it further:

otel_daemon:
containerlogs:
enabled: true
namespaces:
- name: "namespace-name"
include: ["<pod-name-regex>"]
exclude: ["<pod-name-regex>"]
levels: ["ERROR", "WARN"]
FieldEffectOmitted
nameThe namespace to collect from.— (required per entry)
includeList of regexes matched against the pod name; a pod is kept only if it matches at least one.All pods in the namespace
excludeList of regexes matched against the pod name; a matching pod is dropped. Exclude wins over include.Nothing excluded
levelsList of severity values (ERROR, WARN, INFO) to keep.All severity levels

Collect everything from two namespaces and nothing else:

otel_daemon:
containerlogs:
enabled: true
namespaces:
- name: "production"
- name: "payments"

Collect only the API and web pods in production:

otel_daemon:
containerlogs:
enabled: true
namespaces:
- name: "production"
include: ["^api-.*", "^web-.*"]

Collect all of production except debug pods:

otel_daemon:
containerlogs:
enabled: true
namespaces:
- name: "production"
exclude: [".*-debug-.*"]

Collect only warnings and errors from default, while keeping full collection in production:

otel_daemon:
containerlogs:
enabled: true
namespaces:
- name: "production"
- name: "default"
levels: ["ERROR", "WARN"]

Combine every filter — keep only the payment-service pods in payments, excluding canaries, at error and warning level:

otel_daemon:
containerlogs:
enabled: true
namespaces:
- name: "payments"
include: ["^payment-service-.*"]
exclude: [".*-canary-.*"]
levels: ["ERROR", "WARN"]

Apply changes with a helm upgrade:

Terminal window
helm upgrade osuite-k8s osuite/osuite-k8s \
--namespace osuite \
--values values.yaml

What you should see

Within a minute of the upgrade, logs from the collected pods appear in the logs explorer, grouped under their owning service and tagged with k8s.namespace.name and k8s.pod.name. Filtering by severity returns only the levels you allowed.

  • A namespace you expected is missing — once namespaces is non-empty it becomes a whitelist; confirm the namespace is listed by exact name.
  • A pod matched by include is still dropped — check exclude; an exclude match always wins over an include match.
  • A severity filter drops everything — confirm the values are among ERROR, WARN, and INFO; no other severity is produced.
  • The collector’s own logs are noisy — the chart already excludes the otel-daemon pods’ log files to avoid a feedback loop.

No data in Osuite after a few minutes? Work through these checks.

  • Endpoint — confirm the exporter targets exactly ingest.<region>.osuite.io:443 for your region, over TLS.
  • Token — confirm the ingest header carries a valid <your-ingest-token> and has not been rotated.
  • Pipeline — confirm the signal you expect (traces, logs, or metrics) is wired into an active pipeline with the otlp/osuite exporter attached.
  • Export errors — check the application or Collector logs for OTLP export failures (auth, DNS, TLS, connection refused).
  • Network — confirm the host has outbound access to the ingest endpoint on port 443.
  • Timing — allow up to a minute for the first data to appear before assuming a failure.

Still stuck? Ask the Investigation Agent or contact support.