"In 20 minutes, you will see exactly why logs-only troubleshooting is painful, and how metrics + logs + traces together make incident triage dramatically faster."
- Setup and framing (2 min)
- Simple endpoint demo (4 min)
- Complex checkout demo (6 min)
- Failure investigation story (8 min)
- Wrap-up and Q&A (3-5 min)
- Start stack:
docker compose up --build-
Open:
- API: http://localhost:8080
- Grafana: http://localhost:3000
-
In Grafana:
- Confirm dashboard Observability Demo Overview is visible.
- Open Explore and verify datasource health with these checks:
- Loki datasource selected, query:
{app="demo-api"}, time range: Last 15 minutes. - Tempo datasource selected, search service name
logging-analysis-demo-api, time range: Last 15 minutes. - If both return No data, generate one request with
Invoke-RestMethod "http://localhost:8080/demo/simple/ping?delayMs=20"and retry. - "No data" is healthy only when datasource test passes and no traffic has been sent yet.
- Loki datasource selected, query:
- Keep a terminal ready for API calls.
Talking points:
- "Most teams start with logs, but logs alone break down under concurrency and distributed workflows."
- "We need three lenses: metrics for shape, logs for detail, traces for causality."
- "This app has both a simple and a complex scenario so we can compare the experience."
Run:
Invoke-RestMethod "http://localhost:8080/demo/simple/ping?delayMs=20"
Invoke-RestMethod "http://localhost:8080/demo/simple/ping?delayMs=200"Narrate:
- "Same endpoint, different latency."
- "Prometheus captures timing distributions."
- "Loki captures contextual logs for each request."
In Grafana dashboard, point at:
- Request Rate
- Checkout Latency panel (it is expected to show No data until
/demo/checkoutor/demo/load/spikeis called; use this to explain metric scope)
Run:
Invoke-RestMethod "http://localhost:8080/demo/simple/error" -SkipHttpErrorCheckNarrate:
- "This is a deliberate failure to simulate a user-visible issue."
- "Errors panel rises quickly - metrics tell us there is a problem, not why."
In Grafana:
- Show error panel movement
- Open logs panel and point out warning/error entries
Run one checkout:
$body = @{
orderId = "ord-talk-001"
tenant = "retail"
totalAmount = 650.00
items = @(
@{ sku = "SKU-500"; quantity = 2; unitPrice = 125.00 },
@{ sku = "SKU-900"; quantity = 1; unitPrice = 400.00 }
)
} | ConvertTo-Json -Depth 5
Invoke-RestMethod "http://localhost:8080/demo/checkout" -Method Post -Body $body -ContentType "application/json"Narrate:
- "Checkout is multi-step: inventory, payment, shipment."
- "A single result code hides where time was actually spent."
In Grafana Explore:
- Set datasource to Loki and time range to Last 15 minutes.
- Run log query:
{app="demo-api"} |= "checkout" - If there are too many rows, narrow to your test order id:
{app="demo-api"} |= "ord-talk-001"
- Open one matching row and point out:
- Message text like "Checkout started" or "Checkout completed"
- Context fields:
orderId,tenant, anditemCount - Trace fields:
TraceIdandSpanId
- Pivot to trace:
- Click the TraceId link from the log row (or copy TraceId into Tempo search).
- Switch datasource to Tempo and show the trace details:
- Root span:
checkout.process - Child spans:
checkout.reserve_inventory,checkout.capture_payment,checkout.create_shipment - Use span duration to identify the slow or failing step.
- Narrate the correlation story:
- "Metric spike tells us something changed."
- "Logs tell us which order/tenant was impacted."
- "Trace shows exactly which step consumed time or failed."
If you still see no rows in Loki after a checkout call:
- Confirm time range is Last 15 minutes and not a custom stale range.
- Run broader query:
{app="demo-api"}. - Trigger a fresh checkout call and rerun query after 5-10 seconds.
- Validate API is receiving requests:
docker compose logs --tail=50 demo-api.
Key line:
- "Metrics told us something changed, logs gave context, traces told us exactly where and in what order."
First, force one failure mode so the incident is deterministic:
$faults = @{
forceInventoryFailure = $false
forcePaymentFailure = $true
} | ConvertTo-Json
Invoke-RestMethod "http://localhost:8080/demo/admin/faults" -Method Post -Body $faults -ContentType "application/json"Then run load:
Invoke-RestMethod "http://localhost:8080/demo/load/spike?seconds=20&concurrency=12" -Method PostNarrate while charts move in the dashboard:
- "This simulates a traffic spike."
- "Watch request rate and p95 latency rise together."
- "Because payment failure is forced, failures are now deterministic and easy to investigate live."
In Grafana, demonstrate investigation path:
- Dashboard symptom:
- Errors Last 5m increases.
- Checkout Outcomes shows failure rate climbing.
- Logs in Explore (Loki datasource):
- Query:
{app="demo-api"} |= "CAUSE checkout failure" - Highlight
SourceHintfield value, for exampleCheckoutEngine.CapturePaymentAsync.
- Traces in Explore (Tempo datasource):
- Pivot from TraceId in the same log row.
- Show failed trace and span where
checkout.capture_paymentis the failing step.
- Exact source lines in code:
Select-String -Path ".\src\Demo.Api\Program.cs" -Pattern "CAUSE checkout failure at capture_payment|CapturePaymentAsync" |
ForEach-Object { "{0}:{1}: {2}" -f $_.Path, $_.LineNumber, $_.Line.Trim() }- Explain remediation:
- "Root cause is isolated to payment step logic."
- "We can now fix this method directly instead of guessing from generic failures."
After the demo, reset fault toggles:
$reset = @{
forceInventoryFailure = $false
forcePaymentFailure = $false
} | ConvertTo-Json
Invoke-RestMethod "http://localhost:8080/demo/admin/faults" -Method Post -Body $reset -ContentType "application/json"Suggested incident narrative:
- "Pager fires: checkout failures increased."
- "Dashboards confirm symptom and blast radius."
- "Logs show impacted tenant/order patterns."
- "Logs include SourceHint to the failing method: CheckoutEngine.CapturePaymentAsync."
- "Traces isolate the failure path to checkout.capture_payment span."
- "Mitigation: rollback fault flag or deploy fix, then verify metrics recovery."
Talking points:
- "Use metrics for fast detection and SLOs."
- "Use logs for rich event context."
- "Use traces for path-level root cause analysis."
- "The value is not any one tool; it is correlation across all three."
- Add tenant-specific alerting and compare behavior by tenant label.
- Add a downstream fake dependency API and propagate trace context over HTTP.
- Add exemplars and link high-latency metric points directly to traces.
- Validate containers:
docker compose ps- Tail API logs:
docker compose logs -f demo-api- Restart stack quickly:
docker compose down
docker compose up --build