Vendor-Neutral Observability with OpenTelemetry and the Grafana Stack
Modern applications generate enormous amounts of telemetry data. Metrics, logs, and traces help us understand what is happening inside our…
Vendor-Neutral Observability with OpenTelemetry and the Grafana Stack

Modern applications generate enormous amounts of telemetry data. Metrics, logs, and traces help us understand what is happening inside our systems, troubleshoot issues faster, and improve reliability.
While many organizations use managed observability platforms, it is often beneficial to understand the underlying building blocks first. This is especially true when learning observability, building proof-of-concepts, or avoiding vendor lock-in.
In this article, we will build a complete open-source observability stack using:
- Grafana
- Alloy
- Prometheus
- Loki
- Tempo
- OpenTelemetry
- FastAPI
This walkthrough was developed and tested on a local macOS environment using Docker Desktop. Treat this as a minimal example, not a production-ready deployment. In a production-grade Grafana stack, Grafana Mimir could be used for metrics. For this local implementation, Prometheus is used instead to keep the setup simpler.
The complete source code is available on GitHub.
Why an Open-Source Observability Stack?
One of the biggest advantages of this stack is that it is based on open-source components and open standards, which reduces vendor lock-in. You can run the entire observability platform locally, on-premises, or in any cloud provider without being locked into a single vendor. OpenTelemetry provides a standardized way of collecting telemetry data, making migrations and multi-cloud strategies significantly easier. The same concepts, telemetry data, and instrumentation can later be used with managed platforms such as Azure Monitor, Datadog, New Relic, Dynatrace, or Grafana Cloud. More importantly, each component can be replaced independently. You can use Grafana without Loki, Prometheus without Tempo, or OpenTelemetry with a completely different backend.
Architecture Overview
The following components make up our observability platform:

- The application generates telemetry data.
- OpenTelemetry instrumentation generates logs and traces and exports them to Alloy.
- Metrics are exposed through the /metrics endpoint and scraped by Alloy before being forwarded to Prometheus.
- Alloy acts as the central collection and routing layer.
- Metrics are sent to Prometheus, logs to Loki, and traces to Tempo.
- Grafana connects to all three backends and provides a unified observability experience.
Why Alloy?
Grafana Alloy is the telemetry collector used in this solution. Its primary responsibility is to receive telemetry data and route it to the appropriate destination. Think of Alloy as the traffic controller of the observability stack. Instead of configuring every application to communicate directly with multiple backends, applications send telemetry to Alloy and Alloy handles the rest.
Benefits include:
- Centralized telemetry collection
- OpenTelemetry native support
- Flexible routing and processing
- Simplified application configuration
- Easier scaling and maintenance
Why Prometheus?
Prometheus is responsible for metrics.
Metrics answer questions such as:
- How many requests are we processing?
- What is the average response time?
- Are error rates increasing?
- Is CPU or memory usage growing?
Prometheus stores time-series data and allows querying through PromQL.
Why Loki?
Loki is responsible for logs.
Logs provide detailed information about individual events occurring within an application.
Examples include:
- Request processing details
- Errors and exceptions
- Business events
- Debug information
Unlike traditional log management systems, Loki stores labels separately and keeps log storage relatively lightweight.
This makes it a popular choice within the Grafana ecosystem.
Why Tempo?
Tempo is responsible for distributed tracing.
Traces answer questions such as:
- Which services participated in a request?
- Where is the latency coming from?
- Which operation is slowing down the application?
- What happened during a specific transaction?
Tracing becomes increasingly important as applications grow and evolve into distributed systems. In short, traces help visualize the complete lifecycle of a request.
Why Grafana?
Grafana provides the user interface for the entire observability stack.
Instead of switching between multiple tools, Grafana allows us to visualize:
- Metrics from Prometheus
- Logs from Loki
- Traces from Tempo
The real power comes from connecting metrics, logs, and traces in a single place. Instead of switching between tools during an incident, engineers can move between telemetry signals with a few clicks.
Trace to Logs and Logs to Traces
One of the most useful features in Grafana is navigating directly from a trace to the related logs and the other way around. Starting with a trace, we can immediately view all log entries associated with that request. When viewing a log entry, Grafana can extract the Trace ID and jump directly to the corresponding trace. This requires Trace IDs to be included in logs and properly configured in Grafana.

The Sample Application
To generate telemetry data, we use a minimal FastAPI application. The application exposes two endpoints:
- /signal — generates telemetry data used throughout the walkthrough
- /metrics — exposes Prometheus metrics collected by the application
The purpose of the /signal endpoint is not business functionality, but to generate metrics, logs, and traces that we can analyze throughout the observability pipeline. The /metrics endpoint returns application metrics in Prometheus format. Alloy scrapes these metrics and forwards them to Prometheus for storage and querying.
After starting the application, we generate traffic using a simple loop:
for i in {1..100}; do
curl -s http://localhost:8000/signal > /dev/null
done
This creates enough telemetry data to demonstrate the entire stack.
End-to-End Telemetry Flow
The complete flow looks like this:
-
A request hits the /signal endpoint.
-
OpenTelemetry instrumentation generates logs and traces.
-
Logs and traces are sent to Alloy.
-
The application exposes metrics through the /metrics endpoint.
-
Alloy scrapes metrics from /metrics.
-
Alloy forwards:
- metrics to Prometheus
- logs to Loki
- traces to Tempo
- Grafana visualizes and correlates telemetry across all three backends.
This creates a unified observability experience across the entire stack.
Run the solution — step by step
#1 Create Docker containers
docker compose \
-f 01_alloy.yaml \
-f 02_prometheus.yaml \
-f 03_loki.yaml \
-f 04_tempo.yaml \
-f 05_grafana.yaml \
up -d

#2 Check endpoints
alloy: http://localhost:12345
prometheus: http://localhost:9090/
loki: http://localhost:3100/ready
tempo: http://localhost:3200/ready
grafana: http://localhost:3000
#3 Run the FastAPI app
uvicorn main:app --reload
#4 Call the endpoint
for i in {1..100}; do
curl -s http://localhost:8000/signal > /dev/null
done
#5 Open Grafana
http://localhost:3000
Default credentials:
username: admin
password: admin
#6 Verify telemetry
At this point, metrics, logs, and traces should be visible in Grafana.

Final Thoughts
By combining OpenTelemetry, Alloy, Prometheus, Loki, Tempo, and Grafana, we can build a complete, vendor-neutral observability solution using open-source technologies and open standards.
More importantly, understanding these building blocks gives us greater flexibility, control, and freedom of choice. Each component can be replaced independently.
It also becomes much easier to work with managed observability platforms later, because the underlying concepts remain largely the same.
메타데이터
- post_id
- fdfe8d8378a9
- slug
- vendor-neutral-observability-with-opentelemetry-and-the-grafana-stack-fdfe8d8378a9
- url
- https://medium.com/@michalmolka/vendor-neutral-observability-with-opentelemetry-and-the-grafana-stack-fdfe8d8378a9
- canonical_url
- https://medium.com/@michalmolka/vendor-neutral-observability-with-opentelemetry-and-the-grafana-stack-fdfe8d8378a9
- author_url
- https://medium.com/@michalmolka
- status
- ok
- fetched_at
- 2026-07-09 09:01:30