This scenario shows a full OpenTelemetry metrics pipeline through Grafana Alloy.
A Python app generates counters, histograms, and up-down counters with the OpenTelemetry SDK and sends them to Alloy over OTLP.
Alloy batches the metrics, adds a deployment.environment resource attribute, and exports them to Prometheus over OTLP/HTTP for visualization in Grafana.
Ensure you have the following:
- Docker and Docker Compose.
- Ports 3000 for Grafana, 9090 for Prometheus, 12345 for the Alloy UI, and 4317 and 4318 for OTLP free on the host.
+------------------+ +-------+ +-------------+ +---------+
| app | OTLP | Alloy | OTLP | Prometheus | | |
| demo-metrics-app |------>| batch | HTTP | OTLP rcvr |------>| Grafana |
| | gRPC | xform | | | | |
+------------------+ +-------+ +-------------+ +---------+
- app: Python container that emits OTLP metrics every second to
alloy:4317over gRPC. - Alloy: Receives OTLP metrics, batches them, adds
deployment.environment = "demo", and exports to Prometheus athttp://prometheus:9090/api/v1/otlp. - Prometheus: Ingests metrics through its native OTLP receiver with native histogram support enabled.
- Grafana: Queries metrics through a provisioned Prometheus data source.
-
Clone the repository if you haven't already:
git clone https://github.com/grafana/alloy-scenarios.git -
Install the scenario with one of these options:
Option 1: From the scenario directory
Use the default image tags in
docker-compose.yml.- Navigate to this scenario:
cd alloy-scenarios/otel-metrics-pipeline - Deploy the scenario:
docker compose up -d
Option 2: From the repository root
Use pinned image versions from
image-versions.envfor Grafana, Prometheus, and Alloy.- Deploy the scenario:
./run-example.sh otel-metrics-pipeline
- Navigate to this scenario:
-
From the
otel-metrics-pipelinedirectory, check that all containers are up:docker compose psYou should see
app,alloy,prometheus, andgrafana.The
appcontainer installs Python dependencies on first start, so metrics may take a minute to appear.
- Grafana at http://localhost:3000: Query metrics in Explore with the Prometheus data source, with no login required.
- Alloy UI at http://localhost:12345: Pipeline graph, component health, and live debug views.
- Prometheus at http://localhost:9090: Query ingested OTLP metrics directly.
The config.alloy pipeline has four components:
otelcol.receiver.otlp.default: Receives OTLP metrics over gRPC and HTTP.otelcol.processor.batch.default: Batches metrics for efficient export.otelcol.processor.transform.default: Setsdeployment.environment = "demo"on the resource.otelcol.exporter.otlphttp.prometheus: Sends metrics to Prometheus athttp://prometheus:9090/api/v1/otlp.
livedebugging is enabled so you can inspect the pipeline in the Alloy UI.
The demo app emits these OTLP metrics:
app.requests.total: Counter of HTTP requests by endpoint, method, and statusapp.errors.total: Counter of errors by endpointapp.request.duration: Histogram of request latency in millisecondsapp.active_users: Up-down counter of active users by region
Prometheus translates OTLP names to its naming conventions. Dots become underscores and units are appended as suffixes.
-
Open Grafana at http://localhost:3000 and go to Explore. Select the Prometheus data source and run these PromQL queries:
app_requests_total: Total requests by endpoint, method, and statusapp_errors_total: Total errors by endpointapp_request_duration_milliseconds_bucket: Request latency histogram bucketsapp_active_users: Current active users by regionapp_requests_total{deployment_environment="demo"}: Requests with the resource attribute added by Alloy
-
To inspect the pipeline in real time, open the Alloy UI at http://localhost:12345. Select
otelcol.receiver.otlp.default,otelcol.processor.batch.default,otelcol.processor.transform.default, orotelcol.exporter.otlphttp.prometheusfrom the component graph to use live debug.
- Change attribute transforms: Edit
otelcol.processor.transform.defaultinconfig.alloy. - Use the OTel Engine: Run
docker compose -f docker-compose.yml -f docker-compose-otel.yml up -dto load the equivalent pipeline fromconfig-otel.yamlinstead of River syntax. - Promote more resource attributes: Edit
otlp.promote_resource_attributesinprom-config.yaml.
Diagnose container startup failures, missing metrics, and port conflicts.
Run docker compose ps to check the status of each container.
If any container has exited, run docker compose logs <SERVICE_NAME> to read the failure reason.
Replace <SERVICE_NAME> with the name of the service that exited, such as app, alloy, or prometheus.
For Alloy specifically, the most common cause is a syntax error in config.alloy.
The app container runs pip install on first start, which can take up to a minute.
Run docker compose logs app and check that you see Starting OTLP metrics generator....
Open the Alloy UI at http://localhost:12345 and check that all components show a healthy status.
In Grafana, select the Prometheus data source in Explore and run app_requests_total.
Ports 3000 for Grafana, 9090 for Prometheus, 12345 for Alloy, and 4317 and 4318 for OTLP must be free before you start the stack.
If another service uses one of these ports, edit the port mapping in docker-compose.yml for the conflicting service before you run docker compose up -d.
Run docker compose down from the otel-metrics-pipeline directory.
- Alloy components: https://grafana.com/docs/alloy/latest/reference/components/
otelcol.processor.transformreference: https://grafana.com/docs/alloy/latest/reference/components/otelcol/otelcol.processor.transform/- Prometheus OTLP receiver: https://prometheus.io/docs/guides/opentelemetry/
- More examples: https://github.com/grafana/alloy-scenarios