Skip to content

Commit fcb2e65

Browse files
authored
Instrument Docker Compose setups to enable Application Observability (#228)
1 parent 0e1aa3c commit fcb2e65

File tree

9 files changed

+125
-27
lines changed

9 files changed

+125
-27
lines changed

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,19 @@ Now, you can log in to [Grafana Cloud](https://grafana.com/products/cloud/) and
173173

174174
To find the labels applied to the telemetry data, refer to [cloud.alloy](./alloy/cloud.alloy) and [docker-compose-cloud.yaml](./docker-compose-cloud.yaml) .
175175

176-
### Monitor frontend with Grafana Cloud Frontend Observability
176+
### Monitor QuickPizza with Grafana Cloud Application and Frontend Observability
177177

178-
To enable [Grafana Cloud Frontend Observability](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/) for QuickPizza:
178+
The Docker Compose setup is fully instrumented out of the box, so you can jump right into Grafana Cloud Observability apps and start observing the inner workings of the QuickPizza service components.
179+
180+
To enable [Grafana Cloud Application Observability](https://grafana.com/docs/grafana-cloud/monitor-applications/application-observability/) for QuickPizza:
181+
182+
1. In your Grafana Cloud instance, navigate to **Observability > Application**.
183+
2. Click on **Enable metrics generation** to enable the usage of Application Observability.
184+
3. Interact with the QuickPizza app to generate traffic. After a few minutes, the QuickPizza components will be automatically discovered and displayed in the UI.
185+
186+
![Application Observability](./docs/images/grafana-cloud-application-application-observability-quickpizza.png)
187+
188+
To enable [Grafana Cloud Frontend Observability](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/):
179189

180190
1. In Grafana Cloud, create a new Frontend Observability application and set the domain to `http://localhost:3333`.
181191
2. Copy the application's Faro web URL.

alloy/cloud.alloy

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,30 @@ otelcol.receiver.otlp "default" {
99
}
1010

1111
output {
12-
traces = [otelcol.processor.batch.default.input]
12+
traces = [
13+
otelcol.processor.batch.default.input,
14+
otelcol.connector.host_info.default.input,
15+
]
16+
}
17+
}
18+
19+
otelcol.connector.host_info "default" {
20+
host_identifiers = ["container.name", "container.id", "service.name"]
21+
metrics_flush_interval = "10s"
22+
23+
output {
24+
metrics = [otelcol.exporter.prometheus.otlp_metrics.input]
1325
}
1426
}
27+
otelcol.exporter.prometheus "otlp_metrics" {
28+
forward_to = [
29+
grafana_cloud.stack.receivers.metrics,
30+
]
31+
}
1532

1633
otelcol.processor.batch "default" {
1734
output {
18-
metrics = []
19-
logs = []
20-
traces = [
21-
grafana_cloud.stack.receivers.traces,
22-
]
35+
traces = [grafana_cloud.stack.receivers.traces]
2336
}
2437
}
2538

@@ -33,6 +46,8 @@ prometheus.scrape "default" {
3346
"__address__" = env("QUICKPIZZA_HOST"),
3447
"job" = "quickpizza",
3548
"instance" = "local",
49+
"service_name" = "quickpizza",
50+
"service_namespace" = "quickpizza",
3651
},
3752
]
3853
}
@@ -65,6 +80,10 @@ loki.source.docker "default" {
6580
host = "unix:///var/run/docker.sock"
6681
targets = discovery.relabel.quickpizza.output
6782
forward_to = [grafana_cloud.stack.receivers.logs]
83+
labels = {
84+
service_name = "quickpizza",
85+
service_namespace = "quickpizza",
86+
}
6887
}
6988

7089
import.git "grafana_cloud" {

alloy/local-tempo.yaml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
stream_over_http_enabled: true
2+
server:
3+
http_listen_port: 3200
4+
log_level: info
5+
6+
query_frontend:
7+
search:
8+
duration_slo: 5s
9+
throughput_bytes_slo: 1.073741824e+09
10+
metadata_slo:
11+
duration_slo: 5s
12+
throughput_bytes_slo: 1.073741824e+09
13+
trace_by_id:
14+
duration_slo: 5s
15+
16+
distributor:
17+
receivers:
18+
otlp:
19+
protocols:
20+
grpc:
21+
endpoint: "tempo:4317"
22+
http:
23+
endpoint: "tempo:4318"
24+
25+
ingester:
26+
max_block_duration: 5m # cut the headblock when this much time passes. this is being set for demo purposes and should probably be left alone normally
27+
28+
compactor:
29+
compaction:
30+
block_retention: 1h # overall Tempo trace retention. set for demo purposes
31+
32+
metrics_generator:
33+
registry:
34+
external_labels:
35+
source: tempo
36+
cluster: docker-compose
37+
storage:
38+
path: /var/tempo/generator/wal
39+
remote_write:
40+
- url: http://prometheus:9090/api/v1/write
41+
send_exemplars: true
42+
traces_storage:
43+
path: /var/tempo/generator/traces
44+
45+
storage:
46+
trace:
47+
backend: local # backend configuration to use
48+
wal:
49+
path: /var/tempo/wal # where to store the wal locally
50+
local:
51+
path: /var/tempo/blocks
52+
53+
overrides:
54+
defaults:
55+
metrics_generator:
56+
processors: [service-graphs, span-metrics, local-blocks] # enables metrics generator
57+
generate_native_histograms: both

alloy/local.alloy

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ otelcol.processor.batch "default" {
2525

2626
// Scrape Metrics
2727
prometheus.scrape "default" {
28+
scrape_interval = "60s"
2829
forward_to = [
2930
prometheus.remote_write.default.receiver,
3031
]
@@ -33,6 +34,8 @@ prometheus.scrape "default" {
3334
"__address__" = env("QUICKPIZZA_HOST"),
3435
"job" = "quickpizza",
3536
"instance" = "local",
37+
"service_name" = "quickpizza",
38+
"service_namespace" = "quickpizza",
3639
},
3740
]
3841
}
@@ -86,6 +89,10 @@ loki.source.docker "default" {
8689
host = "unix:///var/run/docker.sock"
8790
targets = discovery.relabel.quickpizza.output
8891
forward_to = [loki.write.local.receiver]
92+
labels = {
93+
service_name = "quickpizza",
94+
service_namespace = "quickpizza",
95+
}
8996
}
9097

9198
loki.write "local" {

docker-compose-cloud.yaml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,18 @@ services:
99
QUICKPIZZA_OTLP_ENDPOINT: http://alloy:4318
1010
QUICKPIZZA_TRUST_CLIENT_TRACEID: 1
1111
QUICKPIZZA_PYROSCOPE_ENDPOINT: http://alloy:9999
12+
# Set to 1 to use component name as OpenTelemetry service name
13+
# QUICKPIZZA_OTEL_SERVICE_NAME_LEGACY: 1
1214
# must be set with an .env file
1315
QUICKPIZZA_CONF_FARO_URL: "${QUICKPIZZA_CONF_FARO_URL}"
1416
# must be set with an .env file
1517
QUICKPIZZA_CONF_FARO_APP_NAME: "${QUICKPIZZA_CONF_FARO_APP_NAME}"
16-
18+
# OTEL service.instance.id label. Default: local
19+
# QUICKPIZZA_OTEL_SERVICE_INSTANCE_ID: local
1720
# Namespace label in Faro. Default: quickpizza
1821
# QUICKPIZZA_CONF_FARO_APP_NAMESPACE: quickpizza
1922
# Enable logging. Possible values: error, warn, debug. Default: info
2023
# QUICKPIZZA_LOG_LEVEL: debug
21-
# Service name label in Pyroscope. Default: quickpizza
22-
# QUICKPIZZA_PYROSCOPE_NAME: quickpizza
23-
# Namespace label in Pyroscope. Default: quickpizza
24-
# QUICKPIZZA_PYROSCOPE_NAMESPACE: quickpizza
2524

2625
alloy:
2726
image: grafana/alloy:v1.9.1

docker-compose-local.yaml

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@ services:
1111
QUICKPIZZA_PYROSCOPE_ENDPOINT: http://alloy:9999
1212
# Enable logging. Possible values: error, warn, debug. Default: info
1313
# QUICKPIZZA_LOG_LEVEL: debug
14-
# Service name label in Pyroscope. Default: quickpizza
15-
# QUICKPIZZA_PYROSCOPE_NAME: quickpizza
16-
# Namespace label in Pyroscope. Default: quickpizza
17-
# QUICKPIZZA_PYROSCOPE_NAMESPACE: quickpizza
18-
# Database configuration (default: in-memory SQLite)
19-
# QUICKPIZZA_DB: postgres://user:password@postgres:5432/quickpizza?sslmode=disable
2014

2115
loki:
2216
image: grafana/loki:3.4.3
@@ -27,6 +21,7 @@ services:
2721
image: prom/prometheus:v3.2.1
2822
command:
2923
- --web.enable-remote-write-receiver
24+
- --enable-feature=exemplar-storage
3025
- --enable-feature=native-histograms
3126
- --config.file=/etc/prometheus/prometheus.yml
3227
ports:
@@ -36,22 +31,21 @@ services:
3631
image: grafana/pyroscope:1.14.0
3732
ports:
3833
- "4040:4040"
39-
34+
4035
tempo:
4136
image: grafana/tempo:2.8.1
42-
command:
43-
- "-storage.trace.backend=local" # tell tempo where to permanently put traces
44-
- "-storage.trace.local.path=/tmp/tempo/traces"
45-
- "-storage.trace.wal.path=/tmp/tempo/wal" # tell tempo where to store the wal
46-
- "-auth.enabled=false" # disables the requirement for the X-Scope-OrgID header
47-
- "-server.http-listen-port=3200"
37+
command: [ "-config.file=/etc/tempo.yaml" ]
38+
volumes:
39+
- ./alloy/local-tempo.yaml:/etc/tempo.yaml
4840
ports:
4941
- "3200:3200"
5042
- "4317:4317"
5143
- "4318:4318"
44+
depends_on:
45+
- prometheus
5246

5347
grafana:
54-
image: grafana/grafana:${GRAFANA_VERSION:-12.0.2}
48+
image: grafana/grafana:${GRAFANA_VERSION:-12.1.0}
5549
ports:
5650
- "3000:3000"
5751
environment:
Loading

grafana/datasources/datasource.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ datasources:
1414
jsonData:
1515
tlsAuth: false
1616
tlsAuthWithCACert: false
17+
timeInterval: 60s # Scrape interval (should match Prometheus configuration, defined in local.alloy)
1718
editable: false
1819
- name: Tempo
1920
type: tempo

pkg/http/tracing.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,24 @@ func (t *TraceInstaller) Install(r chi.Router, serviceName string, extraOpts ...
9595
}
9696
}
9797

98+
serviceNamespace, ok := os.LookupEnv("QUICKPIZZA_OTEL_SERVICE_NAMESPACE")
99+
if !ok {
100+
serviceNamespace = "quickpizza"
101+
}
102+
serviceInstanceID, ok := os.LookupEnv("QUICKPIZZA_OTEL_SERVICE_INSTANCE_ID")
103+
if !ok {
104+
serviceInstanceID = "local"
105+
}
106+
98107
// We discard the error here as it cannot possibly take place with the parameters we use.
99108
res, _ := resource.Merge(
100109
resource.Default(),
101110
resource.NewWithAttributes(
102111
semconv.SchemaURL,
103112
semconv.ServiceName(serviceNameAttrValue),
104113
attribute.KeyValue{Key: "service.component", Value: attribute.StringValue(serviceName)},
114+
attribute.KeyValue{Key: "service.namespace", Value: attribute.StringValue(serviceNamespace)},
115+
attribute.KeyValue{Key: "service.instance.id", Value: attribute.StringValue(serviceInstanceID)},
105116
),
106117
)
107118

0 commit comments

Comments
 (0)