Skip to content

Commit e94f3c3

Browse files
committed
Add local SLI observability stack and Grafana dashboard
Introduced a local observability stack using OpenTelemetry Collector, Prometheus, and Grafana with configuration and setup documentation. Added a prebuilt Grafana dashboard for SLI metrics, including panels for latency, success rate, error rates, and diagnostics. Enhanced the sample Web API with endpoints to emit various SLI outcomes for demonstration and testing. Updated documentation to guide users through setup and usage.
1 parent bcf7cf6 commit e94f3c3

10 files changed

Lines changed: 1006 additions & 0 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,8 @@ The default operation name is the HTTP method plus the route template (placehold
331331

332332
Try out the sample weather forecast Web API.
333333

334+
For a local Grafana/Prometheus/OpenTelemetry Collector experience, run the provisioned dashboard in [`sample\Observability\Grafana`](sample/Observability/Grafana/README.md). It shows SLI latency percentiles, success rate, failures, client errors, unknown customer diagnostics, and `<unrouted>` detection.
335+
334336
To view the metrics locally using the [.NET Aspire Dashboard](https://aspire.dev/dashboard/standalone/):
335337
336338
1. Start the Aspire dashboard:
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Local SLI Grafana dashboard
2+
3+
This sample runs a local OpenTelemetry Collector, Prometheus, and Grafana stack so you can see the value of the SLI library while running one of the sample applications.
4+
5+
## Start the dashboard stack
6+
7+
From this directory:
8+
9+
```powershell
10+
docker compose up -d
11+
```
12+
13+
Grafana starts at http://localhost:3000 with anonymous admin access enabled for local development. The SLI dashboard is provisioned automatically under **Dashboards > Trellis > Service Level Indicators**.
14+
15+
![Trellis SLI Grafana dashboard](assets/sli-grafana-dashboard.png)
16+
17+
## Run a sample app
18+
19+
In another terminal, run the Web API sample and point its OTLP exporter at the local collector:
20+
21+
```powershell
22+
$env:OTEL_EXPORTER_OTLP_ENDPOINT = "http://localhost:4317"
23+
dotnet run --project ..\..\WebApi\SampleWebApplicationSLI.csproj
24+
```
25+
26+
Generate traffic:
27+
28+
```powershell
29+
Invoke-RestMethod https://localhost:63936/WeatherForecast -SkipCertificateCheck
30+
Invoke-RestMethod https://localhost:63936/WeatherForecast/MyAction1 -SkipCertificateCheck
31+
Invoke-RestMethod https://localhost:63936/WeatherForecast/MyAction2 -SkipCertificateCheck
32+
Invoke-RestMethod https://localhost:63936/WeatherForecast/my-customer-resource-id -SkipCertificateCheck
33+
```
34+
35+
You can also run the Minimal API or API-versioned samples with the same `OTEL_EXPORTER_OTLP_ENDPOINT` environment variable.
36+
37+
## What the dashboard shows
38+
39+
The dashboard uses the SLI metric contract:
40+
41+
- `operation.duration` histogram exported to Prometheus as `operation_duration_milliseconds_*`
42+
- `CustomerResourceId`
43+
- `LocationId`
44+
- `Operation`
45+
- `Outcome`
46+
- `http.request.method`
47+
- `http.response.status.code`
48+
- optional `http.api.version`
49+
50+
Panels include:
51+
52+
- request volume by operation and outcome
53+
- p50/p95/p99 latency
54+
- success rate using `Success / (Success + Failure)`
55+
- failure and client-error rates
56+
- HTTP status-code breakdown
57+
- unknown customer diagnostics
58+
- `<unrouted>` operation detection
59+
60+
## Stop the stack
61+
62+
```powershell
63+
docker compose down
64+
```
251 KB
Loading
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
services:
2+
otel-collector:
3+
image: otel/opentelemetry-collector-contrib:0.123.0
4+
command: ["--config=/etc/otelcol/config.yaml"]
5+
volumes:
6+
- ./otel-collector-config.yaml:/etc/otelcol/config.yaml:ro
7+
ports:
8+
- "4317:4317"
9+
- "4318:4318"
10+
- "9464:9464"
11+
12+
prometheus:
13+
image: prom/prometheus:v3.3.0
14+
command:
15+
- "--config.file=/etc/prometheus/prometheus.yml"
16+
- "--storage.tsdb.path=/prometheus"
17+
- "--web.enable-lifecycle"
18+
volumes:
19+
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
20+
- prometheus-data:/prometheus
21+
ports:
22+
- "9090:9090"
23+
depends_on:
24+
- otel-collector
25+
26+
grafana:
27+
image: grafana/grafana:11.6.0
28+
environment:
29+
GF_AUTH_ANONYMOUS_ENABLED: "true"
30+
GF_AUTH_ANONYMOUS_ORG_ROLE: "Admin"
31+
GF_AUTH_DISABLE_LOGIN_FORM: "true"
32+
GF_USERS_DEFAULT_THEME: "light"
33+
volumes:
34+
- grafana-data:/var/lib/grafana
35+
- ./grafana/provisioning:/etc/grafana/provisioning:ro
36+
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro
37+
ports:
38+
- "3000:3000"
39+
depends_on:
40+
- prometheus
41+
42+
volumes:
43+
prometheus-data:
44+
grafana-data:

0 commit comments

Comments
 (0)