---
title: Observability with Logfire and OpenTelemetry Collector
description: >-
  Learn how to integrate Pydantic Logfire with OpenTelemetry Collector for
  centralized observability, flexible data routing, and enhanced monitoring
  capabilities
date: '2026-01-21'
authors:
  - Hasan Ramezani
categories:
  - Pydantic Logfire
  - OpenTelemetry
canonical: 'https://pydantic.dev/articles/logfire-opentelemetry-collector'
---

> Markdown version of [Observability with Logfire and OpenTelemetry Collector](https://pydantic.dev/articles/logfire-opentelemetry-collector) — the canonical HTML page.
>
> By [Hasan Ramezani](https://pydantic.dev/authors/hasan-ramezani.md) · 2026-01-21 · Pydantic Logfire, OpenTelemetry
>
> Related: [When agents build agents](https://pydantic.dev/articles/when-agents-build-agents.md) · [You perfected the wrong agent](https://pydantic.dev/articles/agents-week.md)
>
> All articles: [/articles.md](https://pydantic.dev/articles.md) · Site index: [/llms.txt](https://pydantic.dev/llms.txt)

---

# Observability with Logfire and OpenTelemetry Collector

As applications grow in complexity and scale, managing observability data becomes increasingly challenging. The [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) provides a powerful solution for collecting, processing, and exporting telemetry data from multiple sources. When combined with [Pydantic Logfire](https://pydantic.dev/logfire/?utm_source=blogpost), you get a robust observability stack that scales with your infrastructure.

In this guide, we'll explore how to integrate Logfire with OpenTelemetry Collector to build a centralized observability pipeline that gives you complete visibility into your applications.

## Introduction to Logfire and OpenTelemetry Collector

### What is Pydantic Logfire?

Pydantic Logfire is a developer-centric observability platform built on OpenTelemetry standards. It provides:

- **Automatic instrumentation** for Python, JavaScript, Rust, and other languages
- **Distributed tracing** across your entire stack, AI to API
- **Real-time monitoring** with powerful [SQL query](https://pydantic.dev/docs/logfire/reference/sql) capabilities
- **Beautiful, intuitive UI** for exploring traces, logs, and metrics
- **Built-in security** with automatic [scrubbing](https://pydantic.dev/docs/logfire/instrument/scrubbing) of sensitive data

### What is OpenTelemetry Collector?

The OpenTelemetry Collector is a vendor-agnostic telemetry data pipeline that can:

- **Receive** telemetry data via multiple protocols (OTLP, Jaeger, Zipkin, Prometheus)
- **Process** data through filtering, sampling, batching, and enrichment
- **Export** to one or multiple backends simultaneously
- **Scale** horizontally to handle high-volume telemetry

### Why Use Them Together?

While Logfire applications can send data directly to the Logfire backend, using OpenTelemetry Collector as an intermediary provides several benefits:

1. **Centralized Collection**: Route telemetry from multiple services through a single collection point
2. **Reduced Application Overhead**: Offload telemetry processing from your application
3. **Flexible Routing**: Send data to multiple backends (Logfire, Prometheus, etc.) simultaneously
4. **Data Transformation**: Filter, sample, or enrich telemetry before it reaches Logfire
5. **Network Resilience**: Buffer telemetry during network issues or backend downtime
6. **Multi-tenant Support**: Route data from different teams or environments appropriately

## Setting Up OpenTelemetry Collector

### Running the Collector with Docker

The easiest way to get started with OpenTelemetry Collector is using Docker:

```bash
docker pull otel/opentelemetry-collector:latest

docker run -d \
  --name otel-collector \
  -p 4317:4317 \
  -p 4318:4318 \
  -v $(pwd)/otel-collector-config.yaml:/etc/otel-collector-config.yaml \
  otel/opentelemetry-collector:latest \
  --config=/etc/otel-collector-config.yaml
```

### Basic Configuration

The OpenTelemetry Collector is configured using YAML. A minimal configuration consists of three main sections: receivers, processors, and exporters.

Create a file named `otel-collector-config.yaml`:

```yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:
    timeout: 10s
    send_batch_size: 1024

exporters:
  debug:
    verbosity: detailed

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [debug]
    metrics:
      receivers: [otlp]
      processors: [batch]
      exporters: [debug]
    logs:
      receivers: [otlp]
      processors: [batch]
      exporters: [debug]
```

This basic configuration:
- Receives OTLP data on ports 4317 (gRPC) and 4318 (HTTP)
- Batches telemetry for efficient transmission
- Exports to console (useful for testing)

## Integrating Logfire with OpenTelemetry Collector

Now let's configure the collector to send data to Logfire.

### Get Your Logfire Credentials

First, obtain your Logfire write token:

1. Sign in to [Logfire](https://logfire.pydantic.dev/)
2. Navigate to your project settings
3. Create and copy your write token from the project's settings under "Write Tokens"

### Configure the OTLP Exporter

Update your `otel-collector-config.yaml` to include the Logfire exporter:

```yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:
    timeout: 10s
    send_batch_size: 1024

  # Add resource attributes
  resource:
    attributes:
      - key: deployment.environment
        value: production
        action: upsert

exporters:
  otlphttp/logfire:
    # Configure the US / EU endpoint for Logfire.
    # - US: https://logfire-us.pydantic.dev
    # - EU: https://logfire-eu.pydantic.dev
    endpoint: https://logfire-us.pydantic.dev
    headers:
      Authorization: "Bearer YOUR_LOGFIRE_TOKEN"
    compression: gzip

  # Keep debug exporter for debugging
  debug:
    verbosity: basic

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch, resource]
      exporters: [otlphttp/logfire, debug]
    metrics:
      receivers: [otlp]
      processors: [batch, resource]
      exporters: [otlphttp/logfire, debug]
    logs:
      receivers: [otlp]
      processors: [batch, resource]
      exporters: [otlphttp/logfire, debug]
```

Replace `YOUR_LOGFIRE_TOKEN` with your actual Logfire write token.

### Configure Your Application

Now update your application to send telemetry to the collector instead of directly to Logfire:

#### FastAPI Example

```python
# /// script
# dependencies = [
#   "logfire[fastapi]",
#   "fastapi",
#   "uvicorn",
# ]
# ///

import logfire
from fastapi import FastAPI

logfire.configure(send_to_logfire=False)

app = FastAPI()

# Instrument FastAPI with Logfire
logfire.instrument_fastapi(app)


@app.get("/")
async def root():
    logfire.info("Root endpoint accessed")
    return {"message": "Hello World"}


if __name__ == "__main__":
    import uvicorn

    logfire.info("Starting FastAPI application")
    uvicorn.run(app, host="0.0.0.0", port=8000)
```

Run the application:

```bash
# Using uv (automatically installs dependencies from script header)
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 uv run app.py

# Or install manually and run with python
pip install 'logfire[fastapi]' uvicorn
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 python app.py
```

Test the endpoints:

```bash
# Test root endpoint
curl http://localhost:8000/
```

## Configuring Logfire for Observability

### Advanced Collector Configuration

Let's explore more advanced configurations that enhance your observability setup.

#### Sampling

Reduce data volume by sampling traces:

```yaml
processors:
  probabilistic_sampler:
    sampling_percentage: 10  # Sample 10% of traces

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [probabilistic_sampler, batch, resource]
      exporters: [otlphttp/logfire]
```

#### Filtering

Filter out unwanted telemetry:

```yaml
processors:
  filter:
    traces:
      span:
        - 'attributes["http.target"] == "/health"'
        - 'attributes["http.target"] == "/metrics"'

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [filter, batch, resource]
      exporters: [otlphttp/logfire]
```

#### Enrichment

Add environment context to all telemetry:

```yaml
processors:
  resource/add_environment:
    attributes:
      - key: environment
        value: production
        action: insert
      - key: region
        value: us-east-1
        action: insert
      - key: cluster
        value: primary
        action: insert

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [resource/add_environment, batch]
      exporters: [otlphttp/logfire, debug]
```

#### Multi-Backend Export

Send data to multiple backends simultaneously:

```yaml
exporters:
  otlphttp/logfire:
    endpoint: https://logfire-us.pydantic.dev
    headers:
      authorization: "Bearer YOUR_LOGFIRE_TOKEN"

  prometheus:
    endpoint: "localhost:9090"

  jaeger:
    endpoint: "jaeger:14250"
    tls:
      insecure: true

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch, resource]
      exporters: [otlphttp/logfire, jaeger]

    metrics:
      receivers: [otlp]
      processors: [batch, resource]
      exporters: [otlphttp/logfire, prometheus]
```

At Logfire, we use this multi-backend export feature for our demo project to send traces and metrics simultaneously to both our US and EU production environments. This ensures data redundancy and allows users in different regions to access the demo data with low latency. You can see our production configuration in the [Logfire demo repository](https://github.com/pydantic/logfire-demo/blob/main/otel-collector/otel-collector-config.yaml).

### Monitoring the Collector

The collector exposes metrics about its own operation. Configure Prometheus to scrape these metrics:

```yaml
service:
  telemetry:
    metrics:
      level: detailed
      address: 0.0.0.0:8888
```

Then configure Prometheus:

```yaml
scrape_configs:
  - job_name: 'otel-collector'
    static_configs:
      - targets: ['localhost:8888']
```

Key metrics to monitor:
- `otelcol_receiver_accepted_spans` - Spans received
- `otelcol_receiver_refused_spans` - Spans rejected
- `otelcol_exporter_sent_spans` - Spans successfully exported
- `otelcol_exporter_send_failed_spans` - Export failures
- `otelcol_processor_batch_batch_send_size` - Batch sizes

## Best Practices

### 1. Start Simple, Scale Gradually

Begin with a basic configuration and add complexity as needed. Don't over-engineer your initial setup.

### 2. Use Batching

Always enable the batch processor to reduce network overhead and improve throughput.

### 3. Monitor Your Collector

The collector is a critical component. Monitor its health, resource usage, and throughput.

### 4. Handle Failures Gracefully

Configure retry logic and queuing to handle temporary failures without data loss.

### 5. Secure Your Endpoints

Use TLS and authentication to protect your collector endpoints, especially in production.

### 6. Version Your Configuration

Keep your collector configuration in version control and treat it like application code.

### 7. Test Configuration Changes

Validate configuration changes in a staging environment before deploying to production.

### 8. Use Resource Attributes

Add consistent resource attributes to identify the source of telemetry across your infrastructure.

## Troubleshooting

### Collector Not Receiving Data

First, verify the collector is running and healthy by sending a test request:

```bash
# Test the collector's HTTP endpoint
curl -X POST http://localhost:4318/v1/traces \
  -H "Content-Type: application/json" \
  -d '{"resourceSpans":[]}'
```

**Healthy response**: `{"partialSuccess":{}}` - The collector is running and accepting data.

If this fails, check that:
- The collector container is running: `docker ps`
- The ports are properly exposed: `4317` (gRPC) and `4318` (HTTP)
- The configuration file is valid and loaded correctly

Once the collector is confirmed healthy, verify your application is configured to send to the correct endpoint (`http://localhost:4317` for gRPC or `http://localhost:4318` for HTTP).

### Data Not Reaching Logfire

Enable debug logging in the collector:

```yaml
exporters:
  debug:
    verbosity: detailed

service:
  pipelines:
    traces:
      exporters: [debug, otlp/logfire]
```

### High Memory Usage

Configure memory limits:

```yaml
processors:
  memory_limiter:
    check_interval: 1s
    limit_mib: 512
```

### Authentication Errors

Verify your Logfire write token is correct and hasn't expired by testing it directly:

```bash
# For US production stack
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://logfire-us.pydantic.dev/v1/traces

# For EU production stack
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://logfire-eu.pydantic.dev/v1/traces
```

If you see `unknown token%`, your write token is invalid.

## Conclusion

Integrating Pydantic Logfire with OpenTelemetry Collector gives you a flexible, scalable observability pipeline. You gain centralized control over your telemetry data, can route to multiple backends, and have the processing power to filter, sample, and enrich data before it reaches Logfire.

Whether you're running a small application or a large distributed system, this combination provides the foundation for comprehensive observability that grows with your needs.

Ready to get started? Sign up for [Pydantic Logfire](https://logfire.pydantic.dev/) and check out the [OpenTelemetry Collector documentation](https://opentelemetry.io/docs/collector/) for more details.


<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "BlogPosting",
      "mainEntityOfPage": {
        "@type": "WebPage",
        "@id": "https://pydantic.dev/articles/logfire-opentelemetry-collector"
      },
      "headline": "Observability with Logfire and OpenTelemetry Collector",
      "description": "Learn how to integrate Pydantic Logfire with OpenTelemetry Collector for centralized observability, flexible data routing, and enhanced monitoring capabilities.",
      "keywords": "OpenTelemetry Collector, Pydantic Logfire, Observability, Distributed Tracing, OTLP, Telemetry, Monitoring, OpenTelemetry, Data Pipeline, Metrics, Logs, Traces",
      "author": {
        "@type": "Person",
        "name": "Hasan Ramezani"
      },
      "datePublished": "2026-01-22T10:00:00.000Z",
      "publisher": {
        "@type": "Organization",
        "name": "Pydantic",
        "logo": {
          "@type": "ImageObject",
          "url": "https://pydantic.dev/logo.png"
        }
      },
      "about": [
        {
          "@type": "Thing",
          "name": "Observability",
          "sameAs": "https://en.wikipedia.org/wiki/Observability_(software)"
        },
        {
          "@type": "Thing",
          "name": "OpenTelemetry",
          "sameAs": "https://opentelemetry.io/"
        }
      ]
    },
    {
      "@type": "FAQPage",
      "mainEntity": [
        {
          "@type": "Question",
          "name": "What is OpenTelemetry Collector?",
          "acceptedAnswer": {
            "@type": "Answer",
            "text": "OpenTelemetry Collector is a vendor-agnostic telemetry data pipeline that can receive, process, and export observability data (traces, metrics, logs) from multiple sources to multiple backends. It acts as a central hub for managing telemetry data in your infrastructure."
          }
        },
        {
          "@type": "Question",
          "name": "Why should I use OpenTelemetry Collector with Logfire?",
          "acceptedAnswer": {
            "@type": "Answer",
            "text": "Using OpenTelemetry Collector with Logfire provides centralized collection, reduces application overhead, enables flexible routing to multiple backends, allows data transformation and filtering, provides network resilience with buffering, and supports multi-tenant configurations."
          }
        },
        {
          "@type": "Question",
          "name": "How do I configure my application to send data to OpenTelemetry Collector?",
          "acceptedAnswer": {
            "@type": "Answer",
            "text": "Configure your application to use the OTLP exporter pointing to your collector's endpoint (typically localhost:4317 for gRPC or localhost:4318 for HTTP). In Python with Logfire, set send_to_logfire=False and add a BatchSpanProcessor with OTLPSpanExporter pointing to your collector."
          }
        },
        {
          "@type": "Question",
          "name": "Can I send data to multiple backends from OpenTelemetry Collector?",
          "acceptedAnswer": {
            "@type": "Answer",
            "text": "Yes, OpenTelemetry Collector supports exporting to multiple backends simultaneously. You can configure multiple exporters in your pipeline, such as sending traces to both Logfire and Jaeger, or sending metrics to both Logfire and Prometheus."
          }
        }
      ]
    }
  ]
}
</script>
