feat(go.d/framework/chartengine): apply context_namespace to autogen chart contexts (#22642)
Ilya Mashchenko committed
Jun 6, 2026 at 17:35 UTC
35e8d07e5e56754ef3790d5cb9aed851b4311515
11 files changed
+315
-147
src/go/plugin/framework/chartengine/README.md
+1
@@ -168,6 +168,7 @@ Default lifecycle policy when template omits lifecycle:
168
| Topic | Behavior |
169
|-----------------------|------------------------------------------------------------------------------------------------------------------------------------------------|
170
| Trigger | Unmatched series only when autogen is enabled |
171
+| Context namespace | Autogen context = top-level `context_namespace` + the full metric name (which includes any `SnapshotMeter` prefix); empty namespace leaves the bare name. A non-empty meter prefix stacks after `context_namespace`, so pair `context_namespace` with `SnapshotMeter("")` to avoid a doubled prefix |
172
| Structured families | Autogen has dedicated source builders for flattened `Histogram`, `Summary`, `StateSet`, and `MeasureSet` families |
173
| Metric metadata usage | Uses `metrix.MetricMeta` hints for title/family/unit where allowed |
174
| Type ID budget | Enforced via `AutogenPolicy.MaxTypeIDLen` + effective emit type-id prefix (`WithEmitTypeIDBudgetPrefix(...)`) |
src/go/plugin/framework/chartengine/autogen.go
+11
-3
@@ -79,6 +79,8 @@ func (e *Engine) resolveAutogenRoute(
79
return nil, false, nil
80
}
81
82
+ namespace := e.state.cfg.autogenContextNamespace
83
+
84
route, ok, err := buildAutogenRoute(metricName, labels, meta, policy, e.state.cfg.autogenTypeID)
85
if err != nil {
86
return nil, false, err
@@ -112,7 +114,7 @@ func (e *Engine) resolveAutogenRoute(
114
Meta: program.ChartMeta{
115
Title: title,
116
Family: route.family,
115
- Context: getAutogenChartContext(route.contextName),
117
+ Context: getAutogenChartContext(namespace, route.contextName),
118
Units: route.units,
119
Algorithm: route.algorithm,
120
Type: route.chartType,
@@ -601,10 +603,16 @@ func getAutogenChartTitle(metricName string) string {
603
return fmt.Sprintf("Metric \"%s\"", metricName)
604
}
605
604
-func getAutogenChartContext(metricName string) string {
606
+// getAutogenChartContext builds an autogen chart context, prefixed by the spec's root
607
+// context_namespace when set ("prometheus" + "foo" -> "prometheus.foo"), matching the
608
+// template compiler's "." join. Empty namespace -> the bare metric name (unchanged).
609
+func getAutogenChartContext(namespace, metricName string) string {
610
metricName = strings.TrimSpace(metricName)
611
if metricName == "" {
607
- return "metric"
612
+ metricName = "metric"
613
+ }
614
+ if namespace = strings.TrimSpace(namespace); namespace != "" {
615
+ return namespace + "." + metricName
616
}
617
return metricName
618
}
src/go/plugin/framework/chartengine/autogen_test.go
+21
@@ -372,6 +372,27 @@ func TestFitsTypeIDBudget(t *testing.T) {
372
}
373
}
374
375
+func TestGetAutogenChartContext(t *testing.T) {
376
+ tests := map[string]struct {
377
+ namespace string
378
+ metric string
379
+ want string
380
+ }{
381
+ "empty namespace returns bare metric": {namespace: "", metric: "foo", want: "foo"},
382
+ "single-segment namespace is prefixed": {namespace: "prometheus", metric: "foo", want: "prometheus.foo"},
383
+ "multi-segment namespace composes with dot": {namespace: "prometheus.app", metric: "foo", want: "prometheus.app.foo"},
384
+ "whitespace-only namespace is treated empty": {namespace: " ", metric: "foo", want: "foo"},
385
+ "empty metric falls back to metric": {namespace: "", metric: "", want: "metric"},
386
+ "namespace with empty metric": {namespace: "prometheus", metric: "", want: "prometheus.metric"},
387
+ }
388
+
389
+ for name, tc := range tests {
390
+ t.Run(name, func(t *testing.T) {
391
+ assert.Equal(t, tc.want, getAutogenChartContext(tc.namespace, tc.metric))
392
+ })
393
+ }
394
+}
395
+
396
func sortedLabelView(labels map[string]string) metrix.LabelView {
397
items := make([]metrix.Label, 0, len(labels))
398
for key, value := range labels {
src/go/plugin/framework/chartengine/engine.go
+1
@@ -72,6 +72,7 @@ func (e *Engine) Load(spec *charttpl.Spec, revision uint64) error {
72
e.mu.Lock()
73
e.state.cfg.autogen = autogenPolicy
74
e.state.cfg.selector = selectorPolicy
75
+ e.state.cfg.autogenContextNamespace = spec.ContextNamespace
76
e.state.program = compiled
77
e.state.matchIndex = buildMatchIndex(compiled.Charts())
78
// Template revision change resets routing/materialization internals.
src/go/plugin/framework/chartengine/options.go
+14
-11
@@ -12,17 +12,20 @@ import (
12
)
13
14
type engineConfig struct {
15
- autogen AutogenPolicy
16
- autogenTypeID string
17
- selector metrixselector.Selector
18
- autogenOverride policyOverride[AutogenPolicy]
19
- selectorOverride policyOverride[metrixselector.Selector]
20
- runtimeStore metrix.RuntimeStore
21
- runtimeStoreSet bool
22
- runtimeObserver func(PlanRuntimeSample)
23
- log *logger.Logger
24
- seriesSelection seriesSelectionMode
25
- runtimePlanner bool
15
+ autogen AutogenPolicy
16
+ autogenTypeID string
17
+ // autogenContextNamespace prefixes autogen chart contexts (the spec's root
18
+ // context_namespace), so autogen and template charts share one namespace.
19
+ autogenContextNamespace string
20
+ selector metrixselector.Selector
21
+ autogenOverride policyOverride[AutogenPolicy]
22
+ selectorOverride policyOverride[metrixselector.Selector]
23
+ runtimeStore metrix.RuntimeStore
24
+ runtimeStoreSet bool
25
+ runtimeObserver func(PlanRuntimeSample)
26
+ log *logger.Logger
27
+ seriesSelection seriesSelectionMode
28
+ runtimePlanner bool
29
}
30
31
type policyOverride[T any] struct {
src/go/plugin/framework/chartengine/planner_test.go
+76
@@ -233,6 +233,8 @@ func TestBuildPlanLegacySingleScenarioCases(t *testing.T) {
233
"BuildPlanAutogenRemovalLifecycleExpiry": {run: runTestBuildPlanAutogenRemovalLifecycleExpiry},
234
"BuildPlanFirstWriterWinsAndAccumulatesRepeatedRoutes": {run: runTestBuildPlanFirstWriterWinsAndAccumulatesRepeatedRoutes},
235
"BuildPlanEmptyEmissionAndScratchReusePruneAcrossCycles": {run: runTestBuildPlanEmptyEmissionAndScratchReusePruneAcrossCycles},
236
+ "BuildPlanAutogenContextNamespacePrefixesContext": {run: runTestBuildPlanAutogenContextNamespacePrefixesContext},
237
+ "BuildPlanAutogenContextNamespaceStubGroupOnly": {run: runTestBuildPlanAutogenContextNamespaceStubGroupOnly},
238
}
239
240
for name, tc := range tests {
@@ -999,6 +1001,80 @@ groups:
1001
assert.Equal(t, float64(10), update.Values[0].Float64)
1002
}
1003
1004
+func runTestBuildPlanAutogenContextNamespacePrefixesContext(t *testing.T) {
1005
+ e, err := New(WithEnginePolicy(EnginePolicy{Autogen: &AutogenPolicy{Enabled: true}}))
1006
+ require.NoError(t, err)
1007
+
1008
+ // Root context_namespace must prefix autogen (unmatched-series) chart contexts,
1009
+ // joined with "." like the template compiler ("prometheus" + "svc.errors_total").
1010
+ yaml := `
1011
+version: v1
1012
+context_namespace: prometheus
1013
+groups:
1014
+ - family: Service
1015
+ metrics:
1016
+ - svc.requests_total
1017
+ charts:
1018
+ - title: Requests
1019
+ context: requests
1020
+ units: requests/s
1021
+ dimensions:
1022
+ - selector: svc.requests_total
1023
+ name: total
1024
+`
1025
+ require.NoError(t, e.LoadYAML([]byte(yaml), 1))
1026
+
1027
+ store := metrix.NewCollectorStore()
1028
+ cc := mustCycleController(t, store)
1029
+ sm := store.Write().SnapshotMeter("svc")
1030
+ unmatched := sm.Counter("errors_total")
1031
+ methodGET := sm.LabelSet(metrix.Label{Key: "method", Value: "GET"})
1032
+
1033
+ cc.BeginCycle()
1034
+ unmatched.ObserveTotal(10, methodGET)
1035
+ cc.CommitCycleSuccess()
1036
+
1037
+ plan, err := buildPlan(e, store.Read(metrix.ReadFlatten()))
1038
+ require.NoError(t, err)
1039
+
1040
+ create := findCreateChartAction(plan)
1041
+ require.NotNil(t, create)
1042
+ assert.Equal(t, "prometheus.svc.errors_total", create.Meta.Context)
1043
+}
1044
+
1045
+// Mirrors the autogen-only collector shape: a stub group satisfies the
1046
+// required groups[] but declares no charts, so every series is unmatched and handled by autogen,
1047
+// with contexts prefixed by the top-level context_namespace.
1048
+func runTestBuildPlanAutogenContextNamespaceStubGroupOnly(t *testing.T) {
1049
+ e, err := New(WithEnginePolicy(EnginePolicy{Autogen: &AutogenPolicy{Enabled: true}}))
1050
+ require.NoError(t, err)
1051
+
1052
+ yaml := `
1053
+version: v1
1054
+context_namespace: prometheus
1055
+groups:
1056
+ - family: Prometheus
1057
+`
1058
+ require.NoError(t, e.LoadYAML([]byte(yaml), 1))
1059
+
1060
+ store := metrix.NewCollectorStore()
1061
+ cc := mustCycleController(t, store)
1062
+ sm := store.Write().SnapshotMeter("")
1063
+ unmatched := sm.Counter("requests_total")
1064
+ methodGET := sm.LabelSet(metrix.Label{Key: "method", Value: "GET"})
1065
+
1066
+ cc.BeginCycle()
1067
+ unmatched.ObserveTotal(10, methodGET)
1068
+ cc.CommitCycleSuccess()
1069
+
1070
+ plan, err := buildPlan(e, store.Read(metrix.ReadFlatten()))
1071
+ require.NoError(t, err)
1072
+
1073
+ create := findCreateChartAction(plan)
1074
+ require.NotNil(t, create)
1075
+ assert.Equal(t, "prometheus.requests_total", create.Meta.Context)
1076
+}
1077
+
1078
func runTestBuildPlanAutogenUsesMetricMetadataForScalar(t *testing.T) {
1079
e, err := New(WithEnginePolicy(EnginePolicy{Autogen: &AutogenPolicy{Enabled: true}}))
1080
require.NoError(t, err)
src/go/plugin/framework/charttpl/README.md
+12
@@ -268,6 +268,18 @@ For example:
268
| Chart `context` | `queries` |
269
| **Resulting context** | **`mysql.queries`** |
270
271
+**Autogen charts** — the **top-level** `context_namespace` also prefixes the contexts of charts
272
+created by `engine.autogen` (metrics not matched by any template dimension), joined with the same
273
+`.`. Group-level `context_namespace` does not apply to autogen, since unmatched series belong to
274
+no group. For example, with top-level `context_namespace: nagios`, an unmatched metric
275
+`check_load` autogenerates the context `nagios.check_load`.
276
+
277
+The autogen context is `context_namespace` joined with the **full metric name**, and a metric's name
278
+includes any `SnapshotMeter("<prefix>")` prefix (`<prefix>.<instrument>`). So a non-empty meter prefix
279
+**stacks after** `context_namespace` — e.g. `context_namespace: app` with `SnapshotMeter("app")` and
280
+instrument `foo` yields `app.app.foo`. When you set `context_namespace`, write metrics with
281
+`SnapshotMeter("")` so the namespace has a single source; do not also encode it in the meter prefix.
282
+
283
### 3. engine
284
285
Template-level policy that controls metric filtering and autogeneration.
src/go/plugin/scripts.d/collector/nagios/charts.yaml
+10
-10
@@ -10,11 +10,11 @@ groups:
10
groups:
11
- family: Execution
12
metrics:
13
- - nagios.job.execution_state
14
- - nagios.job.perfdata.threshold_state
15
- - nagios.job.execution_duration
16
- - nagios.job.execution_cpu_total
17
- - nagios.job.execution_max_rss
13
+ - job.execution_state
14
+ - job.perfdata.threshold_state
15
+ - job.execution_duration
16
+ - job.execution_cpu_total
17
+ - job.execution_max_rss
18
charts:
19
- id: job_execution_state
20
title: Job Execution State
@@ -24,7 +24,7 @@ groups:
24
instances:
25
by_labels: [nagios_job]
26
dimensions:
27
- - selector: nagios.job.execution_state
27
+ - selector: job.execution_state
28
- id: job_perfdata_threshold_state
29
title: Job Perfdata Threshold State
30
context: perfdata_threshold_state
@@ -33,7 +33,7 @@ groups:
33
instances:
34
by_labels: [nagios_job, perfdata_value]
35
dimensions:
36
- - selector: nagios.job.perfdata.threshold_state
36
+ - selector: job.perfdata.threshold_state
37
- id: job_execution_duration
38
title: Execution Duration
39
context: execution_duration
@@ -42,7 +42,7 @@ groups:
42
instances:
43
by_labels: [nagios_job]
44
dimensions:
45
- - selector: nagios.job.execution_duration
45
+ - selector: job.execution_duration
46
name: duration
47
options:
48
float: true
@@ -54,7 +54,7 @@ groups:
54
instances:
55
by_labels: [nagios_job]
56
dimensions:
57
- - selector: nagios.job.execution_cpu_total
57
+ - selector: job.execution_cpu_total
58
name: total
59
options:
60
float: true
@@ -66,5 +66,5 @@ groups:
66
instances:
67
by_labels: [nagios_job]
68
dimensions:
69
- - selector: nagios.job.execution_max_rss
69
+ - selector: job.execution_max_rss
70
name: rss
src/go/plugin/scripts.d/collector/nagios/collect.go
+3
-1
@@ -69,7 +69,9 @@ func (c *Collector) completeDueCheck(now time.Time, res checkRunResult) {
69
}
70
71
func (c *Collector) emitMetrics(execMetrics executionMetrics) {
72
- sm := c.store.Write().SnapshotMeter("nagios")
72
+ // Empty meter prefix: the namespace comes from charts.yaml context_namespace (nagios),
73
+ // which also prefixes autogen perfdata contexts. A "nagios" meter prefix would double it.
74
+ sm := c.store.Write().SnapshotMeter("")
75
76
jobName := c.job.config.Name
77
if jobName == "" {
src/go/plugin/scripts.d/collector/nagios/collector_test.go
+89
-89
@@ -43,17 +43,17 @@ func TestCollector_ChartTemplateYAML(t *testing.T) {
43
}{
44
"execution duration dimension is float": {
45
context: "execution_duration",
46
- selector: "nagios.job.execution_duration",
46
+ selector: "job.execution_duration",
47
wantFloat: true,
48
},
49
"execution cpu dimension is float": {
50
context: "execution_cpu",
51
- selector: "nagios.job.execution_cpu_total",
51
+ selector: "job.execution_cpu_total",
52
wantFloat: true,
53
},
54
"execution memory dimension is integer": {
55
context: "execution_memory",
56
- selector: "nagios.job.execution_max_rss",
56
+ selector: "job.execution_max_rss",
57
wantFloat: false,
58
},
59
}
@@ -360,22 +360,22 @@ func TestCollector_Collect(t *testing.T) {
360
361
read := coll.MetricStore().Read(metrix.ReadRaw())
362
flat := coll.MetricStore().Read(metrix.ReadFlatten())
363
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "check_disk", "nagios.job.execution_state": "ok"}, 1)
364
- assertMetricValue(t, flat, "nagios.perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "check_disk", "nagios.perfdata.true.job.execution_state": "ok"}, 1)
365
- assertMetricChartFamily(t, flat, "nagios.perfdata.true.job.execution_state", "Perfdata/true")
366
- assertMetricValue(t, flat, "nagios.job.execution_duration", metrix.Labels{"nagios_job": "check_disk"}, 2.5)
367
- assertMetricMeta(t, flat, "nagios.job.execution_duration", "seconds", true)
363
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "check_disk", "job.execution_state": "ok"}, 1)
364
+ assertMetricValue(t, flat, "perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "check_disk", "perfdata.true.job.execution_state": "ok"}, 1)
365
+ assertMetricChartFamily(t, flat, "perfdata.true.job.execution_state", "Perfdata/true")
366
+ assertMetricValue(t, flat, "job.execution_duration", metrix.Labels{"nagios_job": "check_disk"}, 2.5)
367
+ assertMetricMeta(t, flat, "job.execution_duration", "seconds", true)
368
if runtime.GOOS != "windows" {
369
- assertMetricValue(t, flat, "nagios.job.execution_cpu_total", metrix.Labels{"nagios_job": "check_disk"}, 0.5)
370
- assertMetricValue(t, flat, "nagios.job.execution_max_rss", metrix.Labels{"nagios_job": "check_disk"}, 12345)
371
- assertMetricMeta(t, flat, "nagios.job.execution_cpu_total", "seconds", true)
372
- assertMetricMeta(t, flat, "nagios.job.execution_max_rss", "bytes", false)
369
+ assertMetricValue(t, flat, "job.execution_cpu_total", metrix.Labels{"nagios_job": "check_disk"}, 0.5)
370
+ assertMetricValue(t, flat, "job.execution_max_rss", metrix.Labels{"nagios_job": "check_disk"}, 12345)
371
+ assertMetricMeta(t, flat, "job.execution_cpu_total", "seconds", true)
372
+ assertMetricMeta(t, flat, "job.execution_max_rss", "bytes", false)
373
} else {
374
- assertMetricMissing(t, flat, "nagios.job.execution_cpu_total", metrix.Labels{"nagios_job": "check_disk"})
375
- assertMetricMissing(t, flat, "nagios.job.execution_max_rss", metrix.Labels{"nagios_job": "check_disk"})
374
+ assertMetricMissing(t, flat, "job.execution_cpu_total", metrix.Labels{"nagios_job": "check_disk"})
375
+ assertMetricMissing(t, flat, "job.execution_max_rss", metrix.Labels{"nagios_job": "check_disk"})
376
}
377
- assertMetricValue(t, flat, "nagios.perfdata.true.bytes_used_value", metrix.Labels{"nagios_job": "check_disk", metrix.MeasureSetFieldLabel: "value"}, 30000)
378
- point, ok := read.MeasureSet("nagios.perfdata.true.bytes_used", metrix.Labels{"nagios_job": "check_disk"})
377
+ assertMetricValue(t, flat, "perfdata.true.bytes_used_value", metrix.Labels{"nagios_job": "check_disk", metrix.MeasureSetFieldLabel: "value"}, 30000)
378
+ point, ok := read.MeasureSet("perfdata.true.bytes_used", metrix.Labels{"nagios_job": "check_disk"})
379
require.True(t, ok)
380
assert.Equal(t, 30000.0, point.Values[0])
381
@@ -384,15 +384,15 @@ func TestCollector_Collect(t *testing.T) {
384
assert.Equal(t, 1, runner.calls)
385
386
flat = coll.MetricStore().Read(metrix.ReadFlatten())
387
- assertMetricValue(t, flat, "nagios.job.execution_duration", metrix.Labels{"nagios_job": "check_disk"}, 0)
387
+ assertMetricValue(t, flat, "job.execution_duration", metrix.Labels{"nagios_job": "check_disk"}, 0)
388
if runtime.GOOS != "windows" {
389
- assertMetricValue(t, flat, "nagios.job.execution_cpu_total", metrix.Labels{"nagios_job": "check_disk"}, 0)
390
- assertMetricValue(t, flat, "nagios.job.execution_max_rss", metrix.Labels{"nagios_job": "check_disk"}, 0)
389
+ assertMetricValue(t, flat, "job.execution_cpu_total", metrix.Labels{"nagios_job": "check_disk"}, 0)
390
+ assertMetricValue(t, flat, "job.execution_max_rss", metrix.Labels{"nagios_job": "check_disk"}, 0)
391
} else {
392
- assertMetricMissing(t, flat, "nagios.job.execution_cpu_total", metrix.Labels{"nagios_job": "check_disk"})
393
- assertMetricMissing(t, flat, "nagios.job.execution_max_rss", metrix.Labels{"nagios_job": "check_disk"})
392
+ assertMetricMissing(t, flat, "job.execution_cpu_total", metrix.Labels{"nagios_job": "check_disk"})
393
+ assertMetricMissing(t, flat, "job.execution_max_rss", metrix.Labels{"nagios_job": "check_disk"})
394
}
395
- assertMetricValue(t, flat, "nagios.perfdata.true.bytes_used_value", metrix.Labels{"nagios_job": "check_disk", metrix.MeasureSetFieldLabel: "value"}, 30000)
395
+ assertMetricValue(t, flat, "perfdata.true.bytes_used_value", metrix.Labels{"nagios_job": "check_disk", metrix.MeasureSetFieldLabel: "value"}, 30000)
396
},
397
},
398
"uses explicit check name for perfdata namespace": {
@@ -426,11 +426,11 @@ func TestCollector_Collect(t *testing.T) {
426
assert.Equal(t, 1, runner.calls)
427
428
flat := coll.MetricStore().Read(metrix.ReadFlatten())
429
- assertMetricValue(t, flat, "nagios.perfdata.check_service.job.execution_state", metrix.Labels{"nagios_job": "check_service_job", "nagios.perfdata.check_service.job.execution_state": "ok"}, 1)
430
- assertMetricChartFamily(t, flat, "nagios.perfdata.check_service.job.execution_state", "Perfdata/check_service")
431
- assertMetricValue(t, flat, "nagios.perfdata.check_service.bytes_used_value", metrix.Labels{"nagios_job": "check_service_job", metrix.MeasureSetFieldLabel: "value"}, 30000)
432
- assertMetricMissing(t, flat, "nagios.perfdata.pwsh.job.execution_state", metrix.Labels{"nagios_job": "check_service_job", "nagios.perfdata.pwsh.job.execution_state": "ok"})
433
- assertMetricMissing(t, flat, "nagios.perfdata.pwsh.bytes_used_value", metrix.Labels{"nagios_job": "check_service_job", metrix.MeasureSetFieldLabel: "value"})
429
+ assertMetricValue(t, flat, "perfdata.check_service.job.execution_state", metrix.Labels{"nagios_job": "check_service_job", "perfdata.check_service.job.execution_state": "ok"}, 1)
430
+ assertMetricChartFamily(t, flat, "perfdata.check_service.job.execution_state", "Perfdata/check_service")
431
+ assertMetricValue(t, flat, "perfdata.check_service.bytes_used_value", metrix.Labels{"nagios_job": "check_service_job", metrix.MeasureSetFieldLabel: "value"}, 30000)
432
+ assertMetricMissing(t, flat, "perfdata.pwsh.job.execution_state", metrix.Labels{"nagios_job": "check_service_job", "perfdata.pwsh.job.execution_state": "ok"})
433
+ assertMetricMissing(t, flat, "perfdata.pwsh.bytes_used_value", metrix.Labels{"nagios_job": "check_service_job", metrix.MeasureSetFieldLabel: "value"})
434
435
*now = now.Add(1 * time.Second)
436
},
@@ -506,22 +506,22 @@ func TestCollector_Collect(t *testing.T) {
506
assert.Equal(t, 1, runner.calls)
507
508
flat := coll.MetricStore().Read(metrix.ReadFlatten())
509
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "period_job", "nagios.job.execution_state": "ok"}, 1)
510
- assertMetricValue(t, flat, "nagios.perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "period_job", "nagios.perfdata.true.job.execution_state": "ok"}, 1)
511
- assertMetricValue(t, flat, "nagios.perfdata.true.bytes_used_value", metrix.Labels{"nagios_job": "period_job", metrix.MeasureSetFieldLabel: "value"}, 30000)
512
- assertMetricValue(t, flat, "nagios.job.perfdata.threshold_state", metrix.Labels{
513
- "nagios_job": "period_job",
514
- perfdataValueLabelKey: "bytes_used",
515
- "nagios.job.perfdata.threshold_state": perfThresholdStateWarning,
509
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "period_job", "job.execution_state": "ok"}, 1)
510
+ assertMetricValue(t, flat, "perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "period_job", "perfdata.true.job.execution_state": "ok"}, 1)
511
+ assertMetricValue(t, flat, "perfdata.true.bytes_used_value", metrix.Labels{"nagios_job": "period_job", metrix.MeasureSetFieldLabel: "value"}, 30000)
512
+ assertMetricValue(t, flat, "job.perfdata.threshold_state", metrix.Labels{
513
+ "nagios_job": "period_job",
514
+ perfdataValueLabelKey: "bytes_used",
515
+ "job.perfdata.threshold_state": perfThresholdStateWarning,
516
}, 1)
517
518
raw := coll.MetricStore().Read()
519
- thresholdMetric := "nagios.perfdata.true.bytes_used_threshold_state"
519
+ thresholdMetric := "perfdata.true.bytes_used_threshold_state"
520
thresholdLabels := metrix.Labels{"nagios_job": "period_job"}
521
point, ok := raw.StateSet(thresholdMetric, thresholdLabels)
522
require.True(t, ok)
523
assert.True(t, point.States[perfThresholdStateWarning])
524
- alertThresholdMetric := "nagios.job.perfdata.threshold_state"
524
+ alertThresholdMetric := "job.perfdata.threshold_state"
525
alertThresholdLabels := metrix.Labels{"nagios_job": "period_job", perfdataValueLabelKey: "bytes_used"}
526
alertPoint, ok := raw.StateSet(alertThresholdMetric, alertThresholdLabels)
527
require.True(t, ok)
@@ -532,11 +532,11 @@ func TestCollector_Collect(t *testing.T) {
532
assert.Equal(t, 1, runner.calls)
533
534
flat = coll.MetricStore().Read(metrix.ReadFlatten())
535
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "period_job", "nagios.job.execution_state": "paused"}, 1)
536
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "period_job", "nagios.job.execution_state": "retry"}, 0)
537
- assertMetricValue(t, flat, "nagios.perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "period_job", "nagios.perfdata.true.job.execution_state": "paused"}, 1)
538
- assertMetricValue(t, flat, "nagios.perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "period_job", "nagios.perfdata.true.job.execution_state": "retry"}, 0)
539
- assertMetricValue(t, flat, "nagios.perfdata.true.bytes_used_value", metrix.Labels{"nagios_job": "period_job", metrix.MeasureSetFieldLabel: "value"}, 30000)
535
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "period_job", "job.execution_state": "paused"}, 1)
536
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "period_job", "job.execution_state": "retry"}, 0)
537
+ assertMetricValue(t, flat, "perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "period_job", "perfdata.true.job.execution_state": "paused"}, 1)
538
+ assertMetricValue(t, flat, "perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "period_job", "perfdata.true.job.execution_state": "retry"}, 0)
539
+ assertMetricValue(t, flat, "perfdata.true.bytes_used_value", metrix.Labels{"nagios_job": "period_job", metrix.MeasureSetFieldLabel: "value"}, 30000)
540
assertMetricValue(t, flat, thresholdMetric, metrix.Labels{"nagios_job": "period_job", thresholdMetric: perfThresholdStateWarning}, 0)
541
assertMetricValue(t, flat, thresholdMetric, metrix.Labels{"nagios_job": "period_job", thresholdMetric: perfThresholdStateOK}, 0)
542
assertMetricValue(t, flat, thresholdMetric, metrix.Labels{"nagios_job": "period_job", thresholdMetric: perfThresholdStateCritical}, 0)
@@ -567,9 +567,9 @@ func TestCollector_Collect(t *testing.T) {
567
assert.Equal(t, 2, runner.calls)
568
569
flat = coll.MetricStore().Read(metrix.ReadFlatten())
570
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "period_job", "nagios.job.execution_state": "ok"}, 1)
571
- assertMetricValue(t, flat, "nagios.perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "period_job", "nagios.perfdata.true.job.execution_state": "ok"}, 1)
572
- assertMetricValue(t, flat, "nagios.perfdata.true.bytes_used_value", metrix.Labels{"nagios_job": "period_job", metrix.MeasureSetFieldLabel: "value"}, 10000)
570
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "period_job", "job.execution_state": "ok"}, 1)
571
+ assertMetricValue(t, flat, "perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "period_job", "perfdata.true.job.execution_state": "ok"}, 1)
572
+ assertMetricValue(t, flat, "perfdata.true.bytes_used_value", metrix.Labels{"nagios_job": "period_job", metrix.MeasureSetFieldLabel: "value"}, 10000)
573
574
raw = coll.MetricStore().Read()
575
point, ok = raw.StateSet(thresholdMetric, thresholdLabels)
@@ -647,19 +647,19 @@ func TestCollector_Collect(t *testing.T) {
647
assert.Equal(t, 1, runner.calls)
648
assert.Equal(t, 2, coll.state.currentAttempt())
649
flat := coll.MetricStore().Read(metrix.ReadFlatten())
650
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "retry_job", "nagios.job.execution_state": "warning"}, 1)
651
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "retry_job", "nagios.job.execution_state": "retry"}, 1)
652
- assertMetricValue(t, flat, "nagios.perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "retry_job", "nagios.perfdata.true.job.execution_state": "warning"}, 1)
653
- assertMetricValue(t, flat, "nagios.perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "retry_job", "nagios.perfdata.true.job.execution_state": "retry"}, 1)
654
- assertMetricValue(t, flat, "nagios.job.perfdata.threshold_state", metrix.Labels{
655
- "nagios_job": "retry_job",
656
- perfdataValueLabelKey: "bytes_used",
657
- "nagios.job.perfdata.threshold_state": perfThresholdStateWarning,
650
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "retry_job", "job.execution_state": "warning"}, 1)
651
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "retry_job", "job.execution_state": "retry"}, 1)
652
+ assertMetricValue(t, flat, "perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "retry_job", "perfdata.true.job.execution_state": "warning"}, 1)
653
+ assertMetricValue(t, flat, "perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "retry_job", "perfdata.true.job.execution_state": "retry"}, 1)
654
+ assertMetricValue(t, flat, "job.perfdata.threshold_state", metrix.Labels{
655
+ "nagios_job": "retry_job",
656
+ perfdataValueLabelKey: "bytes_used",
657
+ "job.perfdata.threshold_state": perfThresholdStateWarning,
658
}, 1)
659
- assertMetricValue(t, flat, "nagios.job.perfdata.threshold_state", metrix.Labels{
660
- "nagios_job": "retry_job",
661
- perfdataValueLabelKey: "bytes_used",
662
- "nagios.job.perfdata.threshold_state": perfThresholdStateRetry,
659
+ assertMetricValue(t, flat, "job.perfdata.threshold_state", metrix.Labels{
660
+ "nagios_job": "retry_job",
661
+ perfdataValueLabelKey: "bytes_used",
662
+ "job.perfdata.threshold_state": perfThresholdStateRetry,
663
}, 1)
664
665
*now = now.Add(9 * time.Second)
@@ -671,17 +671,17 @@ func TestCollector_Collect(t *testing.T) {
671
assert.Equal(t, 2, runner.calls)
672
assert.Equal(t, 1, coll.state.currentAttempt())
673
flat = coll.MetricStore().Read(metrix.ReadFlatten())
674
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "retry_job", "nagios.job.execution_state": "ok"}, 1)
675
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "retry_job", "nagios.job.execution_state": "retry"}, 0)
676
- assertMetricValue(t, flat, "nagios.job.perfdata.threshold_state", metrix.Labels{
677
- "nagios_job": "retry_job",
678
- perfdataValueLabelKey: "bytes_used",
679
- "nagios.job.perfdata.threshold_state": perfThresholdStateOK,
674
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "retry_job", "job.execution_state": "ok"}, 1)
675
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "retry_job", "job.execution_state": "retry"}, 0)
676
+ assertMetricValue(t, flat, "job.perfdata.threshold_state", metrix.Labels{
677
+ "nagios_job": "retry_job",
678
+ perfdataValueLabelKey: "bytes_used",
679
+ "job.perfdata.threshold_state": perfThresholdStateOK,
680
}, 1)
681
- assertMetricValue(t, flat, "nagios.job.perfdata.threshold_state", metrix.Labels{
682
- "nagios_job": "retry_job",
683
- perfdataValueLabelKey: "bytes_used",
684
- "nagios.job.perfdata.threshold_state": perfThresholdStateRetry,
681
+ assertMetricValue(t, flat, "job.perfdata.threshold_state", metrix.Labels{
682
+ "nagios_job": "retry_job",
683
+ perfdataValueLabelKey: "bytes_used",
684
+ "job.perfdata.threshold_state": perfThresholdStateRetry,
685
}, 0)
686
},
687
},
@@ -739,17 +739,17 @@ func TestCollector_Collect(t *testing.T) {
739
assert.Equal(t, 1, runner.calls)
740
741
flat := coll.MetricStore().Read(metrix.ReadFlatten())
742
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "paused_retry_job", "nagios.job.execution_state": "warning"}, 1)
743
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "paused_retry_job", "nagios.job.execution_state": "retry"}, 1)
744
- assertMetricValue(t, flat, "nagios.job.perfdata.threshold_state", metrix.Labels{
745
- "nagios_job": "paused_retry_job",
746
- perfdataValueLabelKey: "bytes_used",
747
- "nagios.job.perfdata.threshold_state": perfThresholdStateWarning,
742
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "paused_retry_job", "job.execution_state": "warning"}, 1)
743
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "paused_retry_job", "job.execution_state": "retry"}, 1)
744
+ assertMetricValue(t, flat, "job.perfdata.threshold_state", metrix.Labels{
745
+ "nagios_job": "paused_retry_job",
746
+ perfdataValueLabelKey: "bytes_used",
747
+ "job.perfdata.threshold_state": perfThresholdStateWarning,
748
}, 1)
749
- assertMetricValue(t, flat, "nagios.job.perfdata.threshold_state", metrix.Labels{
750
- "nagios_job": "paused_retry_job",
751
- perfdataValueLabelKey: "bytes_used",
752
- "nagios.job.perfdata.threshold_state": perfThresholdStateRetry,
749
+ assertMetricValue(t, flat, "job.perfdata.threshold_state", metrix.Labels{
750
+ "nagios_job": "paused_retry_job",
751
+ perfdataValueLabelKey: "bytes_used",
752
+ "job.perfdata.threshold_state": perfThresholdStateRetry,
753
}, 1)
754
755
*now = time.Date(2026, 3, 23, 20, 0, 0, 0, time.UTC)
@@ -757,20 +757,20 @@ func TestCollector_Collect(t *testing.T) {
757
assert.Equal(t, 1, runner.calls)
758
759
flat = coll.MetricStore().Read(metrix.ReadFlatten())
760
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "paused_retry_job", "nagios.job.execution_state": "paused"}, 1)
761
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "paused_retry_job", "nagios.job.execution_state": "retry"}, 0)
762
- assertMetricValue(t, flat, "nagios.perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "paused_retry_job", "nagios.perfdata.true.job.execution_state": "paused"}, 1)
763
- assertMetricValue(t, flat, "nagios.perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "paused_retry_job", "nagios.perfdata.true.job.execution_state": "retry"}, 0)
760
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "paused_retry_job", "job.execution_state": "paused"}, 1)
761
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "paused_retry_job", "job.execution_state": "retry"}, 0)
762
+ assertMetricValue(t, flat, "perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "paused_retry_job", "perfdata.true.job.execution_state": "paused"}, 1)
763
+ assertMetricValue(t, flat, "perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "paused_retry_job", "perfdata.true.job.execution_state": "retry"}, 0)
764
for _, state := range perfThresholdAlertStateNames {
765
- assertMetricValue(t, flat, "nagios.job.perfdata.threshold_state", metrix.Labels{
766
- "nagios_job": "paused_retry_job",
767
- perfdataValueLabelKey: "bytes_used",
768
- "nagios.job.perfdata.threshold_state": state,
765
+ assertMetricValue(t, flat, "job.perfdata.threshold_state", metrix.Labels{
766
+ "nagios_job": "paused_retry_job",
767
+ perfdataValueLabelKey: "bytes_used",
768
+ "job.perfdata.threshold_state": state,
769
}, 0)
770
}
771
772
raw := coll.MetricStore().Read()
773
- alertPoint, ok := raw.StateSet("nagios.job.perfdata.threshold_state", metrix.Labels{
773
+ alertPoint, ok := raw.StateSet("job.perfdata.threshold_state", metrix.Labels{
774
"nagios_job": "paused_retry_job",
775
perfdataValueLabelKey: "bytes_used",
776
})
@@ -808,10 +808,10 @@ func TestCollector_Collect(t *testing.T) {
808
assert.Equal(t, jobStateTimeout, coll.state.currentJobState())
809
810
flat := coll.MetricStore().Read(metrix.ReadFlatten())
811
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "timeout_job", "nagios.job.execution_state": "timeout"}, 1)
812
- assertMetricValue(t, flat, "nagios.job.execution_state", metrix.Labels{"nagios_job": "timeout_job", "nagios.job.execution_state": "retry"}, 1)
813
- assertMetricValue(t, flat, "nagios.perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "timeout_job", "nagios.perfdata.true.job.execution_state": "timeout"}, 1)
814
- assertMetricValue(t, flat, "nagios.perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "timeout_job", "nagios.perfdata.true.job.execution_state": "retry"}, 1)
811
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "timeout_job", "job.execution_state": "timeout"}, 1)
812
+ assertMetricValue(t, flat, "job.execution_state", metrix.Labels{"nagios_job": "timeout_job", "job.execution_state": "retry"}, 1)
813
+ assertMetricValue(t, flat, "perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "timeout_job", "perfdata.true.job.execution_state": "timeout"}, 1)
814
+ assertMetricValue(t, flat, "perfdata.true.job.execution_state", metrix.Labels{"nagios_job": "timeout_job", "perfdata.true.job.execution_state": "retry"}, 1)
815
816
*now = now.Add(11 * time.Second)
817
runCollectCycle(t, coll)
src/go/plugin/scripts.d/collector/nagios/v2_gate_test.go
+77
-33
@@ -79,7 +79,7 @@ func TestV2Gate_G2_PerfdataRouting(t *testing.T) {
79
store := metrix.NewCollectorStore()
80
cc := gateCycleController(t, store)
81
cc.BeginCycle()
82
- sm := store.Write().SnapshotMeter("nagios")
82
+ sm := store.Write().SnapshotMeter("")
83
labels := sm.LabelSet(
84
metrix.Label{Key: "nagios_job", Value: "gate_job"},
85
)
@@ -121,35 +121,35 @@ func TestV2Gate_G2_PerfdataRouting(t *testing.T) {
121
cc.CommitCycleSuccess()
122
123
reader := store.Read(metrix.ReadFlatten())
124
- assertMetricMeta(t, reader, "nagios.perfdata.check_gate.time_latency_value", "seconds", true)
125
- assertMetricMeta(t, reader, "nagios.perfdata.check_gate.bytes_throughput_value", "bytes", true)
126
- assertMetricMeta(t, reader, "nagios.perfdata.check_gate.bits_wire_rate_value", "bits", true)
127
- assertMetricMeta(t, reader, "nagios.perfdata.check_gate.percent_free_pct_value", "%", true)
128
- assertMetricMeta(t, reader, "nagios.perfdata.check_gate.counter_requests_value", "c", true)
129
- assertMetricMeta(t, reader, "nagios.perfdata.check_gate.generic_custom_value", "generic", true)
130
- assertMetricMeta(t, reader, "nagios.perfdata.check_gate.time_latency_threshold_state", "state", false)
131
- assertMetricMeta(t, reader, "nagios.job.perfdata.threshold_state", "state", false)
132
- assertMetricChartFamily(t, reader, "nagios.perfdata.check_gate.time_latency_value", "Perfdata/check_gate")
133
- assertMetricChartFamily(t, reader, "nagios.perfdata.check_gate.time_latency_threshold_state", "Perfdata/check_gate")
134
- assertMetricValue(t, reader, "nagios.perfdata.check_gate.time_latency_threshold_state", metrix.Labels{
124
+ assertMetricMeta(t, reader, "perfdata.check_gate.time_latency_value", "seconds", true)
125
+ assertMetricMeta(t, reader, "perfdata.check_gate.bytes_throughput_value", "bytes", true)
126
+ assertMetricMeta(t, reader, "perfdata.check_gate.bits_wire_rate_value", "bits", true)
127
+ assertMetricMeta(t, reader, "perfdata.check_gate.percent_free_pct_value", "%", true)
128
+ assertMetricMeta(t, reader, "perfdata.check_gate.counter_requests_value", "c", true)
129
+ assertMetricMeta(t, reader, "perfdata.check_gate.generic_custom_value", "generic", true)
130
+ assertMetricMeta(t, reader, "perfdata.check_gate.time_latency_threshold_state", "state", false)
131
+ assertMetricMeta(t, reader, "job.perfdata.threshold_state", "state", false)
132
+ assertMetricChartFamily(t, reader, "perfdata.check_gate.time_latency_value", "Perfdata/check_gate")
133
+ assertMetricChartFamily(t, reader, "perfdata.check_gate.time_latency_threshold_state", "Perfdata/check_gate")
134
+ assertMetricValue(t, reader, "perfdata.check_gate.time_latency_threshold_state", metrix.Labels{
135
"nagios_job": "gate_job",
136
- "nagios.perfdata.check_gate.time_latency_threshold_state": perfThresholdStateWarning,
136
+ "perfdata.check_gate.time_latency_threshold_state": perfThresholdStateWarning,
137
}, 1)
138
- assertMetricValue(t, reader, "nagios.job.perfdata.threshold_state", metrix.Labels{
139
- "nagios_job": "gate_job",
140
- perfdataValueLabelKey: "time_latency",
141
- "nagios.job.perfdata.threshold_state": perfThresholdStateWarning,
138
+ assertMetricValue(t, reader, "job.perfdata.threshold_state", metrix.Labels{
139
+ "nagios_job": "gate_job",
140
+ perfdataValueLabelKey: "time_latency",
141
+ "job.perfdata.threshold_state": perfThresholdStateWarning,
142
}, 1)
143
- assertMetricValue(t, reader, "nagios.job.perfdata.threshold_state", metrix.Labels{
144
- "nagios_job": "gate_job",
145
- perfdataValueLabelKey: "time_latency",
146
- "nagios.job.perfdata.threshold_state": perfThresholdStateRetry,
143
+ assertMetricValue(t, reader, "job.perfdata.threshold_state", metrix.Labels{
144
+ "nagios_job": "gate_job",
145
+ perfdataValueLabelKey: "time_latency",
146
+ "job.perfdata.threshold_state": perfThresholdStateRetry,
147
}, 0)
148
- assertSeriesKind(t, reader, "nagios.perfdata.check_gate.time_latency_value", metrix.Labels{
148
+ assertSeriesKind(t, reader, "perfdata.check_gate.time_latency_value", metrix.Labels{
149
"nagios_job": "gate_job",
150
metrix.MeasureSetFieldLabel: perfFieldValue,
151
}, metrix.MetricKindGauge)
152
- assertSeriesKind(t, reader, "nagios.perfdata.check_gate.counter_requests_value", metrix.Labels{
152
+ assertSeriesKind(t, reader, "perfdata.check_gate.counter_requests_value", metrix.Labels{
153
"nagios_job": "gate_job",
154
metrix.MeasureSetFieldLabel: perfFieldValue,
155
}, metrix.MetricKindCounter)
@@ -172,7 +172,7 @@ func TestV2Gate_G3_ChartLifecycleChurn(t *testing.T) {
172
emit := func(includeB bool) chartengine.Plan {
173
cc := gateCycleController(t, store)
174
cc.BeginCycle()
175
- sm := store.Write().SnapshotMeter("nagios")
175
+ sm := store.Write().SnapshotMeter("")
176
ls := sm.LabelSet(
177
metrix.Label{Key: "nagios_job", Value: "gate_job"},
178
)
@@ -211,7 +211,7 @@ func TestV2Gate_G3_ChartLifecycleChurn(t *testing.T) {
211
212
cc := gateCycleController(t, store)
213
cc.BeginCycle()
214
- sm := store.Write().SnapshotMeter("nagios")
214
+ sm := store.Write().SnapshotMeter("")
215
ls := sm.LabelSet(
216
metrix.Label{Key: "nagios_job", Value: "gate_job"},
217
)
@@ -238,12 +238,12 @@ func TestV2Gate_G3_ChartLifecycleChurn(t *testing.T) {
238
assert.NotZero(t, countActions[chartengine.CreateChartAction](plan1.Actions))
239
plan2 := emit(false)
240
assert.Zero(t, removeActionsCount(plan2.Actions))
241
- assertPlanHasUpdateForTarget(t, plan2, "nagios.perfdata.check_gate.bytes_a")
242
- assertPlanHasNoRemoveForTarget(t, plan2, "nagios.perfdata.check_gate.bytes_b")
241
+ assertPlanHasUpdateForTarget(t, plan2, "perfdata.check_gate.bytes_a")
242
+ assertPlanHasNoRemoveForTarget(t, plan2, "perfdata.check_gate.bytes_b")
243
244
cc := gateCycleController(t, store)
245
cc.BeginCycle()
246
- sm := store.Write().SnapshotMeter("nagios")
246
+ sm := store.Write().SnapshotMeter("")
247
ls := sm.LabelSet(
248
metrix.Label{Key: "nagios_job", Value: "gate_job"},
249
)
@@ -260,8 +260,8 @@ func TestV2Gate_G3_ChartLifecycleChurn(t *testing.T) {
260
261
plan3 := emit(false)
262
assert.Zero(t, removeActionsCount(plan3.Actions))
263
- assertPlanHasUpdateForTarget(t, plan3, "nagios.perfdata.check_gate.bytes_a")
264
- assertPlanHasNoRemoveForTarget(t, plan3, "nagios.perfdata.check_gate.bytes_b")
263
+ assertPlanHasUpdateForTarget(t, plan3, "perfdata.check_gate.bytes_a")
264
+ assertPlanHasNoRemoveForTarget(t, plan3, "perfdata.check_gate.bytes_b")
265
plan4 := emit(false)
266
assert.Zero(t, removeActionsCount(plan4.Actions))
267
})
@@ -318,7 +318,7 @@ func TestV2Gate_G5_ScalingPrecisionEquivalence(t *testing.T) {
318
store := metrix.NewCollectorStore()
319
cc := gateCycleController(t, store)
320
cc.BeginCycle()
321
- sm := store.Write().SnapshotMeter("nagios")
321
+ sm := store.Write().SnapshotMeter("")
322
for _, measureSet := range samples.values {
323
fields := perfMeasureSetValues(measureSet.value)
324
if measureSet.counter {
@@ -339,12 +339,56 @@ func TestV2Gate_G5_ScalingPrecisionEquivalence(t *testing.T) {
339
}
340
cc.CommitCycleSuccess()
341
flat := store.Read(metrix.ReadFlatten())
342
- assertMetricMeta(t, flat, "nagios."+candidateKey, tc.expectedUnit, true)
343
- assertMetricChartFamily(t, flat, "nagios."+candidateKey, "Perfdata/check_gate")
342
+ assertMetricMeta(t, flat, candidateKey, tc.expectedUnit, true)
343
+ assertMetricChartFamily(t, flat, candidateKey, "Perfdata/check_gate")
344
})
345
}
346
}
347
348
+// With an empty meter prefix and context_namespace: nagios, an autogen perfdata chart's context
349
+// is single-namespaced (nagios.perfdata.*) — never doubled (nagios.nagios.*) and never bare
350
+// (perfdata.*). The chart ID intentionally drops the redundant nagios. prefix; the collector
351
+// identity is already in the chart type (the job full name).
352
+func TestV2Gate_AutogenPerfdataContextSingleNamespaced(t *testing.T) {
353
+ engine, err := chartengine.New()
354
+ require.NoError(t, err)
355
+ require.NoError(t, engine.LoadYAML([]byte(New().ChartTemplateYAML()), 1))
356
+
357
+ store := metrix.NewCollectorStore()
358
+ cc := gateCycleController(t, store)
359
+ cc.BeginCycle()
360
+ sm := store.Write().SnapshotMeter("")
361
+ ls := sm.LabelSet(metrix.Label{Key: "nagios_job", Value: "check_mem"})
362
+ fields := defaultPerfMeasureSetValues()
363
+ fields[perfFieldValue] = 30000
364
+ sm.MeasureSetGauge(
365
+ "perfdata.check_memory.bytes_used",
366
+ metrix.WithMeasureSetFields(perfMeasureSetFieldSpecs()...),
367
+ metrix.WithChartFamily(perfdataFamily("check_memory")),
368
+ metrix.WithUnit("bytes"),
369
+ ).ObserveFields(fields, ls)
370
+ cc.CommitCycleSuccess()
371
+
372
+ plan, err := prepareCommittedPlan(engine, store.Read(metrix.ReadFlatten()))
373
+ require.NoError(t, err)
374
+
375
+ var found bool
376
+ for _, action := range plan.Actions {
377
+ create, ok := action.(chartengine.CreateChartAction)
378
+ if !ok || !strings.Contains(create.ChartID, "perfdata.check_memory") {
379
+ continue
380
+ }
381
+ found = true
382
+ assert.Equal(t, "nagios.perfdata.check_memory.bytes_used", create.Meta.Context,
383
+ "autogen perfdata context must be single-namespaced via context_namespace")
384
+ assert.NotContains(t, create.Meta.Context, "nagios.nagios.",
385
+ "autogen context must not double-prefix the namespace")
386
+ assert.Falsef(t, strings.HasPrefix(create.ChartID, "nagios."),
387
+ "autogen chart ID should drop the redundant nagios. prefix, got %q", create.ChartID)
388
+ }
389
+ require.True(t, found, "expected an autogen create-chart action for the perfdata measureset")
390
+}
391
+
392
func countActions[T any](actions []chartengine.EngineAction) int {
393
n := 0
394
for _, action := range actions {