Skip to main content
Hey there — welcome back. In this lesson we move from theory into practice. Observability is more than collecting logs, metrics, and traces — it’s using those signals to answer real operational questions when systems misbehave: what happened, where, when, and why. This guide shows how to connect signals to real problems and turn dashboards and alerts into actionable investigations. By the end you’ll see how observability becomes actionable insight, not just data. Systems will fail in unexpected ways. Traditional monitoring (is the server up? is CPU < 80%?) often doesn’t help when users report that checkout is broken. Observability goes deeper: it lets you ask and answer new diagnostic questions using combined metrics, structured logs, and distributed traces.
A slide titled "Observability – Overview" showing a person at a laptop with an alert "Checkout page broken" alongside an iceberg diagram that contrasts shallow monitoring (server up, CPU, requests) above the water with deeper observability (what/when/where/why) below the surface. The observability section lists details like error rate spike, time after deployment, payment DB connection, and missing index in query.
Internalizing an observable mindset is essential for effective SRE work: assume unknown failures, enable unexpected questions, and focus on system behavior (not just simplistic health checks).
A presentation slide titled "Observability – Overview." It shows an "Observability Mindset" circle linked to three principles: assume unknown failures; enable unexpected questions; and understand behavior, not just health.

Hands-on: spin up the KodeKloud Record Store

We’ll run the Record Store app locally, generate traffic, and inspect the metrics, logs, and traces. Start the Compose stack (from repo root):
You should see containers start. Example service logs (truncated):
Generate test traffic and logs:
Example output from the log-generation script (trimmed and cleaned):

The three pillars of observability

Observability generally stands on three pillars:
  • Metrics — tell you “what” is happening (counts, latencies, throughput).
  • Logs — explain “why” (context, errors, enriched fields).
  • Traces — show “where” time is spent across distributed services.
A slide titled "The Three Pillars – A Deep Dive" showing three colored pillar icons labeled Metrics (What happened), Logs (Why it happened), and Traces (Where it happened). The icons are blue/purple, orange, and green respectively.

Metrics: instrument, expose, scrape, visualize

Typical flow:
  • Define counters, histograms, and gauges in the application.
  • Expose them on /metrics.
  • Have Prometheus scrape them.
  • Visualize in Grafana and evaluate rules with Prometheus (Alertmanager).
Minimal example (metrics.py):
Application-specific metrics (excerpt from the Record Store):
Middleware centralizes recording metrics for each HTTP request instead of scattering metric code through business logic. Example FastAPI middleware (records counts, durations, and annotates OpenTelemetry spans):
Normalize dynamic route segments (e.g., /products/) for metric labels to avoid high-cardinality label explosions.
Avoid tagging metrics with high-cardinality values (user IDs, raw UUIDs). High-cardinality labels can cause large memory and storage usage in Prometheus.
PromQL examples:
You can view these metrics in Grafana dashboards for latency, throughput, error rate, and availability.
A presentation slide titled "The Three Pillars – A Deep Dive" showing icons for Metrics, Logs, and Traces and a flow from Python Code → Prometheus Metrics → Dashboards. The slide includes a Grafana dashboard screenshot displaying user-facing metrics like response time, throughput, error rate, and availability.
If you open the project in your editor you’ll find the API source files, Docker Compose, and telemetry code.
A screenshot of Visual Studio Code showing the Welcome page and Explorer sidebar for a project (kodekloud-records-store-web-app) with files like docker-compose.yaml, Dockerfile, and test_traffic.sh. The right pane displays Start options and Walkthroughs/tutorial cards.
A typical set of imports in main.py (cleaned and corrected):
Prometheus configuration (prometheus.yaml) — consolidated example:
You can view what Prometheus will scrape at the metrics endpoint, e.g. http://localhost:8000/metrics. Example output (truncated and cleaned):

Logs: structured, enriched, and correlated

Structured JSON logs are critical for filtering, searching, and correlating with traces and metrics. Include trace_id and span_id in logs so you can join traces and logs for root-cause analysis. Example structured log entry:
The app uses a small structured logger that enriches messages with trace context and extra fields:
Container logs are collected by Fluent Bit (via Docker Fluentd/Fluent Bit driver), which attaches container metadata and forwards structured logs to Grafana Loki. Loki stores labeled log streams efficiently and LogQL allows queries that correlate logs to metrics and traces.
A presentation slide titled "The Three Pillars – A Deep Dive" with three pillar icons on the left labeled Metrics, Logs, and Traces. On the right it lists four structured-logging benefits: machine-parsable for analysis, consistent fields across services, rich context for debugging, and correlation with traces and metrics.

Traces: visualize the request journey

Traces show the request journey across services. Each span is a timed operation with attributes and events. Example checkout trace (summary):
Traces combined with structured logs and metrics let you pinpoint bottlenecks and errors. Jaeger is used here for trace visualization: search by service, operation, tags, or trace ID.
A screenshot of the Jaeger UI showing a timeline scatter/bubble chart of trace durations with a search/filter sidebar on the left. Below the chart is a list of 20 traces for the service "kodekloud-record-store-api-dev," including operations like GET /health and GET /metrics.
Generate test traces:
Example responses:
Click a trace in Jaeger to inspect span timings, tags, and process details.
A screenshot of the Jaeger UI showing a distributed trace for "kodekloud-record-store-api-dev: GET /trace-test," with a timeline of spans, durations, and a highlighted "test-span" containing tags and process info. The view displays span bars, timing markers, and trace details like start time and total duration.
When an error occurs, expand the trace to find the error span and related logs.
A browser screenshot of the Jaeger UI showing a trace for "kodekloud-record-store-api-dev: GET /error-test" with a timeline of spans, durations, and span details. The panel shows an "error-span" entry and a warning about a duplicate tag "error:true".

The observability stack wiring

All components are wired together in Docker Compose: application services (API, worker), DB, message broker, Prometheus, Pushgateway, Grafana, Alertmanager, Loki, Fluent Bit, Jaeger, and Blackbox Exporter.
A diagram titled "Implementing Observability at KodeKloud Records Store" showing the observability stack: application services (API/FastAPI, Worker/Celery, DB/PostgreSQL, RabbitMQ), metrics & monitoring tools (Prometheus, Pushgateway, Grafana, Alertmanager, Blackbox Exporter), logging (Loki, Fluent Bit) and distributed tracing (Jaeger).
Example Compose fragments showing environment and logging driver configuration:
From a tooling perspective, the stack includes:
A screenshot of an "Observability Tools" slide listing a metrics stack (Prometheus, Pushgateway, Grafana, Alertmanager, Blackbox Exporter) with their ports and brief descriptions. On the right is a Jaeger-like UI panel for searching and filtering traces.
A presentation slide titled "Observability Tools" listing a logging stack: Fluent Bit (Port 24224) to collect Docker logs, Loki (Port 3100) to store structured logs, and Grafana to display logs with metrics. On the right is a Jaeger UI trace search panel.
Putting it all together: a user request reaches FastAPI; middleware and instrumentation generate metrics, structured logs, and traces; Prometheus scrapes metrics and evaluates alerts; logs flow to Loki via Fluent Bit; traces flow to Jaeger via OpenTelemetry exporters. Alertmanager routes alerts to the right channels. Grafana ties metrics, logs, and traces together to support fast investigation.
A presentation slide titled "The Three Pillars – A Deep Dive" showing three pillar icons labeled Metrics, Logs, and Traces on the left and a boxed summary on the right titled "What This Trace Reveals" with notes: Total Request Time 1.35s, Bottleneck: Processing delay → 800ms, Database <150ms, and Investigation Focus: Optimize background tasks.

Wrap-up

Thanks for sticking with this practical lesson. We covered how metrics, logs, and traces are produced, collected, stored, and visualized in a concrete stack, and how they combine to help you detect, investigate, and resolve problems faster. For deeper exploration, check the resources below. You can also explore data sources and visualization fundamentals in the accompanying material.

Watch Video