Skip to content

Commit 4365bd8

Browse files
authored
Merge pull request #64 from coder/tempo
feat: add tracing support
2 parents e906c9e + ed96327 commit 4365bd8

File tree

7 files changed

+107
-14
lines changed

7 files changed

+107
-14
lines changed

README.md

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Logs will be scraped from all pods in the Kubernetes cluster.
2222

2323
```bash
2424
helm repo add coder-observability https://helm.coder.com/observability
25-
helm upgrade --install coder-observability coder-observability/coder-observability --version 0.4.2 --namespace coder-observability --create-namespace
25+
helm upgrade --install coder-observability coder-observability/coder-observability --version 0.4.3 --namespace coder-observability --create-namespace
2626
```
2727

2828
## Requirements
@@ -288,6 +288,7 @@ If you switch from classic to native histograms, dashboards may need to account
288288
| https://grafana.github.io/helm-charts | grafana-agent(grafana-agent) | ~0.37.0 |
289289
| https://grafana.github.io/helm-charts | loki | ~v6.7.3 |
290290
| https://grafana.github.io/helm-charts | pyroscope | ~v1.14.1 |
291+
| https://grafana.github.io/helm-charts | tempo | ~v1.23.0 |
291292
| https://prometheus-community.github.io/helm-charts | prometheus | ~v25.24.1 |
292293

293294
Each subchart can be disabled by setting the `enabled` field to `false`.
@@ -420,16 +421,24 @@ values which are defined [here](https://github.com/grafana/helm-charts/tree/main
420421
| grafana.datasources."datasources.yaml".datasources[2].type | string | `"loki"` | |
421422
| grafana.datasources."datasources.yaml".datasources[2].uid | string | `"loki"` | |
422423
| grafana.datasources."datasources.yaml".datasources[2].url | string | `"http://loki-gateway.{{ .Release.Namespace }}.{{ $.Values.global.zone }}"` | |
424+
| grafana.datasources."datasources.yaml".datasources[3].access | string | `"proxy"` | |
423425
| grafana.datasources."datasources.yaml".datasources[3].editable | bool | `false` | |
424426
| grafana.datasources."datasources.yaml".datasources[3].isDefault | bool | `false` | |
425-
| grafana.datasources."datasources.yaml".datasources[3].jsonData.sslmode | string | `"{{ .Values.global.postgres.sslmode }}"` | |
426-
| grafana.datasources."datasources.yaml".datasources[3].name | string | `"postgres"` | |
427-
| grafana.datasources."datasources.yaml".datasources[3].secureJsonData.password | string | `"{{ if .Values.global.postgres.password }}{{ .Values.global.postgres.password }}{{ else }}$PGPASSWORD{{ end }}"` | |
427+
| grafana.datasources."datasources.yaml".datasources[3].name | string | `"traces"` | |
428428
| grafana.datasources."datasources.yaml".datasources[3].timeout | string | `"{{ add $.Values.global.dashboards.queryTimeout 5 }}"` | |
429-
| grafana.datasources."datasources.yaml".datasources[3].type | string | `"postgres"` | |
430-
| grafana.datasources."datasources.yaml".datasources[3].uid | string | `"postgres"` | |
431-
| grafana.datasources."datasources.yaml".datasources[3].url | string | `"{{ .Values.global.postgres.hostname }}:{{ .Values.global.postgres.port }}"` | |
432-
| grafana.datasources."datasources.yaml".datasources[3].user | string | `"{{ .Values.global.postgres.username }}"` | |
429+
| grafana.datasources."datasources.yaml".datasources[3].type | string | `"tempo"` | |
430+
| grafana.datasources."datasources.yaml".datasources[3].uid | string | `"tempo"` | |
431+
| grafana.datasources."datasources.yaml".datasources[3].url | string | `"http://tempo.{{ .Release.Namespace }}.{{ $.Values.global.zone }}:3200"` | |
432+
| grafana.datasources."datasources.yaml".datasources[4].editable | bool | `false` | |
433+
| grafana.datasources."datasources.yaml".datasources[4].isDefault | bool | `false` | |
434+
| grafana.datasources."datasources.yaml".datasources[4].jsonData.sslmode | string | `"{{ .Values.global.postgres.sslmode }}"` | |
435+
| grafana.datasources."datasources.yaml".datasources[4].name | string | `"postgres"` | |
436+
| grafana.datasources."datasources.yaml".datasources[4].secureJsonData.password | string | `"{{ if .Values.global.postgres.password }}{{ .Values.global.postgres.password }}{{ else }}$PGPASSWORD{{ end }}"` | |
437+
| grafana.datasources."datasources.yaml".datasources[4].timeout | string | `"{{ add $.Values.global.dashboards.queryTimeout 5 }}"` | |
438+
| grafana.datasources."datasources.yaml".datasources[4].type | string | `"postgres"` | |
439+
| grafana.datasources."datasources.yaml".datasources[4].uid | string | `"postgres"` | |
440+
| grafana.datasources."datasources.yaml".datasources[4].url | string | `"{{ .Values.global.postgres.hostname }}:{{ .Values.global.postgres.port }}"` | |
441+
| grafana.datasources."datasources.yaml".datasources[4].user | string | `"{{ .Values.global.postgres.username }}"` | |
433442
| grafana.deploymentStrategy.type | string | `"Recreate"` | |
434443
| grafana.enabled | bool | `true` | |
435444
| grafana.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION | bool | `true` | |
@@ -576,4 +585,13 @@ values which are defined [here](https://github.com/grafana/helm-charts/tree/main
576585
| runbookViewer.image | string | `"dannyben/madness"` | |
577586
| sqlExporter.enabled | bool | `true` | |
578587
| sqlExporter.image | string | `"burningalchemist/sql_exporter"` | |
588+
| tempo.enabled | bool | `false` | |
589+
| tempo.fullnameOverride | string | `"tempo"` | |
590+
| tempo.nameOverride | string | `"tempo"` | |
591+
| tempo.persistence.enabled | bool | `true` | |
592+
| tempo.persistence.size | string | `"10Gi"` | |
593+
| tempo.podAnnotations."prometheus.io/scrape" | string | `"true"` | |
594+
| tempo.replicas | int | `1` | |
595+
| tempo.tempo.reportingEnabled | bool | `false` | |
596+
| tempo.tempo.retention | string | `"336h"` | |
579597

TESTING_KIND.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
To test the observability chart locally without a kubernetes cluster, you can use [`kind` (Kubernetes in Docker)](https://kind.sigs.k8s.io/). This allows you to create a local Kubernetes cluster that can be used for testing purposes.
1111

1212
```bash
13-
kind create cluster --name observability
13+
kind create cluster --name observability --image kindest/node:v1.24.0
1414
# To clean everything up, you can delete the cluster with:
1515
# kind delete cluster --name observability
1616
```
@@ -46,6 +46,11 @@ coder:
4646
- name: CODER_ACCESS_URL
4747
# Keep this an empty string to get a public `try` url
4848
value: ""
49+
# Enable tracing in observability chart (tempo.enabled=true)
50+
- name: CODER_TRACE_ENABLE
51+
value: "true"
52+
- name: OTEL_EXPORTER_OTLP_ENDPOINT
53+
value: "http://tempo.coder-observability.svc.cluster.local:4317"
4954
```
5055
5156
### Verify `coder` installation
@@ -87,7 +92,20 @@ Install the local observability chart using Helm into its own namespace.
8792
kubectl config set-context --current --namespace=coder-observability
8893
# This will install the local observability chart into the `coder-observability` namespace
8994

90-
helm install --namespace coder-observability --create-namespace observe .
95+
cd coder-observability
96+
helm upgrade --install coder-observability . --namespace observe --create-namespace
97+
```
98+
99+
You may need to remove the taint to get pods to schedule if you get an error like this:
100+
101+
```bash
102+
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
103+
NAME TAINTS
104+
observability-control-plane [map[effect:NoSchedule key:node-role.kubernetes.io/control-plane]]
105+
```
106+
107+
```bash
108+
kubectl taint nodes observability-control-plane node-role.kubernetes.io/control-plane:NoSchedule-
91109
```
92110
93111
## To update

coder-observability/Chart.lock

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ dependencies:
1111
- name: loki
1212
repository: https://grafana.github.io/helm-charts
1313
version: 6.7.4
14+
- name: tempo
15+
repository: https://grafana.github.io/helm-charts
16+
version: 1.23.3
1417
- name: grafana-agent
1518
repository: https://grafana.github.io/helm-charts
1619
version: 0.37.0
17-
digest: sha256:38b7d46261c4d39a103fbf61eac9da26a997024221ab81078ea5b34fc2b83c68
18-
generated: "2025-08-27T14:16:57.521541846Z"
20+
digest: sha256:537af466b8fca7d1ef78c62cfeae304e8e76e25b80e52f317da3ac3f411ba1f6
21+
generated: "2025-10-13T14:43:48.263512398+02:00"

coder-observability/Chart.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ apiVersion: v2
22
name: coder-observability
33
description: Gain insights into your Coder deployment
44
type: application
5-
version: 0.4.2
5+
version: 0.4.3
66
dependencies:
77
- name: pyroscope
88
condition: pyroscope.enabled
@@ -20,6 +20,10 @@ dependencies:
2020
condition: loki.enabled
2121
repository: https://grafana.github.io/helm-charts
2222
version: '~v6.7.3'
23+
- name: tempo
24+
condition: tempo.enabled
25+
repository: https://grafana.github.io/helm-charts
26+
version: '~v1.23.0'
2327
- name: grafana-agent
2428
alias: grafana-agent
2529
condition: grafana-agent.enabled

coder-observability/templates/_collector-config.tpl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,9 @@ otelcol.receiver.otlp "otlp_receiver" {
377377
output {
378378
metrics = [otelcol.processor.batch.default.input]
379379
logs = [otelcol.processor.batch.default.input]
380+
{{- if .Values.tempo.enabled }}
381+
traces = [otelcol.processor.batch.default.input]
382+
{{- end }}
380383
}
381384
}
382385
otelcol.exporter.prometheus "to_prometheus" {
@@ -391,11 +394,24 @@ otelcol.exporter.loki "to_loki" {
391394
]
392395
}
393396
{{- end }}
397+
{{- if .Values.tempo.enabled }}
398+
otelcol.exporter.otlp "to_tempo" {
399+
client {
400+
endpoint = "http://tempo.{{ .Release.Namespace }}.{{ .Values.global.zone }}:4317"
401+
tls {
402+
insecure = true
403+
}
404+
}
405+
}
406+
{{- end }}
394407
otelcol.processor.batch "default" {
395408
output {
396409
metrics = [otelcol.exporter.prometheus.to_prometheus.input]
397410
{{- if .Values.loki.enabled }}
398411
logs = [otelcol.exporter.loki.to_loki.input]
412+
{{- end }}
413+
{{- if .Values.tempo.enabled }}
414+
traces = [otelcol.exporter.otlp.to_tempo.input]
399415
{{- end }}
400416
}
401417
}

coder-observability/values.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,15 @@ grafana:
385385
# add 5s on global timeout to distinguish between Grafana timeout & datasource timeout
386386
timeout: '{{ add $.Values.global.dashboards.queryTimeout 5 }}'
387387
uid: loki
388+
- name: traces
389+
type: tempo
390+
url: http://tempo.{{ .Release.Namespace }}.{{ $.Values.global.zone }}:3200
391+
access: proxy
392+
isDefault: false
393+
editable: false
394+
# add 5s on global timeout to distinguish between Grafana timeout & datasource timeout
395+
timeout: '{{ add $.Values.global.dashboards.queryTimeout 5 }}'
396+
uid: tempo
388397
- name: postgres
389398
type: postgres
390399
url: '{{ .Values.global.postgres.hostname }}:{{ .Values.global.postgres.port }}'
@@ -664,3 +673,20 @@ loki:
664673
mountPath: /var/loki-ruler-wal
665674
extraArgs:
666675
- -log.level=debug
676+
677+
tempo:
678+
enabled: false
679+
nameOverride: tempo
680+
fullnameOverride: tempo
681+
682+
tempo:
683+
retention: 336h # 14 days
684+
reportingEnabled: false
685+
686+
persistence:
687+
enabled: true
688+
size: 10Gi
689+
690+
replicas: 1
691+
podAnnotations:
692+
prometheus.io/scrape: "true"

compiled/resources.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,14 @@ data:
229229
type: loki
230230
uid: loki
231231
url: http://loki-gateway.coder-observability.svc
232+
- access: proxy
233+
editable: false
234+
isDefault: false
235+
name: traces
236+
timeout: '905'
237+
type: tempo
238+
uid: tempo
239+
url: http://tempo.coder-observability.svc:3200
232240
- editable: false
233241
isDefault: false
234242
jsonData:
@@ -11686,7 +11694,7 @@ spec:
1168611694
app.kubernetes.io/name: grafana
1168711695
app.kubernetes.io/instance: coder-observability
1168811696
annotations:
11689-
checksum/config: 8143dd78a48b90e972a84c3078e9812a2536a4efff7ca13f404626d5eae08ab2
11697+
checksum/config: 20c285f755dee545f371c9b074076736f3f793c8901c979afa0e244702d80f10
1169011698
checksum/dashboards-json-config: 010b57348b6dd1f09007330c03d22a0570022534712646511cad39a9e3cb4bb7
1169111699
checksum/sc-dashboard-provider-config: 01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b
1169211700
kubectl.kubernetes.io/default-container: grafana

0 commit comments

Comments
 (0)