This repository demonstrates how to use OpenTelemetry auto-instrumentation for Go and Python applications with Grafana Tempo for distributed tracing. The lab includes demo applications that generate various types of traces and a complete observability stack.
This lab showcases:
- OpenTelemetry Auto-Instrumentation: Automatic trace generation without code changes for both Go and Python
- Grafana Tempo: Distributed tracing backend for storing and querying traces
- Demo Applications: Sample applications in Go and Python to generate realistic traces
- Grafana Dashboard: Pre-configured visualization for exploring traces
┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Go Application │────▶│ OTel Auto-Instr │────▶│ Tempo │
└─────────────────┘ └──────────────────┘ └──────┬──────┘
│
▼
┌─────────────┐
│ Grafana │
└─────────────┘
- Docker and Docker Compose
- Go 1.19 or later (for Go example)
- Python 3.8 or later (for Python example)
- Make (optional, but recommended)
- curl and jq (for testing endpoints)
git clone https://github.com/digitalis-io/opentelemtry-local.git
cd opentelemtry-local
make up
make up-python
Or without Make:
# For Go
docker compose up -d
# For Python
docker compose -f docker-compose.python.yaml up -d
This starts:
- Tempo: Distributed tracing backend (ports 3200, 4317, 4318, 9411, 14268)
- Grafana: Visualization UI (port 3000)
- Memcached: Cache for Tempo query performance
- Auto-Instrumentation: Automatic instrumentation for your chosen language
# Build the application
make build-app
# Run with auto-instrumentation
make run-app
The Python application starts automatically when you run make up-python
. No additional steps needed!
The demo application will be available at http://localhost:8080
# Test all endpoints
make test-all
# Or test individual endpoints
make test-good # Returns 200 OK
make test-bad # Returns 500 Error
make test-admin # Returns 401 Unauthorized
make test-health # Health check
- Open Grafana at http://localhost:3000 (no login required)
- Navigate to Explore in the left sidebar
- Select Tempo as the data source
- Search for traces using:
- Service name:
test-application
- Trace ID (if you have one)
- Tags like
http.status_code=500
- Service name:
A simple HTTP server (available in both Go and Python) with endpoints that simulate different scenarios:
GET /
- Service informationGET /good
- Successful request with database calls and external API simulationGET /bad
- Failed request that returns 500 errorGET /admin
- Unauthorized request that returns 401GET /health
- Health check endpoint
Each endpoint generates realistic traces with:
- Simulated database operations
- External API calls
- Variable latencies
- Different error scenarios
An HTTP client that makes requests to various external APIs:
- Tests both successful and failing requests
- Demonstrates distributed tracing across services
- Shows how traces propagate through HTTP headers
Run it with:
make run-client
Run make help
to see all available commands:
Docker Commands:
make up - Start all services
make down - Stop all services
make restart - Restart all services
make logs - View logs from all services
make clean - Stop services and clean up data
Application Commands:
make build-app - Build the test application
make run-app - Run test application with auto-instrumentation
make run-client - Run the HTTP client test application
Testing Commands:
make test-good - Send a successful request
make test-bad - Send a failing request
make test-admin - Send an unauthorized request
make test-health - Check service health
make test-all - Run all endpoint tests
The OpenTelemetry Go auto-instrumentation uses eBPF to automatically inject tracing code into your Go application without modifying the source code. The go-auto
service in the Docker Compose file:
- Monitors for the specified binary (
OTEL_GO_AUTO_TARGET_EXE
) - Injects instrumentation at runtime
- Sends traces to Tempo using OTLP protocol
Configuration is done through environment variables:
OTEL_EXPORTER_OTLP_ENDPOINT
: Where to send traces (Tempo)OTEL_SERVICE_NAME
: Name of your service in tracesOTEL_PROPAGATORS
: Trace context propagation format
-
Search for Traces:
- Use the search bar to filter by service name
- Filter by duration, status code, or custom tags
- Use TraceQL for advanced queries
-
Trace View:
- See the full request flow
- Identify bottlenecks and slow operations
- View tags and logs associated with spans
-
Service Graph (if enabled):
- Visualize service dependencies
- See request rates and error rates
- Identify critical paths
# Find slow requests (> 100ms)
{ duration > 100ms }
# Find failed requests
{ status.code = 2 }
# Find requests to specific endpoint
{ http.target = "/bad" }
# Complex query
{ service.name = "test-application" && duration > 50ms && http.status_code = 500 }
-
Check if all services are running:
make ps
-
Check logs for errors:
make logs-tempo make logs-go-auto
-
Ensure the application binary name matches
OTEL_GO_AUTO_TARGET_EXE
in docker compose.yaml
-
Make sure to build the application first:
make build-app
-
Check that port 8080 is not in use
- Verify Tempo is running and healthy
- Check the data source configuration in Grafana
- Ensure the Tempo URL is correct (
http://tempo:3200
)
To generate more traces for testing:
# Install hey if not already installed
go install github.com/rakyll/hey@latest
# Run load test
make load-test
This sends 100 concurrent requests to each endpoint.
This lab includes both Go and Python versions of the demo application. The Python version (test-application.py
) provides the same endpoints and functionality as the Go version.
To switch from Go to Python auto-instrumentation:
-
Use the Python Docker Compose file:
make up-python # or docker compose -f docker-compose.python.yaml up -d
-
Key differences:
- Python uses
opentelemetry-instrument
command for auto-instrumentation - No binary compilation needed - Python runs directly
- Instrumentation is configured via environment variables in the container
- Python uses
-
Python-specific environment variables:
- OTEL_SERVICE_NAME=test-application-python - OTEL_TRACES_EXPORTER=otlp - OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4318 - OTEL_PYTHON_LOG_CORRELATION=true
- Update
OTEL_GO_AUTO_TARGET_EXE
in docker-compose.yaml to match your binary name - Mount your application directory in the
go-auto
service - Configure the OTLP endpoint to send traces to Tempo
- Create a new service in docker-compose.python.yaml
- Install OpenTelemetry packages:
opentelemetry-distro
andopentelemetry-exporter-otlp
- Run with:
opentelemetry-instrument python your-app.py
- Set the same environment variables as shown in the Python example
Edit tempo.yaml
to:
- Adjust retention periods
- Configure different storage backends
- Enable additional features like metrics generation
The data-sources.yml
file configures Tempo as a data source. Modify it to:
- Add authentication if needed
- Configure additional data sources
- Enable streaming for better performance
- Integrate with Your Application: Apply auto-instrumentation to your own Go or Python services
- Add Custom Spans: Use the OpenTelemetry SDK for manual instrumentation
- Set Up Alerting: Configure alerts based on trace data
- Scale Up: Deploy Tempo in a production environment with proper storage
- Correlate with Metrics: Add Prometheus for metrics alongside traces
- OpenTelemetry Documentation
- Grafana Tempo Documentation
- OpenTelemetry Go Auto-Instrumentation
- OpenTelemetry Python Documentation
- Grafana Explore Traces App
This project is licensed under the MIT License - see the LICENSE file for details.