> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bronto.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Nginx access logs and traces with OpenTelemetry

> Collect Nginx access logs, error logs, and request traces with the OpenTelemetry Collector and forward them to Bronto for latency, status code, and upstream analysis.

Forward Nginx access and error logs, and optionally request traces, to Bronto through a single OpenTelemetry Collector. See [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) for Collector basics.

## Prerequisites

* A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key))
* Nginx running and writing logs (default paths: `/var/log/nginx/access.log` and `/var/log/nginx/error.log`)
* An [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) (recommended) or [Fluent Bit](https://docs.fluentbit.io/manual/installation/getting-started-with-fluent-bit) installed on the same host
* For traces: Nginx 1.25.3+ with the [`ngx_otel_module`](https://nginx.org/en/docs/ngx_otel_module.html) (install the `nginx-module-otel` package)

## Logs and traces

Nginx emits request traces over OTLP/gRPC via `ngx_otel_module`. Point the module at a local Collector that forwards both signals to Bronto.

**1. Enable tracing in Nginx.** Add `load_module` to the top of `nginx.conf` and the `otel_*` directives inside the `http` block:

```nginx nginx.conf theme={"dark"}
load_module modules/ngx_otel_module.so;

http {
    otel_exporter {
        endpoint localhost:4317;
    }
    otel_service_name  nginx;
    otel_trace         on;
    otel_trace_context propagate;
}
```

**2. Configure the Collector** to tail the log files and accept traces, then export each signal to Bronto:

```yaml /etc/otel/config.yaml theme={"dark"}
receivers:
  filelog/nginx:
    include:
      - /var/log/nginx/access.log
      - /var/log/nginx/error.log
    resource:
      service.name: nginx
      service.namespace: <YOUR_COLLECTION_NAME>
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317

processors:
  batch:

exporters:
  otlphttp/brontologs:
    logs_endpoint: "https://ingestion.<REGION>.bronto.io/v1/logs"
    compression: gzip
    headers:
      x-bronto-api-key: <YOUR_API_KEY>
  otlphttp/brontotraces:
    traces_endpoint: "https://ingestion.<REGION>.bronto.io/v1/traces"
    compression: gzip
    headers:
      x-bronto-api-key: <YOUR_API_KEY>

service:
  pipelines:
    logs:
      receivers: [filelog/nginx]
      processors: [batch]
      exporters: [otlphttp/brontologs]
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlphttp/brontotraces]
```

Set `<REGION>` to `eu` or `us`. The `service.name` / `service.namespace` attributes (and `otel_service_name`) route data to the Bronto dataset and collection.

## Logs only

If you only need logs, drop the `otlp` receiver and the traces pipeline:

```yaml /etc/otel/config.yaml theme={"dark"}
receivers:
  filelog/nginx:
    include:
      - /var/log/nginx/access.log
      - /var/log/nginx/error.log
    resource:
      service.name: nginx
      service.namespace: <YOUR_COLLECTION_NAME>

processors:
  batch:

exporters:
  otlphttp/brontologs:
    logs_endpoint: "https://ingestion.<REGION>.bronto.io/v1/logs"
    compression: gzip
    headers:
      x-bronto-api-key: <YOUR_API_KEY>

service:
  pipelines:
    logs:
      receivers: [filelog/nginx]
      processors: [batch]
      exporters: [otlphttp/brontologs]
```

## What you will see in Bronto

Open [Search](https://app.bronto.io/search) and filter by `service.name = nginx`. Access logs in the default `combined` format carry the client IP, request method and path, HTTP status code, response size, referrer, and user agent; error logs carry a timestamp, severity level (`error`, `warn`, `crit`), and the message. Bronto's [Custom Parser](/core-features/custom-parser) extracts these fields server-side — no parser operators needed in the Collector.

Traces appear in [Explore Traces](/tracing/explore-traces) — one span per request, with the method, route, status code, and duration. See [Send Traces to Bronto](/tracing/send-traces) for more.

## Troubleshooting

* **No logs?** Confirm the Collector's user can read `/var/log/nginx/`. Run `sudo chmod +r /var/log/nginx/*.log` or add the user to the `adm` group, then restart the Collector.
* **No traces?** Confirm `ngx_otel_module` is loaded (`nginx -V`), `otel_trace` is `on`, and the `otel_exporter` endpoint matches the Collector's `otlp` gRPC port (`4317`).
* **Want structured fields at the source?** Switch Nginx to a JSON `log_format` (see the [Nginx log\_format reference](https://nginx.org/en/docs/http/ngx_http_log_module.html#log_format)) for direct field extraction.
* For general issues, see [OTel Collector troubleshooting](https://opentelemetry.io/docs/collector/troubleshooting/).

## Alternative: Fluent Bit

If your organization already runs Fluent Bit, forward the Nginx log files with its `tail` input and HTTP output. Fluent Bit handles logs only — for traces, use the OpenTelemetry Collector above.

```ini fluent-bit.conf theme={"dark"}
[INPUT]
    name  tail
    path  /var/log/nginx/access.log,/var/log/nginx/error.log
    tag   nginx

[OUTPUT]
    name        http
    match       nginx
    host        ingestion.<REGION>.bronto.io
    port        443
    tls         on
    format      json_lines
    compress    gzip
    header      x-bronto-api-key    <YOUR_API_KEY>
    header      x-bronto-dataset    nginx
    header      x-bronto-collection <YOUR_COLLECTION_NAME>
```

Set **Format** to `json_lines`, not `json` — `json` sends a single array and breaks ingestion. See [Connect Fluent Bit to Bronto](/agent-setup/fluent-bit) for installation and the full output reference.
