src/go/internal/promprofile/README.md
This document is the canonical architecture for the developer framework that validates and proves Netdata Prometheus
profiles. The framework is intentionally split between the
netdata/netdata and
netdata/testdata repositories.
Field-level schemas, production behavior, and command syntax remain with their executable owners. This document owns the system boundary, authority model, dependency direction, and extension rules that connect those owners.
The framework has two related entry points:
The framework is pre-merge developer tooling. Production collection does not load proof descriptors, source contracts, fixtures, or the testdata repository.
The framework does not:
netdata/testdata revision inside Netdata;| Repository | Owns | Does not own |
|---|---|---|
netdata/netdata | Production runtime behavior; stock profiles; operator rationale; profile design; replay descriptors; strict schema loaders, compilers, reconciliation, and coverage; standalone validator policy; developer CLIs; cross-repository consumer verification | Bulky fixture corpora; generated exporter registration ledgers; source-registry generator runtimes |
netdata/testdata | Sanitized source-derived fixtures; source-semantic contracts; optional generated source registries and their manifests/generators; registry reproduction workflow | Netdata profile design; expected Netdata output; collector policy; chart routing; proof reconciliation |
The split keeps reviewable intent beside the stock profile while avoiding large source-complete fixture and registration corpora in the main repository.
Compact Netdata-side artifacts live under
src/go/plugin/go.d/collector/prometheus/profile-proofs/<profile>/:
OPERATOR-MODEL.md
PROFILE-DESIGN.yaml
proof.yaml
Source-side artifacts live under prometheus/profiles/<profile>/ in netdata/testdata:
SOURCE-SEMANTICS.yaml
fixtures/*.prom
SOURCE-REGISTRY.yaml # optional
SOURCE-REGISTRY.generator.yaml # required with SOURCE-REGISTRY.yaml
generator/*.py # required with the registry pair
The proof compiler enforces exact directory layouts. Unexpected, unreferenced, or half-present registry artifacts fail verification instead of being ignored.
No single YAML file is a complete proof. The framework obtains independence by assigning each kind of claim to one owner and compiling disagreements into failures.
| Claim | Authority | Enforcement |
|---|---|---|
| Exporter registrations, types, components, label domains, lifecycle, availability, units, and source relationships | SOURCE-SEMANTICS.yaml, plus the optional mechanical source registry and its pinned public upstream evidence | Strict semantic load and static compilation |
| Operator questions, entity grain, identity, label treatment, reductions, exclusions, units, and presentation intent | PROFILE-DESIGN.yaml | Strict semantic load, static compilation, and production reconciliation |
| Human rationale for the design | OPERATOR-MODEL.md | Human review; exact machine claims belong in the YAML contracts |
| Realizable input environments, fixtures, lifecycle sequences, expected verdicts/findings, and coverage participation | proof.yaml | Strict proof descriptor load and replay verification |
| Profile parsing, selection, relabeling, assembly, writer behavior, chart routing, and public wire identities | Production Prometheus, metrix, chartengine, and chartemit packages | Real production execution with opt-in structured facts |
| Contributor validation policy, evidence obligations, severities, and report wording | internal/promprofile/validation | Standalone validation report |
| Cross-artifact consistency, semantic output reconciliation, observations, and declaration-bounded coverage | internal/promprofile/semantics and internal/promprofile/proof | Catalog compilation and proof verification |
Important boundaries:
PROFILE-DESIGN.yaml is research-backed design input, not a serialization of the resulting profile.proof.yaml contains independent expectations, not generated snapshots, counts, or content digests.src/go/internal/promprofile/ is a namespace of focused packages, not an umbrella Go package:
| Package | Responsibility |
|---|---|
input (prominput) | Typed execution inputs shared by proof compilation and validation replay, including fixture sequences, supporting profiles, metadata examples, and future probes |
replay (promreplay) | Detached neutral result and semantic-snapshot types between production replay and proof reconciliation |
yaml (promyaml) | Strict YAML decoding helpers, including duplicate/unknown-key rejection used by proof and semantic schemas |
semantics (promsemantics) | Source/design/registry schemas, strict validation, semantic compilation, environment evaluation, production reconciliation, observations, and coverage |
proof (promproof) | Proof discovery, exact layout checks, support-closure compilation, case compilation, expected-result verification, and catalog-wide coverage orchestration |
validation (promvalidation) | Standalone contributor policy, isolated production execution, bounded analysis, deterministic reporting, and proof replay snapshots |
testutil (promtestutil) | Test-only discovery and required/optional handling of the external testdata checkout |
The dependency shape deliberately prevents proof semantics from entering production packages and prevents validation from becoming a second semantic compiler:
flowchart LR
CLIProof["proof CLI
composition root"]
CLIValidation["validation CLI"]
Proof["promproof
catalog + expectations"]
Semantics["promsemantics
contract compiler + reconciliation"]
Validation["promvalidation
production orchestration + policy"]
Input["prominput
replay request"]
Replay["promreplay
neutral result"]
StrictYAML["promyaml
strict decoding"]
SharedRuntime["shared runtime mechanisms
Prometheus identity + matcher + selector"]
Production["production pipeline
collector + metrix + chartengine + chartemit"]
CLIProof --> Proof
CLIProof --> Validation
CLIValidation --> Validation
Proof --> Semantics
Proof --> Input
Proof --> Replay
Proof --> StrictYAML
Semantics --> Replay
Semantics --> StrictYAML
Semantics --> SharedRuntime
Input --> SharedRuntime
Validation --> Input
Validation --> Replay
Validation --> Production
promproof accepts replay as a callback. The proof CLI injects promvalidation.ReplayProofCase; promproof therefore does
not import promvalidation, and promvalidation does not import the semantic compiler. This composition-root wiring keeps
the two authorities independent and avoids an import cycle. Shared input and semantic code reuse production identity,
matcher, and selector primitives where those primitives are the behavior being described; they do not run or duplicate the
collector pipeline.
promproof.Discover loads each proof.yaml directly below the stock proof root. There is no separate handwritten proof
registry. A profile name determines its stock profile path and stable testdata directory.
promproof.LoadCompiledCatalog:
PROFILE-DESIGN.yaml and external SOURCE-SEMANTICS.yaml;The complete catalog is compiled even for targeted verification because support closure and cross-profile composition must be known. Only the requested candidate profiles are replayed and charged with coverage in a targeted run.
For each case, promproof derives:
Supporting profiles are passed into the isolated catalog, but the production collector still selects profiles through its
normal matching behavior. The job does not force the candidate or copy support composition into profiles:.
promvalidation.ReplayProofCase creates one isolated validation session for the case and processes fixtures in order.
Multi-step cases retain collector/chart lifecycle state; standalone cases do not borrow state from other cases.
Each usable step executes the same profile selection, job/profile relabeling, Prometheus assembly and writer, metrix store,
chartengine plan, and chartemit preparation used by the collector. Structured diagnostics are projected into a detached
promreplay.Result containing the validator findings and, when available, a neutral semantic snapshot.
Current fixture evidence and synthetic future probes use separate production collector/store/plan sequences. Future probes
therefore cannot satisfy current source coverage or hide missing current charts.
Contributor and future requirements are built for the candidate and every supplied support profile. Shared job policy is
analyzed once against the composed namespace; one future collector/planner run carries all declared and safely derived
probes. Each profiles.candidate or profiles.supports[] report entry records its first owned raw probe when one exists.
Ownership is established from the open probe that actually covers a profile-owned wildcard scope or relabel rule; declared
input order alone does not assign ownership. Current physical sample names and logical typed-family base names are excluded
before any future input is accepted or derived.
promproof consumes each result immediately and asks promsemantics to reconcile:
Expected standalone failures are compared by finding code. Successful steps require a semantic snapshot. Participating cases contribute to declaration-bounded coverage, which is verified after the candidate profile's final case. Full replay snapshots are not retained for the complete catalog.
The validator must observe production decisions without making production depend on validation:
When a new proof needs a runtime fact that is not observable, add the fact at the production semantic owner first. Do not
infer it from names, duplicate the production algorithm in promvalidation, or add proof-only behavior to the collector.
Support composition exists for metrics that are exported with the candidate but belong to another reusable stock profile, such as language/runtime process metrics.
PROFILE-DESIGN.yaml is the single declaration owner through composition.supports.Do not repeat support lists in proof.yaml, job configuration, or source semantics.
proof.yaml, PROFILE-DESIGN.yaml, SOURCE-SEMANTICS.yaml, and the optional source-registry pair each declare their own
strict schema version. The current versions are defined beside their Go loaders and validators.
A schema version identifies syntax and meaning. Bump it only when a reader cannot interpret old and new artifacts under one unambiguous contract. Adding a compatible optional field does not automatically require a new version; changing the meaning of an existing field does.
Schema loaders fail closed on unknown fields, duplicate keys, invalid closed values, broken references, and unused policy objects. Do not add permissive compatibility shims for unmerged artifacts; update the two repositories together.
Netdata verification intentionally consumes the latest netdata/testdata master:
SOURCE-SEMANTICS.yaml and source-registry generator manifests pin full public exporter/source commits as evidence
provenance. Those pins describe exporter truth; they are not a pin of the testdata repository.master content.For a coordinated change, prepare both repositories together, merge the testdata evidence before the Netdata consumer that
requires it, update the local checkout to latest master, and rerun complete Netdata verification. This ordering avoids a
Netdata revision whose required evidence does not yet exist; it is not a substitute for the consumer verification.
The Prometheus source registries
workflow runs the shared generator tests and reproduces every generated registry byte-for-byte from its declared upstream
closure. It proves registry reproducibility and sandbox behavior. It does not prove a Netdata dashboard.
Netdata's Prometheus profile workflow:
master content;The workflow is the end-to-end consumer check. The testdata producer workflow and Netdata consumer workflow are complementary, not interchangeable.
Local authoring and command details live in the scoped documents below. Tests remain offline after a checkout exists; required mode converts missing external evidence from a skip into a failure.
Use these ownership rules when extending the framework:
promvalidation.promsemantics.promproof and shared request/result data in prominput or promreplay only when
both sides need it.netdata/testdata.SOURCE-SEMANTICS.yaml at registration/signal granularity.master.Do not introduce another registry, digest, copied support list, output snapshot, or architecture authority unless the existing owner cannot express the required invariant and that limitation is demonstrated first.
Executable field authorities are the strict types and validators in proof, semantics, and validation, plus the
production packages those validators exercise. If prose and executable behavior disagree, fix the prose or code at its
owning boundary rather than adding a second interpretation here.