Back to Langflow

OpenTelemetry

docs/docs/Develop/observability-opentelemetry.mdx

1.12.0.dev346.5 KB
Original Source

Langflow emits OpenTelemetry traces, metrics, and logs describing the health of the Langflow service itself: request rate, error rate, duration, runtime health, and one span per flow run.

This telemetry answers operator questions, such as which flows are failing, whether the service is slow, and where the time went. It is not LLM tracing. Langflow deliberately withholds prompts, completions, and other flow payloads from this export. For prompt-level tracing, use one of the monitoring integrations instead.

There is no vendor code in the Langflow runtime. Langflow speaks plain OTLP, so any OpenTelemetry-compatible backend works, either directly or through an OpenTelemetry Collector.

Prerequisites

  • An OTLP endpoint, such as an OpenTelemetry Collector, a Grafana stack, or a commercial APM.

  • The langflow distribution already includes the OpenTelemetry packages. If you run the lfx engine on its own, install the extra:

    bash
    pip install "lfx[otel]"
    

    If an OTLP endpoint is configured and the packages are missing, Langflow logs a warning at startup rather than exporting nothing silently.

Configure environment variables

Set the endpoint and a service name. Nothing else is required.

text
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OTEL_SERVICE_NAME=langflow

If no OTLP endpoint is set, Langflow installs no providers and the export path stays inert.

The standard OpenTelemetry SDK variables also apply. The following are the ones operators reach for most often:

VariablePurpose
OTEL_EXPORTER_OTLP_PROTOCOLhttp/protobuf (default) or grpc.
OTEL_EXPORTER_OTLP_HEADERSAuthentication headers, such as an API key.
OTEL_EXPORTER_OTLP_TRACES_ENDPOINTPer-signal endpoint override. The same pattern applies to METRICS and LOGS.
OTEL_TRACES_EXPORTER=noneDisables a single signal. The same pattern applies to METRICS and LOGS.
OTEL_EXPORTER_OTLP_COMPRESSION=gzipCompresses payloads. Required by backends with a payload size cap.

What Langflow exports

Traces

SpanEmitted byCarries
flow.executeLangflowflow_id, run_id, session_id, protocol, status, and error.type when the run fails
HTTP server spansFastAPI and ASGI instrumentationRoute, method, status code
Database spansSQLAlchemy instrumentationdb.system, db.operation, and db.statement with bound parameters left as ? placeholders

The flow.execute span is the unit of work. There is no span per component, because component spans would carry component payloads.

The protocol attribute records which entry point drove the run: v1, v1.build, v1.build.public, v1.advanced, v2, webhook, mcp, a2a, openai_responses, voice, agentic, lfx.run, or lfx.serve. Use it to compare error rates across the API, the MCP server, and the UI's build endpoint.

The status attribute is ok, error, paused, or cancelled. A run stopped by a user is cancelled rather than error, so a stop button does not inflate your error rate.

Metrics

  • HTTP server metrics, including http.server.request.duration, which give you rate, errors, and duration.
  • Process metrics for this interpreter: CPU, memory, threads, open file descriptors, context switches, and garbage collection.
  • Langflow's own gauges, such as langflow_event_loop_lag_seconds.

Process metrics deliberately describe the process rather than the host. Under Kubernetes, host metrics would report the node, which is misleading next to a per-pod request rate, and your infrastructure agent already provides them.

Logs

If an OTLP endpoint is configured, log records at INFO and above are exported, and every record carries trace_id and span_id so you can pivot from a slow trace to the lines it produced.

What Langflow does not export

The export is an allowlist, not a filter applied after the fact. Spans from instrumentation that is not on the list, including every LLM tracing integration, are dropped on the way out.

The following never reach your backend:

  • Prompts, completions, tool arguments, and tool results.
  • Exception messages. A failed run reports error.type only, because the message frequently embeds flow content. For example, a run that failed with RuntimeError("inventory service returned 503") exports error.type = RuntimeError and nothing else.
  • Database bound parameters, so chat message text stays in the database.
  • Outbound provider request URLs, since provider keys are sometimes passed as query parameters.
  • Log message bodies, unless a call site explicitly opts in.

Two settings widen this, and both warn when set:

VariableEffect
LANGFLOW_OTEL_LOG_LEVEL=DEBUGExports DEBUG records. Langflow logs flow inputs and outputs at DEBUG, so prompt and completion content reaches your backend.
LANGFLOW_OTEL_LOG_BODIES=allExports log message bodies, including completions, chat history, and provider error text.

Control span volume

Database spans are the bulk of the export. Measured against a running instance under steady load, they were roughly 80% of exported spans, at about 50 spans per flow run against a single flow.execute. Backends that bill per span ingested will bill mostly for them.

To send flow and request spans only:

text
LANGFLOW_OTEL_DB_SPANS=false

Consider the trade before you set it. In that same measurement, 17% of database connection checkouts took longer than 50 ms and 4% took longer than 200 ms. Without database spans, a run that was slow waiting on the database looks simply slow, with no cause attached.

When the setting is off, the instrumentation is never installed, so the spans are not created rather than created and discarded.

Verify your configuration

Run the doctor. It sends a probe on every signal and reports what the backend accepted:

bash
lfx observability doctor

The doctor also reports what you are about to send, including whether log bodies are exported and whether database spans are on. Look for items named lfx.observability.doctor in your backend.

A successful send is not proof that your backend kept the data. Some backends acknowledge a payload and then discard invalid records during asynchronous validation. Always confirm by querying the backend for the trace or metric you expect.

Vendor guides

See also