Nicholas Pini
04/13/2026, 8:27 AMMarvin
04/13/2026, 8:27 AMMarvin
04/13/2026, 8:33 AMapiVersion: v1
kind: ConfigMap
metadata:
name: otel-collector-config
data:
config.yaml: |
receivers:
filelog:
include:
- /var/log/containers/*.log
start_at: end
# Operators help parse container log format and JSON lines
operators:
- type: container
- type: json_parser
parse_from: body
on_error: send
# Optional: allow SDKs to send OTLP traces/metrics directly
otlp:
protocols:
grpc:
http:
processors:
k8sattributes:
auth_type: serviceAccount
batch:
exporters:
# Replace with your backend (examples: otlp, loki, datadog, etc.)
otlp:
endpoint: your-otel-backend:4317
tls:
insecure: true
service:
pipelines:
logs:
receivers: [filelog]
processors: [k8sattributes, batch]
exporters: [otlp]
# Optional: enable if you’ll send traces/metrics via OTLP
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
Example DaemonSet volumes (abbreviated):
# In your Otel Collector DaemonSet
spec:
template:
spec:
serviceAccountName: otel-collector
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
containers:
- name: otel-collector
image: otel/opentelemetry-collector-contrib:latest
args: ["--config=/etc/otel/config.yaml"]
volumeMounts:
- name: varlog
mountPath: /var/log
readOnly: true
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
ports:
- name: otlp-grpc
containerPort: 4317
- name: otlp-http
containerPort: 4318
2) Ensure Prefect pods log to stdout (default) or switch to JSON for easier parsing
- Prefect already writes rich-formatted logs to stdout. The collector will ingest these from /var/log/containers.
- If you want clean JSON logs, provide a logging override and mount it into your worker/flow pods.
Minimal JSON logging override:
version: 1
disable_existing_loggers: False
formatters:
json:
class: prefect.logging.formatters.JsonFormatter
handlers:
console:
class: prefect.logging.handlers.PrefectConsoleHandler
level: INFO
formatter: json
loggers:
prefect:
level: INFO
handlers: [console]
propagate: false
Then set this in your pods:
- Mount the file (e.g., ConfigMap) at /etc/prefect/logging.yml
- Set env var: PREFECT_LOGGING_SETTINGS_PATH=/etc/prefect/logging.yml
Tip for flow-run pods: apply the env/volume in your Kubernetes work pool’s base job template so every flow pod inherits it.
3) (Optional) Export traces/metrics via OTLP from your Prefect runtimeMarvin
04/13/2026, 8:33 AMOTEL_EXPORTER_OTLP_ENDPOINT=<http://otel-collector:4318>
- or OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
- Make sure opentelemetry-sdk and opentelemetry-exporter-otlp are installed in your flow image.
Notes and references
- Prefect logging customization: Logging customization (Prefect 3)
- Prefect telemetry overview: Telemetry (Prefect 3)
- OpenTelemetry Collector filelog receiver: filelog receiver docs
- k8sattributes processor: k8sattributes processor docs
- Python OTel configuration (env vars): OpenTelemetry Python configuration
Quick sanity checks
- You do not need to change Prefect code to get logs into OTel on Kubernetes; scraping stdout via filelog is the simplest and most robust approach.
- If you want to correlate logs with K8s metadata, ensure the collector has k8s RBAC and k8sattributes enabled.
- If you prefer a direct code‑level log exporter, you can implement a custom logging handler in Prefect, but it’s usually unnecessary on Kubernetes.
Questions to tailor this for you
- Do you want to ingest logs from flow-run pods, the worker pod(s), the Prefect Server API/Orion pods, or all of the above?
- What’s your log backend (OTLP to another collector, Loki, Datadog, etc.)?
- Do you also want traces and/or metrics exported from Prefect runtimes? If yes, I can share a minimal OTel SDK init snippet or env var setup for Python 3.12 containers.