This repository provides a complete local observability setup for CI/CD pipelines:
- Jenkins: pipeline runner
- OpenTelemetry Collector: OTLP receiver, tail-sampling, span-to-metrics conversion
- Jaeger: traces UI
- Prometheus: metrics scraping + alert rules
- Grafana: pre-provisioned dashboards
- Pipeline simulator: generates live success/failure/slow-job metrics so dashboards are not empty
docker-compose.yml now includes:
jenkinsjaegerotel-collectorpipeline-simulatorprometheusgrafana
Also added:
- persistent volumes for Prometheus and Grafana
- service startup dependencies
- exposed ports for UI and telemetry endpoints
- fixed port conflict by keeping Jaeger host port only on
16686and using OTLP host ports on collector
otel-collector-config.yaml now includes:
- OTLP receiver (
4317gRPC,4318HTTP) tail_samplingpolicies- keep errors
- keep slow traces (>30s)
- sample 20% of normal traces
spanmetricsconnector- Prometheus exporter for metrics at
:8889 - health check extension at
:13133
Added:
prometheus/prometheus.ymlprometheus/alert_rules.yml
Scrape jobs include:
- Prometheus self-metrics
- OTel Collector internal metrics
- OTel spanmetrics endpoint
- Pipeline simulator
- Jenkins
/prometheusendpoint (when enabled)
Alert rules included:
PipelineFailureRateHighPipelineSlowJobsDetectedOTelCollectorDroppingSpans
Added:
grafana/provisioning/datasources/prometheus.ymlgrafana/provisioning/dashboards/dashboard.ymlgrafana/provisioning/dashboards/json/pipeline-observability.json
Dashboard: Pipeline Observability
- Success rate (5m)
- Failure rate / sec
- Slow jobs / sec (>10s)
- Pipeline throughput
- p50/p95 duration by job type
- OTel collector ingestion
Added pipeline-simulator (Python + prometheus_client) that continuously emits:
pipeline_job_runs_totalpipeline_job_success_totalpipeline_job_failures_totalpipeline_job_duration_secondshistogrampipeline_job_in_progress
This gives immediate, realistic CI-like metrics for testing.
Jenkins/Instrumented Apps (OTLP traces)
|
v
OTel Collector
/ | \
v v v
Jaeger spanmetrics collector metrics
|
v
Prometheus
|
v
Grafana
Pipeline simulator ---> Prometheus ---> Grafana
docker compose up -d --build
docker compose ps- Jenkins: http://localhost:8080
- Jaeger: http://localhost:16686
- Prometheus: http://localhost:9090
- Grafana: http://localhost:3000
- Username:
admin - Password:
admin
- Username:
docker compose psExpected: all 6 services are Up.
Open: http://localhost:9090/targets
Expected targets UP:
prometheusotel_collector_internalotel_spanmetricspipeline_simulatorjenkins(optional, depends on Jenkins endpoint availability)
In Prometheus Graph UI, run:
pipeline_job_runs_totalpipeline_job_success_totalpipeline_job_failures_totalpipeline_job_duration_seconds_bucket
Expected: non-empty data and increasing counters.
In Grafana, open Observability > Pipeline Observability.
Expected: panels update every 10s with live numbers and timeseries.
Open http://localhost:16686, select service, click Find Traces.
Expected:
- Jaeger internal traces always visible
- Jenkins traces visible after Jenkins OTel plugin is configured and jobs are run
Use this to complete trace validation from Jenkins to Jaeger via collector.
- Open Jenkins: http://localhost:8080
- Go to Manage Jenkins > Plugins
- Install/verify OpenTelemetry plugin
- Go to Manage Jenkins > System
- Find OpenTelemetry section and set:
- Endpoint:
http://otel-collector:4318(if Jenkins uses Docker network route) - Protocol: OTLP/HTTP
- Service name:
jenkins(or your preferred name)
- Endpoint:
- Save configuration
- Run 2-3 pipelines (success + failure + slow)
- Open Jaeger and verify service traces for Jenkins
If Jenkins cannot resolve otel-collector, use http://localhost:4318.
Use this pipeline in Jenkins to generate realistic signal:
pipeline {
agent any
stages {
stage('Fast Success') {
steps {
echo 'Quick successful stage'
sleep 2
}
}
stage('Slow Stage') {
steps {
echo 'Simulate slow job stage'
sleep 20
}
}
stage('Optional Failure') {
steps {
script {
if (env.BUILD_NUMBER.toInteger() % 3 == 0) {
error('Simulated failure for observability testing')
}
}
}
}
}
}Your setup is correct when all of these are true:
- all services are running (
docker compose ps) - Prometheus targets are
UP - Prometheus queries return live data
- Grafana dashboard panels show values
- Jaeger shows traces for instrumented services
- collector logs show healthy startup without crash loops
# Start
docker compose up -d --build
# Stop
docker compose down
# Logs
docker compose logs -f
docker compose logs --tail=100 otel-collector
docker compose logs --tail=100 prometheus
docker compose logs --tail=100 grafanaotlp alias is deprecatedin collector: warning only, non-blocking- Grafana plugin auto-update permission errors (bundled plugin files): usually non-blocking for this stack
- Grafana 401 session token rotation warnings: expected during session refresh/re-login
These screenshots show live data from your running stack.
This implementation aligns with the Jenkins GSoC idea:
Project: Use OpenTelemetry for Jenkins Jobs on ci.jenkins.io
Goal: Enhance observability of Jenkins jobs using OpenTelemetry
Focus areas: OpenTelemetry, observability, DevOps
What this repository demonstrates toward that goal:
- OpenTelemetry-based pipeline telemetry architecture
- Trace ingestion and tail-based sampling strategy
- Metrics pipeline with Prometheus
- Dashboarding and health visualization with Grafana
- Practical validation workflow for logs, metrics, traces, failures, and slow jobs
Current repository status is strong and presentation-ready. The setup already validates:
- working multi-service observability architecture
- live Prometheus metrics
- live Grafana dashboarding
- live Jaeger tracing UI
- documented runbook for reproducible testing
For production-like Jenkins validation, ensure Jenkins pipeline traces are sent to collector (otel-collector:4318 or localhost:4318) and confirm Jenkins-specific traces in Jaeger.


