<@ULVA73B9P> how can i enable opentelemetry logs f...
# marvin-ai
t
@Marvin how can i enable opentelemetry logs for prefect worker, i want to do logging and monitoring my jobs that run by prefect worker, currently i deploy worker by docker-compose
m
thought for 232.4 seconds
Great question. Short answer: Prefect 3.x does not (yet) natively export OpenTelemetry to an external OTLP backend, but you can enable OTEL-based logs/traces for your worker (and your flows) by running the worker under OpenTelemetry’s Python auto-instrumentation and pointing it at your collector. If you just want logs in Prefect, you can also enable Prefect’s “logs to API.” A couple clarifying questions to tailor the setup: - Which work pool type are you using (process, docker, kubernetes)? If your flows run in separate containers (e.g., Docker work pool), you’ll need to instrument those containers too. - What backend are you sending OpenTelemetry data to (e.g., OTEL Collector + Grafana Tempo/Loki, Datadog, New Relic, etc.)? - Do you want logs only, or traces and metrics as well? Approach A: Prefect-native logs to Prefect API (no OTEL) - This is the quickest way to centralize logs in Prefect’s UI: - Set
PREFECT_LOGGING_TO_API_ENABLED=true
on the worker and on any flow containers. - Optionally tweak batching/levels via settings. - Docs: - Logging customization - Settings reference - Workers Approach B: OpenTelemetry logs/traces via auto-instrumentation - Install OTEL SDK + exporter in your worker image and start the worker via
opentelemetry-instrument
so Python logs/HTTP calls/etc. are exported to your collector. 1) Minimal Dockerfile for your worker image
Copy code
FROM prefecthq/prefect:3-latest
# Or your existing worker base image

# Install OTEL Python SDK and OTLP exporter
RUN pip install --no-cache-dir \
  opentelemetry-sdk \
  opentelemetry-exporter-otlp \
  opentelemetry-instrumentation \
  opentelemetry-instrumentation-logging
2) docker-compose.yml snippet
Copy code
services:
  otel-collector:
    image: otel/opentelemetry-collector:latest
    command: ["--config=/etc/otelcol/config.yaml"]
    volumes:
      - ./otel-collector.yaml:/etc/otelcol/config.yaml:ro
    ports:
      - "4317:4317"   # gRPC
      - "4318:4318"   # HTTP

  prefect-worker:
    image: your-prefect-worker:latest
    # Run the worker through OTEL auto-instrumentation
    command: >
      opentelemetry-instrument
      --traces_exporter otlp
      --metrics_exporter otlp
      --logs_exporter otlp
      prefect worker start --pool YOUR_POOL_NAME
    environment:
      # Prefect connectivity
      - PREFECT_API_URL=<https://api.prefect.cloud/api/accounts/xxx/workspaces/yyy>
      - PREFECT_API_KEY=${PREFECT_API_KEY}
      # Optionally also send logs to Prefect (independent of OTEL)
      - PREFECT_LOGGING_TO_API_ENABLED=true

      # OTEL config
      - OTEL_SERVICE_NAME=prefect-worker
      - OTEL_RESOURCE_ATTRIBUTES=service.namespace=prefect,work.pool=YOUR_POOL_NAME
      - OTEL_EXPORTER_OTLP_ENDPOINT=<http://otel-collector:4317>
      - OTEL_EXPORTER_OTLP_PROTOCOL=grpc
      # If your collector/back-end needs headers (example)
      # - OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer YOUR_TOKEN

      # Helpful tuning
      - OTEL_LOG_LEVEL=info
      - OTEL_PYTHON_LOG_CORRELATION=true
    depends_on:
      - otel-collector
    restart: unless-stopped
3) Collector config (example)
Copy code
receivers:
  otlp:
    protocols:
      grpc:
      http:

exporters:
  # Replace with the exporter(s) you need (Tempo, Loki, Datadog, etc.)
  logging:
    loglevel: info

service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [logging]
    logs:
      receivers: [otlp]
      exporters: [logging]
    metrics:
      receivers: [otlp]
      exporters: [logging]
Important notes - If your work pool launches flows in separate containers (e.g., Docker or Kubernetes pools), you must add the same OTEL dependencies and
opentelemetry-instrument
startup to those containers as well. Otherwise you’ll only get worker-level telemetry, not flow-run telemetry.
- Prefect’s own task/flow orchestration is not currently emitted as OTEL spans by default. OTEL auto-instrumentation will capture Python logging, HTTP calls (e.g., requests), and other supported libraries automatically, which is still very useful for centralized logging/monitoring. - If you only need logs in Prefect’s UI, prefer
PREFECT_LOGGING_TO_API_ENABLED=true
for simplicity. Related Prefect docs - Logging customization - Settings reference - Workers - Self-hosted with Docker Compose OpenTelemetry Python docs - Auto-instrumentation - Logs If you share which backend you’re targeting and your work pool type, I can tailor the compose + config (and the flow container setup if needed).
t
@Marvin currently my work pool is docker pool and backend python, but it does not matter, i want to enable otel debug log to check that if log can send to otel-collector. Now i see otel logs but my collector does not have it
m
thought for 87.7 seconds
Got it. Since you’re using a Docker work pool, remember there are two processes to instrument: - the worker container - every flow-run container the worker launches (your flow image) If you only instrument the worker, you’ll see OTEL debug logs in the worker but nothing reaches the collector for the flow runs. Quick checklist to get OTEL logs/traces out and verify with debug logs: 1) Install OTEL packages in BOTH images - Add to your worker image and your flow image:
Copy code
pip install --no-cache-dir \
  opentelemetry-sdk \
  opentelemetry-exporter-otlp \
  opentelemetry-instrumentation \
  opentelemetry-instrumentation-logging
2) Run both processes via opentelemetry-instrument - Worker (docker-compose):
Copy code
command: >
  opentelemetry-instrument
  --traces_exporter otlp
  --metrics_exporter otlp
  --logs_exporter otlp
  prefect worker start --pool YOUR_DOCKER_POOL
- Flow image (so it instruments whatever command Prefect injects):
Copy code
ENTRYPOINT ["opentelemetry-instrument", "--traces_exporter", "otlp", "--logs_exporter", "otlp"]
# no CMD here — Prefect will set the flow command at runtime
3) Environment variables (debug + connectivity) Set these in BOTH worker and flow containers:
Copy code
# Identify the service
OTEL_SERVICE_NAME=prefect-worker             # worker image
# for flows, build/override to something like:
# OTEL_SERVICE_NAME=prefect-flow
OTEL_RESOURCE_ATTRIBUTES=service.namespace=prefect,work.pool=docker

# Endpoint/protocol — match your collector
OTEL_EXPORTER_OTLP_ENDPOINT=<http://otel-collector:4317>
OTEL_EXPORTER_OTLP_PROTOCOL=grpc
# If using HTTP receiver instead, use:
# OTEL_EXPORTER_OTLP_ENDPOINT=<http://otel-collector:4318>
# OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

# Enable all three signals
OTEL_TRACES_EXPORTER=otlp
OTEL_METRICS_EXPORTER=otlp
OTEL_LOGS_EXPORTER=otlp

# Debug and helpful extras
OTEL_LOG_LEVEL=debug
OTEL_PYTHON_LOG_CORRELATION=true
OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true
# If your collector is plaintext gRPC and the SDK complains about TLS:
# OTEL_EXPORTER_OTLP_INSECURE=true
# If your backend needs auth:
# OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer YOUR_TOKEN
4) Collector config must have a logs pipeline Make sure your collector has all three pipelines and that the receiver matches your chosen protocol:
Copy code
receivers:
  otlp:
    protocols:
      grpc:
      http:

exporters:
  logging:
    loglevel: debug
  # add your real exporter(s) here too

service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [logging]      # plus your real exporter
    logs:
      receivers: [otlp]
      exporters: [logging]      # plus your real exporter
    metrics:
      receivers: [otlp]
      exporters: [logging]      # plus your real exporter
Common pitfalls that cause “I see OTEL debug logs but the collector shows nothing” - Using localhost in a container: from the worker/flow container, use http://otel-collector:4317 (service name), not http://localhost. - Protocol/port mismatch: 4317 is gRPC; 4318 is HTTP. Set OTEL_EXPORTER_OTLP_PROTOCOL accordingly. - Logs pipeline missing in the collector (traces might work, logs won’t). - Flow image not instrumented: Docker work pool runs your flows in separate containers. Instrument those too (ENTRYPOINT trick above). - Version skew: use recent OTEL libs (sdk/exporter/instrumentation) and a recent collector image — logs signal support matured fairly recently. Minimal docker-compose example (worker + collector) ``` services: otel-collector: image: otel/opentelemetry-collector:latest command: ["--config=/etc/otelcol/config.yaml"] volumes: - ./otel-collector.yaml/etc/otelcol/config.yamlro ports: - "4317:4317" - "4318:4318" prefect-worker: image: your-prefect-worker:latest command: > opentelemetry-instrument --traces_exporter otlp --metrics_exporter otlp --logs_exporter otlp prefect worker start --pool YOUR_DOCKER_POOL environment:
- PREFECT_API_URL=... - PREFECT_API_KEY=... - OTEL_SERVICE_NAME=prefect-worker - OTEL_RESOURCE_ATTRIBUTES=service.namespace=prefect,work.pool=docker - OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 - OTEL_EXPORTER_OTLP_PROTOCOL=grpc - OTEL_TRACES_EXPORTER=otlp - OTEL_METRICS_EXPORTER=otlp - OTEL_LOGS_EXPORTER=otlp - OTEL_LOG_LEVEL=debug - OTEL_PYTHON_LOG_CORRELATION=true - OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true depends_on: - otel-collector restart: unless-stopped
Copy code
Quick ways to verify
- Temporarily keep the collector’s logging exporter enabled to see incoming traces/logs in its stdout.
- From inside the worker container, run a quick log generator:
opentelemetry-instrument --traces_exporter otlp --logs_exporter otlp python - <<'PY' import logging, time logging.basicConfig(level=logging.INFO) log = logging.getLogger("otel-test") for i in range(3): log.warning("hello from worker %s", i) time.sleep(1) PY ``` If the collector’s logging exporter prints those, your path is good. If you can, please share: - your worker service section from docker-compose - your flow image Dockerfile (or base image) - your otel-collector.yaml pipelines - the exact OTEL_* env vars you’re using With that I can pinpoint why the collector isn’t seeing the data. References - OpenTelemetry Python auto-instrumentation: https://opentelemetry.io/docs/languages/python/automatic/ - OpenTelemetry Python logs: https://opentelemetry.io/docs/languages/python/logs/ - Prefect workers: https://docs-3.prefect.io/v3/concepts/workers - Logging in Prefect (if you also want logs in the Prefect UI): https://docs-3.prefect.io/v3/advanced/logging-customization
t
@Marvin how can i monitor log in container that run by prefect worker with type docker-pool
m
thought for 421.4 seconds
There are two good ways to monitor logs from containers started by a Docker work pool: Option 1 — Use Prefect’s built‑in logging (easiest, shows up in Prefect UI) - Make sure your flow containers have: -
PREFECT_LOGGING_TO_API_ENABLED=true
(sends logs to Prefect) -
PREFECT_LOGGING_LOG_PRINTS=true
(captures print statements) - Optionally:
PREFECT_LOGGING_ROOT_LEVEL=INFO
and
PREFECT_LOGGING_EXTRA_LOGGERS=requests,urllib3
to capture 3rd‑party loggers How to set these for all runs in a Docker work pool: - Add them to your deployment’s job variables so the Docker work pool injects them into each flow container. prefect.yaml example:
Copy code
deployments:
- name: my-deploy
  entrypoint: path/to/flow.py:my_flow
  work_pool:
    name: my-docker-pool
    job_variables:
      env:
        PREFECT_LOGGING_TO_API_ENABLED: "true"
        PREFECT_LOGGING_LOG_PRINTS: "true"
        PREFECT_LOGGING_ROOT_LEVEL: "INFO"
        PREFECT_LOGGING_EXTRA_LOGGERS: "requests,urllib3"
Then redeploy:
Copy code
prefect deploy
You’ll see the logs under the Flow Run in the Prefect UI. - Logging docs: Logging customization - Job variables docs: Customize job variables Option 2 — Send logs to your OpenTelemetry collector (needs instrumentation in the flow image) Because Docker work pools launch each flow in its own container, you must instrument the flow image (not just the worker). 1) Add OTEL libs to your flow image and instrument it - Dockerfile (flow image):
Copy code
FROM your-base-image

RUN pip install --no-cache-dir \
  opentelemetry-sdk \
  opentelemetry-exporter-otlp \
  opentelemetry-instrumentation \
  opentelemetry-instrumentation-logging

# Make OTEL wrap whatever command Prefect injects at runtime
ENTRYPOINT ["opentelemetry-instrument", "--traces_exporter", "otlp", "--logs_exporter", "otlp"]
2) Set OTEL env vars via job_variables.env so they land inside the flow container:
Copy code
deployments:
- name: my-deploy
  entrypoint: path/to/flow.py:my_flow
  work_pool:
    name: my-docker-pool
    job_variables:
      image: your-flow-image:latest
      env:
        OTEL_SERVICE_NAME: "prefect-flow"
        OTEL_RESOURCE_ATTRIBUTES: "service.namespace=prefect,work.pool=docker"
        OTEL_EXPORTER_OTLP_PROTOCOL: "grpc"            # or "http/protobuf"
        OTEL_EXPORTER_OTLP_ENDPOINT: "<http://HOSTNAME_OR_IP:4317>"
        OTEL_TRACES_EXPORTER: "otlp"
        OTEL_LOGS_EXPORTER: "otlp"
        OTEL_METRICS_EXPORTER: "otlp"
        OTEL_LOG_LEVEL: "debug"
        OTEL_PYTHON_LOG_CORRELATION: "true"
        OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED: "true"
        # If using plaintext gRPC:
        # OTEL_EXPORTER_OTLP_INSECURE: "true"
        # If your backend needs auth:
        # OTEL_EXPORTER_OTLP_HEADERS: "Authorization=Bearer YOUR_TOKEN"
Connectivity tips (common reasons logs don’t reach the collector): - Don’t use localhost inside the flow container unless your collector is in the same container. Use a reachable address: - If your collector runs in Docker Compose on the same host, expose 4317/4318 and use: - Mac/Windows:
<http://host.docker.internal:4317>
- Linux: use the Docker host gateway IP (often
172.17.0.1
) or enable host-gateway and set endpoint to
<http://host.docker.internal:4317>
- Ensure your collector has a logs pipeline enabled:
Copy code
receivers:
  otlp:
    protocols:
      grpc:
      http:
exporters:
  logging:
    loglevel: debug
service:
  pipelines:
    logs:
      receivers: [otlp]
      exporters: [logging]   # plus your real exporter(s)
Verify quickly from a flow container - Run a test flow that logs, or exec into a similar container and run: ``` opentelemetry-instrument --traces_exporter otlp --logs_exporter otlp python - <<'PY' import logging, time logging.basicConfig(level=logging.INFO) log = logging.getLogger("otel-test") for i in range(3):
log.warning("hello from flow container %s", i) time.sleep(1) PY ``` - If your collector has a logging exporter enabled, you should see the entries arrive. References - Prefect workers and Docker infra: Docker work pools - Logging customization: Prefect logging - OpenTelemetry Python auto-instrumentation: Auto-instrumentation - OpenTelemetry logs: Logs If you share: - your prefect.yaml (or deploy() snippet) for the deployment, - your flow image Dockerfile, - how/where the collector runs (host/compose/k8s) and its endpoint, I can pinpoint the minimal changes to get logs visible either in Prefect UI or in your OTEL backend.