feat(go/jobruntime): add config_source field to runtime job logs (#22127)
Ilya Mashchenko committed
Apr 3, 2026 at 13:13 UTC
b5304aa73f4c5c9d98e78f7f26bc3a206e6747a3
6 files changed
+91
-8
src/go/plugin/agent/jobmgr/job_factory.go
+11
@@ -21,6 +21,15 @@ import (
21
"github.com/netdata/netdata/go/plugins/plugin/framework/vnodes"
22
)
23
24
+func jobLogSource(cfg confgroup.Config) string {
25
+ sourceType := cfg.SourceType()
26
+ provider := cfg.Provider()
27
+ if sourceType != "" && sourceType == provider {
28
+ return sourceType
29
+ }
30
+ return fmt.Sprintf("%s/%s", sourceType, provider)
31
+}
32
+
33
// jobFactory builds runtime jobs from configs without mutating manager-owned runtime maps.
34
type jobFactory struct {
35
logger *logger.Logger
@@ -125,6 +134,7 @@ func (f *jobFactory) createV2(cfg confgroup.Config, creator collectorapi.Creator
134
Name: cfg.Name(),
135
ModuleName: cfg.Module(),
136
FullName: cfg.FullName(),
137
+ Source: jobLogSource(cfg),
138
UpdateEvery: cfg.UpdateEvery(),
139
AutoDetectEvery: cfg.AutoDetectionRetry(),
140
IsStock: cfg.SourceType() == "stock",
@@ -172,6 +182,7 @@ func (f *jobFactory) createV1(cfg confgroup.Config, creator collectorapi.Creator
182
Name: cfg.Name(),
183
ModuleName: cfg.Module(),
184
FullName: cfg.FullName(),
185
+ Source: jobLogSource(cfg),
186
UpdateEvery: cfg.UpdateEvery(),
187
AutoDetectEvery: cfg.AutoDetectionRetry(),
188
Priority: cfg.Priority(),
src/go/plugin/agent/jobmgr/job_factory_test.go
new
+39
@@ -0,0 +1,39 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package jobmgr
4
+
5
+import (
6
+ "testing"
7
+
8
+ "github.com/netdata/netdata/go/plugins/plugin/framework/confgroup"
9
+ "github.com/stretchr/testify/assert"
10
+)
11
+
12
+func TestJobLogSource(t *testing.T) {
13
+ tests := map[string]struct {
14
+ sourceType string
15
+ provider string
16
+ want string
17
+ }{
18
+ "different source type and provider": {
19
+ sourceType: confgroup.TypeDiscovered,
20
+ provider: "file watcher",
21
+ want: "discovered/file watcher",
22
+ },
23
+ "same source type and provider": {
24
+ sourceType: confgroup.TypeDyncfg,
25
+ provider: confgroup.TypeDyncfg,
26
+ want: confgroup.TypeDyncfg,
27
+ },
28
+ }
29
+
30
+ for name, tc := range tests {
31
+ t.Run(name, func(t *testing.T) {
32
+ cfg := confgroup.Config{}
33
+ cfg.SetSourceType(tc.sourceType)
34
+ cfg.SetProvider(tc.provider)
35
+
36
+ assert.Equal(t, tc.want, jobLogSource(cfg))
37
+ })
38
+ }
39
+}
src/go/plugin/framework/jobruntime/job_logger.go
new
+13
@@ -0,0 +1,13 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package jobruntime
4
+
5
+import "log/slog"
6
+
7
+func jobLoggerAttrs(collector, job, source string) []any {
8
+ return []any{
9
+ slog.String("collector", collector),
10
+ slog.String("job", job),
11
+ slog.String("config_source", source),
12
+ }
13
+}
src/go/plugin/framework/jobruntime/job_logger_test.go
new
+24
@@ -0,0 +1,24 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package jobruntime
4
+
5
+import (
6
+ "bytes"
7
+ "testing"
8
+
9
+ "github.com/netdata/netdata/go/plugins/logger"
10
+ "github.com/stretchr/testify/assert"
11
+)
12
+
13
+func TestJobLoggerAttrs(t *testing.T) {
14
+ var buf bytes.Buffer
15
+
16
+ logger.NewWithWriter(&buf).
17
+ With(jobLoggerAttrs("module", "job", "stock/file reader")...).
18
+ Info("captured")
19
+
20
+ out := buf.String()
21
+ assert.Contains(t, out, "collector=module")
22
+ assert.Contains(t, out, "job=job")
23
+ assert.Contains(t, out, "config_source=\"stock/file reader\"")
24
+}
src/go/plugin/framework/jobruntime/job_v1.go
+2
-4
@@ -60,6 +60,7 @@ type JobConfig struct {
60
Name string
61
ModuleName string
62
FullName string
63
+ Source string
64
Module collectorapi.CollectorV1
65
Labels map[string]string
66
Out io.Writer
@@ -107,10 +108,7 @@ func NewJob(cfg JobConfig) *Job {
108
auditAnalyzer: cfg.AuditAnalyzer,
109
}
110
110
- log := logger.New().With(
111
- slog.String("collector", j.ModuleName()),
112
- slog.String("job", j.Name()),
113
- )
111
+ log := logger.New().With(jobLoggerAttrs(j.ModuleName(), j.Name(), cfg.Source)...)
112
113
j.Logger = log
114
if j.module != nil {
src/go/plugin/framework/jobruntime/job_v2.go
+2
-4
@@ -29,6 +29,7 @@ type JobV2Config struct {
29
Name string
30
ModuleName string
31
FullName string
32
+ Source string
33
Module collectorapi.CollectorV2
34
Labels map[string]string
35
Out io.Writer
@@ -71,10 +72,7 @@ func NewJobV2(cfg JobV2Config) *JobV2 {
72
j.out = io.Discard
73
}
74
74
- log := logger.New().With(
75
- slog.String("collector", j.ModuleName()),
76
- slog.String("job", j.Name()),
77
- )
75
+ log := logger.New().With(jobLoggerAttrs(j.ModuleName(), j.Name(), cfg.Source)...)
76
j.Logger = log
77
if j.module != nil {
78
j.module.GetBase().Logger = log