sources¶
Pluggable framework for external metrics (roadmap C1/C2): SLO/SLI data, DORA delivery metrics and code quality — from exchangeable, combinable sources, into normalised register JSON the portfolio report renders.
Status: implemented (alpha)
Design: three guarantees¶
- Exchangeable — the report never sees a vendor. Providers translate a
foreign system into three normalised record contracts (
SloRecord,DoraRecord,QualityRecord); status/tier judgements happen centrally in the registers (portfolio/slo_config.py,portfolio/dora_config.py), so every source is judged by the same rule. - Combinable — a fetch config may list several sources; their records
merge into one register, each row keeping its origin (
sourcecolumn in the report). - Easy to extend — a new source is ONE file in
sources/providers/defining aPROVIDERobject; auto-discovery picks it up, no registry to edit (see the recipe below).
The file provider is the universal fallback (the C3 principle): any system can be attached today by exporting the normalised JSON — no API approval needed.
Shipped providers¶
| Provider | Kind | Why this reference |
|---|---|---|
file |
slo, dora, quality | Universal path 1 — works without any API access |
prometheus |
slo | De-facto OSS monitoring standard (~77 % production use; sits behind most Grafana setups); commercial leaders (Datadog ~24 % APM share, Dynatrace) attach via file or a future provider |
github |
dora | Robert's pick, largest platform — no native DORA API, so the four keys are derived: deployments (frequency), latest deployment statuses (CFR), merged PRs (lead time, median created→merged), incident-labelled issues (MTTR). Approximations are documented and configurable (environment, incident label, caps) |
gitlab |
dora | The only mainstream system with a native DORA API (/api/v4/.../dora/metrics, Ultimate tier) — kept as the second reference to prove exchangeability |
sonarqube |
quality | De-facto static-quality standard (named by the roadmap): coverage, maintainability rating, critical violations |
Tokens always come from environment variables (PROMETHEUS_TOKEN,
GITHUB_TOKEN, GITLAB_TOKEN, SONAR_TOKEN, overridable via
token_env), are never stored and never logged; 401/403 errors point to
the possibly missing approval and to the file path as fallback.
CLI¶
python -m sources providers
python -m sources fetch --kind slo --config slo_sources.json --output slo.json
A config is one source object — or a combination:
{
"sources": [
{"provider": "prometheus", "base_url": "https://prom.intern",
"services": [{"service": "Order API", "slo": "availability",
"target_pct": 99.9,
"sli_query": "avg_over_time(up[30d])", "scale": 100}]},
{"provider": "file", "path": "dynatrace_export.json"}
]
}
The output is the register JSON the solution config references
("slo": "slo.json", "dora": "dora.json"); the report then renders
Service Levels & Error Budgets (breached first, central budget rule:
consumed = (100−SLI)/(100−target), at risk below 25 % remaining) and
Delivery Performance (DORA) & Code Quality (per-metric tiers at the
published DORA thresholds, unit tier = worst metric; quality table below).
Tutorial¶
New to this? The step-by-step tutorial Attaching your own data
source builds a complete CSV provider
from zero (no external systems needed, runs against the demo scenario),
then shows swapping, combining and day-to-day management — every step
with an example. Also available as PDF:
DE / EN.
The shipped csv provider (sources/providers/csv_slo.py) is the
tutorial's living reference solution.
Recipe: your own source in ~30 lines¶
Create sources/providers/my_system.py:
from sources.base import KIND_SLO, SloRecord
from sources.http import bearer, get_json, token_from_env
class MySystemSource:
provider_id = "my_system"
kinds = (KIND_SLO,)
def fetch(self, kind, config, log):
headers = bearer(token_from_env(config, "MY_SYSTEM_TOKEN"))
data = get_json(config["base_url"] + "/api/slos", headers, "MySystem")
return [SloRecord(service=e["name"], slo=e["goal"],
target_pct=e["target"], sli_pct=e["current"],
source="my_system") for e in data]
PROVIDER = MySystemSource()
Done — python -m sources providers lists it, fetch can use it, and it
combines freely with every other source.
Architecture¶
sources/
├── base.py Record contracts, provider protocol, auto-discovery
├── http.py Shared urllib GET + auth headers + error mapping
├── cli.py fetch (multi-source merge) and providers commands
└── providers/
├── file_source.py Universal file path (all kinds)
├── prometheus.py C1 reference (SLO/SLI via instant query)
├── github_dora.py C2 reference (DORA derived from GitHub)
├── gitlab_dora.py C2 alternative (native DORA API)
└── sonarqube.py C2 quality (component measures)
Standard library only. The REST providers are fully mock-tested; a live test against real instances is the remaining practice step (as with get_data).