<@ULVA73B9P> I have a prefect server and workers d...
# ask-marvin
r
@Marvin I have a prefect server and workers deployed using helm in a self hosted k8s cluster. I want to export traces and spans using OTEL how can I do that without having to add a lot of code ? Is it by design already included in prefect ?
m
thought for 214.0 seconds
Short answer - Prefect 3.x does create OpenTelemetry spans for flow and task runs out of the box. - However, Prefect does not ship an OTLP exporter or a Helm switch to send those spans anywhere. To actually export traces, you need to initialize an OTEL SDK/exporter in the Python processes (workers/flow runs, and optionally server) — the easiest way with little/no code is auto-instrumentation. What this means in practice - Built-in: Prefect’s engine generates spans for flow/task runs. If a global OpenTelemetry TracerProvider/exporter is active in the process, those spans will be exported. - Not built-in: No first-class Helm values or Prefect setting to configure an OTLP endpoint. Prefect doesn’t bootstrap an exporter for you in self-hosted installs. Minimal-code ways to export traces Pick one of these approaches to activate an OTEL exporter in your pods without changing your flow code: 1) Use OpenTelemetry auto-instrumentation in your worker/flow images - Add the exporter to the image:
Copy code
pip install opentelemetry-distro opentelemetry-exporter-otlp
  opentelemetry-bootstrap -a install
- Start the worker under the auto-instrumentation shim so it configures a global TracerProvider:
Copy code
opentelemetry-instrument --traces_exporter otlp --service_name prefect-worker \
    prefect worker start -p <your-pool>
- Set OTEL env vars in the worker Deployment (and in any custom flow-run image, if you use one):
Copy code
OTEL_EXPORTER_OTLP_ENDPOINT=<http://otel-collector:4317>
  OTEL_EXPORTER_OTLP_PROTOCOL=grpc
  OTEL_TRACES_SAMPLER=parentbased_always_on
  OTEL_RESOURCE_ATTRIBUTES=service.name=prefect-worker,service.namespace=prefect
- Result: Prefect’s built-in flow/task spans will be picked up and exported by the global SDK initialized by the shim. 2) Use the OpenTelemetry Operator (no entrypoint changes) - Install the operator and an OTEL Collector in your cluster. - Create an Instrumentation resource pointing at your collector and set desired sampler/propagators. - Annotate your Prefect worker Deployment (and flow-run Jobs if desired) to inject Python auto-instrumentation. The operator will inject the SDK and set up the exporter automatically. - Docs: OpenTelemetry Operator 3) Instrument Prefect Server (optional, for API/HTTP spans) - If you also want traces from the Prefect Server API (FastAPI), run the server under
opentelemetry-instrument
or use the Operator to inject into the server pod. Add the same OTEL_* env vars and the FastAPI/ASGI instrumentation will export request spans. A few notes - Prefect’s orchestration tracing is enabled by default in 3.x; if you previously disabled it, re-enable it:
Copy code
PREFECT_CLOUD_ENABLE_ORCHESTRATION_TELEMETRY=true
- There are no OTEL-specific Helm values today. You’ll either: - Override container command/args and add env vars in your Helm values, or - Use the OpenTelemetry Operator and add annotations. - Prefect’s spans will “just work” once there is a global TracerProvider/exporter in the process. References - Prefect Helm chart: prefect-helm - Prefect Server Helm guide: Server on Helm (docs) - OTEL Python auto-instrumentation: OpenTelemetry Python automatic instrumentation Questions to tailor the setup - Which parts do you want traced: flow/task runs, worker processes, server API, or all of the above? - Are you using the stock Prefect images or custom images for workers/flow runs? - Which OTEL collector/backend are you targeting (endpoint/protocol)?
r
@Marvin do I also need to instrument the flow run execution ?
m
thought for 130.9 seconds
Short answer: yes — you need the flow-run process to have an OTEL TracerProvider/exporter too. Why: Prefect emits spans inside the flow/task execution process. If only the worker pod is instrumented, those flow/task spans won’t be exported because the flow-run container is a separate pod/process with its own Python runtime. Minimal-code ways to cover flow runs Pick one: - OpenTelemetry Operator (no code changes) - Install the Operator and a Collector. - Add an Instrumentation resource and annotate your Prefect flow-run pods so the Operator injects the Python SDK/exporter. - In Prefect, add pod annotations and OTEL_* env vars via your deployment’s job variables/pod overrides so dynamically-created flow-run pods are injected. Example shape:
Copy code
job_variables:
      pod:
        metadata:
          annotations:
            <http://instrumentation.opentelemetry.io/inject-python|instrumentation.opentelemetry.io/inject-python>: "true"
        env:
          - name: OTEL_EXPORTER_OTLP_ENDPOINT
            value: <http://otel-collector:4317>
          - name: OTEL_EXPORTER_OTLP_PROTOCOL
            value: grpc
          - name: OTEL_RESOURCE_ATTRIBUTES
            value: service.name=prefect-flow-run,service.namespace=prefect
- Docs: OpenTelemetry Operator - Auto-instrumentation in your flow-run image (very low code) - Bake the SDK into the image used for flow runs:
Copy code
pip install opentelemetry-distro opentelemetry-exporter-otlp
    opentelemetry-bootstrap -a install
- Set OTEL_* env vars on the flow-run pods. - Run the flow-run process under the shim (via your pod template/entrypoint), e.g.:
Copy code
opentelemetry-instrument --traces_exporter otlp <your flow run command>
- If you can’t change the command, a tiny
sitecustomize.py
that sets a global TracerProvider + OTLP exporter on import also works, with no changes to your flow code. Recommendations - Instrument both: worker pods and flow-run pods. That ensures worker-side and flow/task spans all get exported and can be correlated. - If you want server API traces as well, run the Prefect Server pod under
opentelemetry-instrument
or use the Operator to inject there too. Helpful links - Prefect Helm: prefect-helm - Prefect Server on Helm: Server on Helm (docs) - Kubernetes work pools (pod/job overrides/job variables): Kubernetes work pool docs - OTEL Python auto-instrumentation: OpenTelemetry Python automatic instrumentation If you can share: - Whether your flow runs use a custom image - If you’re open to using the OpenTelemetry Operator - Your collector endpoint/protocol …I can give you a concrete values.yaml/pod spec snippet for your setup.
r
@Marvin But I've already installed
prefect[otel]
isn't in it ?
m
thought for 108.8 seconds
Installing
prefect[otel]
only installs the OpenTelemetry packages. It does not automatically configure an OTLP exporter or initialize a TracerProvider. What changes with prefect[otel] - You now have the OTEL SDK, OTLP exporter, and auto-instrumentation tooling available in the environment. - Prefect’s built-in flow/task spans are still created (that’s on by default), but they will remain no-op unless a global TracerProvider/exporter is initialized. To actually export spans, you still need to initialize the OTEL SDK somewhere in the process. Easiest low/no-code options: - Use the auto-instrumentation shim to start the process:
Copy code
opentelemetry-instrument --traces_exporter otlp --service_name prefect-worker \
    prefect worker start -p <your-pool>
And set env vars like:
Copy code
OTEL_EXPORTER_OTLP_ENDPOINT=<http://otel-collector:4317>
  OTEL_EXPORTER_OTLP_PROTOCOL=grpc
  OTEL_TRACES_SAMPLER=parentbased_always_on
  OTEL_RESOURCE_ATTRIBUTES=service.name=prefect-worker
- Or use the OpenTelemetry Operator to inject the SDK/exporter into your worker and flow-run pods via annotations. Key point: Prefect won’t start an exporter for you; once a TracerProvider is present (from auto-instrumentation or Operator injection), Prefect’s spans will be exported automatically.
n
hi @Romain Lefebvre - i would use the logfire SDK (you can use any OTEL dashboard)