master
md 197 lines 7.84 KB
Rendered Raw
1 # Collector Taxonomy
2
3 Collector chart taxonomy is authored in public repo source files and
4 generated into a dashboard-consumable JSON artifact.
5
6 ## Source Files
7
8 - Collector taxonomy authoring file:
9 `<collector>/taxonomy.yaml`, sibling to `metadata.yaml`.
10 - Section registry:
11 `integrations/taxonomy/sections.yaml`.
12 - Icon registry:
13 `integrations/taxonomy/icons.yaml`.
14 - Schemas:
15 `integrations/schemas/taxonomy_collector.json`,
16 `integrations/schemas/taxonomy_sections.json`,
17 `integrations/schemas/taxonomy_output.json`.
18 - Generator:
19 `integrations/gen_taxonomy.py`.
20 - Touched-collector checker:
21 `integrations/check_collector_taxonomy.py`.
22 - Seed helper:
23 `integrations/gen_taxonomy_seed.py`.
24
25 ## Authoring Contract
26
27 `taxonomy.yaml` v1 is a closed schema. Unknown core keys fail
28 validation; extension keys must be prefixed with `x_`.
29
30 Required top-level fields:
31
32 - `taxonomy_version: 1`
33 - `plugin_name`
34 - `module_name`
35 - either `placements` or `taxonomy_optout`, not both
36
37 Each placement requires `id`, `section_id`, `title`, and `items`.
38 `section_id` is the only accepted v1 section reference.
39 `section_path` is rejected in authoring files. Section IDs are stable
40 opaque handles; hierarchy is defined by `parent_id` in
41 `sections.yaml`.
42
43 `items:` is an ordered recursive tree. The allowed item kinds are:
44
45 - context-string shorthand such as `mysql.queries`; this is an owning
46 structural context leaf and normalizes to `type: owned_context`;
47 - `type: owned_context` with one literal `context`;
48 - `type: group` with stable hand-authored `id`, `title`, and nested
49 structural `items`;
50 - `type: flatten`, the structural equivalent of the legacy FE
51 `properties.justGroup` behavior;
52 - `type: selector` with one selector mechanism;
53 - `type: context`, a display widget that references contexts and
54 requires `contexts` plus `chart_library`;
55 - `type: grid`, `type: first_available`, and `type: view_switch` for
56 dashboard widget composition.
57
58 Strings are allowed only in structural positions: placement `items`,
59 `group.items`, and `flatten.items`. Grid bodies, first-available
60 alternatives, and view-switch branches must use explicit object
61 items. Nested `flatten` under `flatten.items` is rejected. The
62 recursion matrix is exhaustive: unlisted container/item combinations
63 are invalid.
64
65 `single_node:` is a sparse same-kind delta only. It may override
66 display, selector, or renderer fields allowed on the same item type.
67 It may not contain `type`, `items`, `multi_node`, `single_node`, or
68 change an owning item into a display widget. Whole-body single-vs-
69 multi differences use `type: view_switch`; `view_switch` and sparse
70 `single_node` are mutually exclusive on the same item.
71
72 Renderer-private payloads live only under `renderer:`. Current known
73 keys are `renderer.overlays`, `renderer.url_options`, and
74 `renderer.toolbox_elements`; future renderer-only additions must use
75 `x_*` under `renderer`. `toolbox_elements`, `overlays`, and
76 `url_options` are not valid item-body siblings.
77
78 ## Selectors And Context References
79
80 Every literal context owned by `owned_context` or referenced by a
81 `context` widget must exist in the owning collector's `metadata.yaml`
82 under `metrics.scopes[].metrics[].name`, unless the exact reference
83 uses the explicit unresolved-reference escape hatch:
84
85 ```yaml
86 contexts:
87 - context: mysql.future_context
88 unresolved:
89 reason: staged downstream rollout
90 owner: cloud-frontend
91 expires: "2026-08-01"
92 ```
93
94 Dynamic collectors must opt in from metadata:
95
96 ```yaml
97 metrics:
98 dynamic_context_prefixes:
99 - prefix: snmp.
100 reason: SNMP profiles emit vendor-specific contexts at runtime.
101 dynamic_collect_plugins:
102 - plugin: statsd.plugin
103 reason: statsd synthetic charts are operator-defined.
104 ```
105
106 `type: selector` owns the contexts it resolves from `context_prefix`
107 or `collect_plugin`. Selector objects inside a widget `contexts:`
108 array reference contexts but do not own them. `context_prefix_exclude`
109 is valid only on the same item/reference that also has
110 `context_prefix`. A `context_prefix:` value may narrow a declared
111 metadata dynamic namespace; for example, a collector that declares
112 `dynamic_context_prefixes: [{prefix: snmp., ...}]` may use
113 `context_prefix: [snmp.device_prof_]` in taxonomy authoring.
114
115 `collect_plugin:` selects by Agent `_collect_plugin` label. It is for
116 dynamic contexts that do not share a stable context-name prefix.
117
118 ## Output Artifact
119
120 `integrations/gen_taxonomy.py` emits gitignored
121 `integrations/taxonomy.json`:
122
123 - `taxonomy_schema_version`
124 - `source.netdata_commit`
125 - `source.generated_at`
126 - normalized `sections`
127 - normalized `placements`
128 - `opted_out_collectors`
129
130 Each placement and item includes:
131
132 - `resolved_contexts`: contexts owned by structural strings,
133 `owned_context`, and selector items.
134 - `referenced_contexts`: contexts referenced by display widgets,
135 grids, first-available alternatives, and view-switch widget
136 branches.
137 - `unresolved_references`: explicit unresolved-reference escape
138 hatches with `context`, `reason`, `owner`, `expires`, and
139 `item_path`. This is the durable signal that a widget reference is
140 intentionally unresolved instead of accidentally missing. `expires`
141 uses `YYYY-MM-DD`.
142
143 The snapshots are deterministic for identical repository input and
144 preserve author item order for the recursive tree.
145
146 ## CI Contract
147
148 Pull requests run `integrations/check_collector_taxonomy.py` from
149 `.github/workflows/check-markdown.yml`. The checker:
150
151 - validates all committed `taxonomy.yaml` files;
152 - validates the generated artifact shape;
153 - fails when a PR adds/removes a collector `taxonomy.yaml`;
154 - fails when a PR edits a collector `metadata.yaml` metrics block
155 without a sibling `taxonomy.yaml`.
156
157 The master regeneration workflow runs `gen_taxonomy.py` and removes
158 the gitignored artifact during cleanup.
159
160 ## Finding Codes
161
162 Active v1 codes:
163
164 | Code | Severity | Meaning |
165 |---|---|---|
166 | TAX001 | fatal | Schema/load failure or missing matching metadata. |
167 | TAX002 | reserved | Reserved for a future empty-effective-node lint; current empty authoring shapes fail schema/load validation as TAX001. |
168 | TAX003 | fatal | Literal context is not declared by the owning collector metadata. |
169 | TAX006 | fatal | Duplicate section or placement ownership key. |
170 | TAX021 | fatal | Invalid `single_node` override key or shape. |
171 | TAX022 | fatal | `multi_node:` used outside `type: view_switch`. |
172 | TAX023 | fatal | List-merge syntax such as `*_extend` used; v1 lists replace. |
173 | TAX024 | warning | Empty `single_node:` block. |
174 | TAX025 | warning | `single_node` override equals the top-level value. |
175 | TAX028 | fatal | Unknown/deprecated section, unknown icon, or invalid section authoring shape. |
176 | TAX029 | fatal | Invalid dynamic declaration location or `context_prefix_exclude` usage. |
177 | TAX030 | fatal | Touched collector needs `taxonomy.yaml` coverage. |
178 | TAX031 | fatal | `context_prefix` used without metadata opt-in. |
179 | TAX032 | reserved | Reserved for a future narrower prefix-overlap diagnostic; current selector ownership overlap conflicts emit TAX036. |
180 | TAX033 | fatal | Resolved context owned by more than one placement. |
181 | TAX034 | warning | Literal context is redundant because a prefix already covers it. |
182 | TAX035 | fatal | `collect_plugin` used without metadata opt-in. |
183 | TAX036 | fatal | Selector overlap conflict across collector/type boundaries. |
184 | TAX037 | fatal | Literal context is referenced by a widget but not owned by any structural item. |
185 | TAX038 | warning | `unresolved` escape hatch is stale because the context now resolves. |
186
187 Removed v1 codes:
188
189 - TAX026 and TAX027 were removed with `only_views`.
190 - TAX040 through TAX042 were removed with chart-recipe manifests.
191
192 ## Contributor Rule
193
194 Collector context changes and taxonomy changes move together. A PR
195 that adds, removes, or renames chart contexts must update
196 `metadata.yaml` and `taxonomy.yaml` in the same change unless the
197 collector uses a declared dynamic selector that covers the context.