Skip to content

Commit 5ff432c

Browse files
authored
feat: add support for datasource-managed alerts (#362)
1 parent a893328 commit 5ff432c

File tree

16 files changed

+697
-70
lines changed

16 files changed

+697
-70
lines changed

README.md

Lines changed: 55 additions & 56 deletions
Large diffs are not rendered by default.

docker-compose.yaml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ services:
2828
command: -config.file=/etc/loki/loki-config.yml
2929
volumes:
3030
- ./testdata/loki-config.yml:/etc/loki/loki-config.yml
31+
- ./testdata/loki-rules.yml:/loki/rules/fake/loki-rules.yml
3132

3233
promtail:
3334
image: grafana/promtail:2.9.15@sha256:466ba2fac4448ed2dc509b267995a3c13511d69f6bba01800ca7b38d9953f899
@@ -46,16 +47,26 @@ services:
4647

4748
tempo:
4849
image: grafana/tempo:2.9.0-rc.0@sha256:5517ee34d335dedb9ad43028bd8f72edd0bb98b744ea5847a7572755d93d9866
49-
command: ["-config.file=/etc/tempo/tempo-config.yaml"]
50+
command: [ "-config.file=/etc/tempo/tempo-config.yaml" ]
5051
volumes:
5152
- ./testdata/tempo-config.yaml:/etc/tempo/tempo-config.yaml
5253
ports:
5354
- "3200:3200" # tempo
5455

5556
tempo2:
5657
image: grafana/tempo:2.9.0-rc.0@sha256:5517ee34d335dedb9ad43028bd8f72edd0bb98b744ea5847a7572755d93d9866
57-
command: ["-config.file=/etc/tempo/tempo-config.yaml"]
58+
command: [ "-config.file=/etc/tempo/tempo-config.yaml" ]
5859
volumes:
5960
- ./testdata/tempo-config-2.yaml:/etc/tempo/tempo-config.yaml
6061
ports:
6162
- "3201:3201" # tempo instance 2
63+
64+
alertmanager:
65+
image: prom/alertmanager:v0.28.1
66+
ports:
67+
- "9093:9093"
68+
volumes:
69+
- ./testdata/alertmanager.yml:/etc/alertmanager/alertmanager.yml
70+
command:
71+
- '--config.file=/etc/alertmanager/alertmanager.yml'
72+
- '--storage.path=/alertmanager'

go.mod

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,32 @@ require (
1616
github.com/grafana/pyroscope/api v1.2.0
1717
github.com/invopop/jsonschema v0.13.0
1818
github.com/mark3labs/mcp-go v0.43.0
19+
github.com/prometheus/alertmanager v0.28.1
1920
github.com/prometheus/client_golang v1.23.2
2021
github.com/prometheus/common v0.67.2
2122
github.com/prometheus/prometheus v0.307.3
2223
github.com/stretchr/testify v1.11.1
2324
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0
2425
go.opentelemetry.io/otel v1.38.0
2526
go.opentelemetry.io/otel/sdk v1.38.0
27+
gopkg.in/yaml.v3 v3.0.1
2628
)
2729

2830
require (
2931
github.com/apache/arrow-go/v18 v18.4.1 // indirect
32+
github.com/aws/aws-sdk-go-v2 v1.39.2 // indirect
33+
github.com/aws/aws-sdk-go-v2/config v1.31.12 // indirect
34+
github.com/aws/aws-sdk-go-v2/credentials v1.18.16 // indirect
35+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 // indirect
36+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 // indirect
37+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 // indirect
38+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
39+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 // indirect
40+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 // indirect
41+
github.com/aws/aws-sdk-go-v2/service/sso v1.29.6 // indirect
42+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1 // indirect
43+
github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 // indirect
44+
github.com/aws/smithy-go v1.23.0 // indirect
3045
github.com/bahlo/generic-list-go v0.2.0 // indirect
3146
github.com/beorn7/perks v1.0.1 // indirect
3247
github.com/buger/jsonparser v1.1.1 // indirect
@@ -99,6 +114,7 @@ require (
99114
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
100115
github.com/prometheus/client_model v0.6.2 // indirect
101116
github.com/prometheus/procfs v0.16.1 // indirect
117+
github.com/prometheus/sigv4 v0.2.1 // indirect
102118
github.com/rivo/uniseg v0.4.7 // indirect
103119
github.com/shopspring/decimal v1.3.1 // indirect
104120
github.com/spf13/cast v1.7.1 // indirect
@@ -132,5 +148,5 @@ require (
132148
google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 // indirect
133149
google.golang.org/grpc v1.75.1 // indirect
134150
google.golang.org/protobuf v1.36.10 // indirect
135-
gopkg.in/yaml.v3 v3.0.1 // indirect
151+
gopkg.in/yaml.v2 v2.4.0 // indirect
136152
)

go.sum

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,32 @@ github.com/apache/arrow-go/v18 v18.4.1 h1:q/jVkBWCJOB9reDgaIZIdruLQUb1kbkvOnOFez
1212
github.com/apache/arrow-go/v18 v18.4.1/go.mod h1:tLyFubsAl17bvFdUAy24bsSvA/6ww95Iqi67fTpGu3E=
1313
github.com/apache/thrift v0.22.0 h1:r7mTJdj51TMDe6RtcmNdQxgn9XcyfGDOzegMDRg47uc=
1414
github.com/apache/thrift v0.22.0/go.mod h1:1e7J/O1Ae6ZQMTYdy9xa3w9k+XHWPfRvdPyJeynQ+/g=
15+
github.com/aws/aws-sdk-go-v2 v1.39.2 h1:EJLg8IdbzgeD7xgvZ+I8M1e0fL0ptn/M47lianzth0I=
16+
github.com/aws/aws-sdk-go-v2 v1.39.2/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY=
17+
github.com/aws/aws-sdk-go-v2/config v1.31.12 h1:pYM1Qgy0dKZLHX2cXslNacbcEFMkDMl+Bcj5ROuS6p8=
18+
github.com/aws/aws-sdk-go-v2/config v1.31.12/go.mod h1:/MM0dyD7KSDPR+39p9ZNVKaHDLb9qnfDurvVS2KAhN8=
19+
github.com/aws/aws-sdk-go-v2/credentials v1.18.16 h1:4JHirI4zp958zC026Sm+V4pSDwW4pwLefKrc0bF2lwI=
20+
github.com/aws/aws-sdk-go-v2/credentials v1.18.16/go.mod h1:qQMtGx9OSw7ty1yLclzLxXCRbrkjWAM7JnObZjmCB7I=
21+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 h1:Mv4Bc0mWmv6oDuSWTKnk+wgeqPL5DRFu5bQL9BGPQ8Y=
22+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9/go.mod h1:IKlKfRppK2a1y0gy1yH6zD+yX5uplJ6UuPlgd48dJiQ=
23+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 h1:se2vOWGD3dWQUtfn4wEjRQJb1HK1XsNIt825gskZ970=
24+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9/go.mod h1:hijCGH2VfbZQxqCDN7bwz/4dzxV+hkyhjawAtdPWKZA=
25+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 h1:6RBnKZLkJM4hQ+kN6E7yWFveOTg8NLPHAkqrs4ZPlTU=
26+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9/go.mod h1:V9rQKRmK7AWuEsOMnHzKj8WyrIir1yUJbZxDuZLFvXI=
27+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
28+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
29+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 h1:oegbebPEMA/1Jny7kvwejowCaHz1FWZAQ94WXFNCyTM=
30+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1/go.mod h1:kemo5Myr9ac0U9JfSjMo9yHLtw+pECEHsFtJ9tqCEI8=
31+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 h1:5r34CgVOD4WZudeEKZ9/iKpiT6cM1JyEROpXjOcdWv8=
32+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9/go.mod h1:dB12CEbNWPbzO2uC6QSWHteqOg4JfBVJOojbAoAUb5I=
33+
github.com/aws/aws-sdk-go-v2/service/sso v1.29.6 h1:A1oRkiSQOWstGh61y4Wc/yQ04sqrQZr1Si/oAXj20/s=
34+
github.com/aws/aws-sdk-go-v2/service/sso v1.29.6/go.mod h1:5PfYspyCU5Vw1wNPsxi15LZovOnULudOQuVxphSflQA=
35+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1 h1:5fm5RTONng73/QA73LhCNR7UT9RpFH3hR6HWL6bIgVY=
36+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1/go.mod h1:xBEjWD13h+6nq+z4AkqSfSvqRKFgDIQeaMguAJndOWo=
37+
github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 h1:p3jIvqYwUZgu/XYeI48bJxOhvm47hZb5HUQ0tn6Q9kA=
38+
github.com/aws/aws-sdk-go-v2/service/sts v1.38.6/go.mod h1:WtKK+ppze5yKPkZ0XwqIVWD4beCwv056ZbPQNoeHqM8=
39+
github.com/aws/smithy-go v1.23.0 h1:8n6I3gXzWJB2DxBDnfxgBaSX6oe0d/t10qGz7OKqMCE=
40+
github.com/aws/smithy-go v1.23.0/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
1541
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
1642
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
1743
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -223,6 +249,8 @@ github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1
223249
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
224250
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
225251
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
252+
github.com/prometheus/alertmanager v0.28.1 h1:BK5pCoAtaKg01BYRUJhEDV1tqJMEtYBGzPw8QdvnnvA=
253+
github.com/prometheus/alertmanager v0.28.1/go.mod h1:0StpPUDDHi1VXeM7p2yYfeZgLVi/PPlt39vo9LQUHxM=
226254
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
227255
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
228256
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
@@ -233,6 +261,8 @@ github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzM
233261
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
234262
github.com/prometheus/prometheus v0.307.3 h1:zGIN3EpiKacbMatcUL2i6wC26eRWXdoXfNPjoBc2l34=
235263
github.com/prometheus/prometheus v0.307.3/go.mod h1:sPbNW+KTS7WmzFIafC3Inzb6oZVaGLnSvwqTdz2jxRQ=
264+
github.com/prometheus/sigv4 v0.2.1 h1:hl8D3+QEzU9rRmbKIRwMKRwaFGyLkbPdH5ZerglRHY0=
265+
github.com/prometheus/sigv4 v0.2.1/go.mod h1:ySk6TahIlsR2sxADuHy4IBFhwEjRGGsfbbLGhFYFj6Q=
236266
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
237267
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
238268
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
@@ -369,6 +399,8 @@ google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j
369399
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
370400
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
371401
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
402+
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
403+
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
372404
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
373405
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
374406
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

mcpgrafana.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ type GrafanaConfig struct {
136136
BasicAuth *url.Userinfo
137137

138138
// OrgID is the organization ID to use for multi-org support.
139-
// When set, it will be sent as X-Scope-OrgId header regardless of authentication method.
139+
// When set, it will be sent as X-Grafana-Org-Id header regardless of authentication method.
140140
// Works with service account tokens, API keys, and basic authentication.
141141
OrgID int64
142142

testdata/alertmanager.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
global:
2+
resolve_timeout: 5m
3+
4+
route:
5+
group_by: ['alertname']
6+
group_wait: 10s
7+
group_interval: 10s
8+
repeat_interval: 12h
9+
receiver: 'test-receiver'
10+
11+
receivers:
12+
- name: 'test-receiver'
13+
webhook_configs:
14+
- url: 'http://localhost:5001/'
15+
16+
- name: 'test-email'
17+
email_configs:
18+
19+
20+
smarthost: 'localhost:25'
21+
require_tls: false
22+
23+
- name: 'test-slack'
24+
slack_configs:
25+
- api_url: 'https://hooks.slack.com/services/test'
26+
channel: '#alerts'
27+
28+
inhibit_rules:
29+
- source_match:
30+
severity: 'critical'
31+
target_match:
32+
severity: 'warning'
33+
equal: ['alertname']

testdata/loki-config.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,23 @@ storage_config:
3838
shared_store: filesystem
3939
filesystem:
4040
directory: /loki/chunks
41+
42+
ruler:
43+
enable_api: true
44+
enable_sharding: false
45+
storage:
46+
type: local
47+
local:
48+
directory: /loki/rules
49+
rule_path: /loki/rules-temp
50+
alertmanager_url: http://alertmanager:9093
51+
ring:
52+
kvstore:
53+
store: inmemory
54+
remote_write:
55+
enabled: false
56+
57+
limits_config:
58+
ruler_evaluation_delay_duration: 0s
59+
ruler_max_rules_per_rule_group: 100
60+
ruler_max_rule_groups_per_tenant: 100

testdata/loki-rules.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
groups:
2+
- name: loki_test_rules
3+
interval: 10s
4+
rules:
5+
- alert: LokiTestAlertFiring
6+
expr: |
7+
sum(rate({job="varlogs"}[1m])) >= 0
8+
for: 0s
9+
labels:
10+
severity: warning
11+
environment: test
12+
source: loki
13+
annotations:
14+
summary: "Loki test alert"
15+
description: "This is a test alert managed by Loki ruler"
16+
17+
- alert: LokiTestAlertInfo
18+
expr: |
19+
sum(rate({job="varlogs"}[1m])) > 1000
20+
for: 0s
21+
labels:
22+
severity: info
23+
environment: test
24+
source: loki
25+
annotations:
26+
summary: "Loki info alert (should not fire)"
27+
description: "High rate alert for testing"

testdata/prometheus-seed.yml

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,41 @@
11
groups:
22
- name: seed
3+
interval: 10s
34
rules:
4-
- record: test
5-
expr: vector(1)
5+
# Recording rule
6+
- record: test
7+
expr: vector(1)
8+
9+
# Alerting rules for testing datasource-managed alerts
10+
- alert: PrometheusTestAlertFiring
11+
expr: vector(1) > 0
12+
for: 0s
13+
labels:
14+
severity: warning
15+
environment: test
16+
source: prometheus
17+
annotations:
18+
summary: "Test alert that should always be firing"
19+
description: "This is a test alert managed by Prometheus ruler"
20+
21+
- alert: PrometheusTestAlertNormal
22+
expr: vector(0) > 0
23+
for: 0s
24+
labels:
25+
severity: info
26+
environment: test
27+
source: prometheus
28+
annotations:
29+
summary: "Test alert that should be normal"
30+
description: "This alert should not fire"
31+
32+
- alert: PrometheusTestAlertCritical
33+
expr: up == 1
34+
for: 1m
35+
labels:
36+
severity: critical
37+
environment: test
38+
source: prometheus
39+
annotations:
40+
summary: "Critical test alert based on up metric"
41+
description: "Tests filtering and label matching"

testdata/prometheus.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
global:
22
scrape_interval: 1s
33

4+
alerting:
5+
alertmanagers:
6+
- static_configs:
7+
- targets: ['alertmanager:9093']
8+
49
scrape_configs:
510
- job_name: 'prometheus'
611
static_configs:

0 commit comments

Comments
 (0)