Skip to content

Commit 872b902

Browse files
committed
Introduce service.Settings.TelemetryFactory
The `service.Settings` type now has a `TelemetryFactory` field for injecting the `telemetry.Factory` to be used for creating a logger and logger provider, meter provider, and tracer provider. The `otelcol` package is hard-coded to inject an otelconftelemetry factory for now. In a followup we will make it possible to inject the telemetry through `otelcol.Factories`.
1 parent 2e9dda5 commit 872b902

File tree

14 files changed

+553
-598
lines changed

14 files changed

+553
-598
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: breaking
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
7+
component: service
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: The `service.Settings` type now requires a `telemetry.Factory` to be provided
11+
12+
# One or more tracking issues or pull requests related to the change
13+
issues: [4970]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# Optional: The change log or logs in which this entry should be included.
21+
# e.g. '[user]' or '[user, api]'
22+
# Include 'user' if the change is relevant to end users.
23+
# Include 'api' if there is a change to a library API.
24+
# Default: '[user]'
25+
change_logs: [api]

internal/e2e/status_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,12 @@ func Test_ComponentStatusReporting_SharedInstance(t *testing.T) {
7575
ExtensionsFactories: map[component.Type]extension.Factory{
7676
component.MustNewType("watcher"): newExtensionFactory(),
7777
},
78+
TelemetryFactory: otelconftelemetry.NewFactory(),
7879
}
7980
set.BuildInfo = component.BuildInfo{Version: "test version", Command: "otelcoltest"}
8081

8182
cfg := service.Config{
82-
Telemetry: otelconftelemetry.Config{
83+
Telemetry: &otelconftelemetry.Config{
8384
Logs: otelconftelemetry.LogsConfig{
8485
Level: zapcore.InfoLevel,
8586
Development: false,

otelcol/collector.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"go.opentelemetry.io/collector/confmap/xconfmap"
2626
"go.opentelemetry.io/collector/otelcol/internal/grpclog"
2727
"go.opentelemetry.io/collector/service"
28+
"go.opentelemetry.io/collector/service/telemetry/otelconftelemetry"
2829
)
2930

3031
// State defines Collector's state.
@@ -216,6 +217,10 @@ func (col *Collector) setupConfigurationComponents(ctx context.Context) error {
216217
},
217218
AsyncErrorChannel: col.asyncErrorChannel,
218219
LoggingOptions: col.set.LoggingOptions,
220+
221+
// TODO: inject the telemetry factory through factories.
222+
// See https://github.com/open-telemetry/opentelemetry-collector/issues/4970
223+
TelemetryFactory: otelconftelemetry.NewFactory(),
219224
}, cfg.Service)
220225
if err != nil {
221226
return err

otelcol/collector_windows.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919

2020
"go.opentelemetry.io/collector/featuregate"
2121
"go.opentelemetry.io/collector/service"
22+
"go.opentelemetry.io/collector/service/telemetry/otelconftelemetry"
2223
)
2324

2425
type windowsService struct {
@@ -214,7 +215,7 @@ func (w windowsEventLogCore) Sync() error {
214215
func withWindowsCore(elog *eventlog.Log, serviceConfig **service.Config) func(zapcore.Core) zapcore.Core {
215216
return func(core zapcore.Core) zapcore.Core {
216217
if serviceConfig != nil && *serviceConfig != nil {
217-
for _, output := range (*serviceConfig).Telemetry.Logs.OutputPaths {
218+
for _, output := range (*serviceConfig).Telemetry.(*otelconftelemetry.Config).Logs.OutputPaths {
218219
if output != "stdout" && output != "stderr" {
219220
// A log file was specified in the configuration, so we should not use the Windows Event Log
220221
return core

otelcol/config_test.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ func TestConfigValidate(t *testing.T) {
5050
expected: nil,
5151
},
5252
{
53-
name: "custom-service-telemetrySettings-encoding",
53+
name: "valid-telemetry-config",
5454
cfgFn: func() *Config {
5555
cfg := generateConfig()
56-
cfg.Service.Telemetry.Logs.Encoding = "json"
56+
cfg.Service.Telemetry = fakeTelemetryConfig{}
5757
return cfg
5858
},
5959
expected: nil,
@@ -89,6 +89,15 @@ func TestConfigValidate(t *testing.T) {
8989
},
9090
expected: errMissingReceivers,
9191
},
92+
{
93+
name: "invalid-telemetry-config",
94+
cfgFn: func() *Config {
95+
cfg := generateConfig()
96+
cfg.Service.Telemetry = fakeTelemetryConfig{Invalid: true}
97+
return cfg
98+
},
99+
expected: errors.New("service::telemetry: invalid config"),
100+
},
92101
{
93102
name: "invalid-extension-reference",
94103
cfgFn: func() *Config {
@@ -330,3 +339,14 @@ func generateConfig() *Config {
330339
func newPtr[T int | string](str T) *T {
331340
return &str
332341
}
342+
343+
type fakeTelemetryConfig struct {
344+
Invalid bool `mapstructure:"invalid"`
345+
}
346+
347+
func (cfg fakeTelemetryConfig) Validate() error {
348+
if cfg.Invalid {
349+
return errors.New("invalid config")
350+
}
351+
return nil
352+
}

otelcol/unmarshaler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func unmarshal(v *confmap.Conf, factories Factories) (*configSettings, error) {
3030
// TODO: inject the telemetry factory through factories, once available.
3131
// See https://github.com/open-telemetry/opentelemetry-collector/issues/4970
3232
telFactory := otelconftelemetry.NewFactory()
33-
defaultTelConfig := *telFactory.CreateDefaultConfig().(*otelconftelemetry.Config)
33+
defaultTelConfig := telFactory.CreateDefaultConfig().(*otelconftelemetry.Config)
3434

3535
// Unmarshal top level sections and validate.
3636
cfg := &configSettings{

otelcol/unmarshaler_test.go

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func TestUnmarshalEmptyAllSections(t *testing.T) {
5656
OutputPaths: zapProdCfg.OutputPaths,
5757
ErrorOutputPaths: zapProdCfg.ErrorOutputPaths,
5858
InitialFields: zapProdCfg.InitialFields,
59-
}, cfg.Service.Telemetry.Logs)
59+
}, cfg.Service.Telemetry.(*otelconftelemetry.Config).Logs)
6060
}
6161

6262
func TestUnmarshalUnknownTopLevel(t *testing.T) {
@@ -149,26 +149,13 @@ func TestServiceUnmarshalError(t *testing.T) {
149149
expectError string
150150
}{
151151
{
152-
name: "invalid-logs-level",
152+
name: "invalid-telemetry-unknown-key",
153153
conf: confmap.NewFromStringMap(map[string]any{
154154
"telemetry": map[string]any{
155-
"logs": map[string]any{
156-
"level": "UNKNOWN",
157-
},
158-
},
159-
}),
160-
expectError: "decoding failed due to the following error(s):\n\n'telemetry.logs' decoding failed due to the following error(s):\n\n'level' unrecognized level: \"UNKNOWN\"",
161-
},
162-
{
163-
name: "invalid-metrics-level",
164-
conf: confmap.NewFromStringMap(map[string]any{
165-
"telemetry": map[string]any{
166-
"metrics": map[string]any{
167-
"level": "unknown",
168-
},
155+
"unknown": "key",
169156
},
170157
}),
171-
expectError: "decoding failed due to the following error(s):\n\n'telemetry.metrics' decoding failed due to the following error(s):\n\n'level' unknown metrics level \"unknown\"",
158+
expectError: "decoding failed due to the following error(s):\n\n'telemetry' has invalid keys: unknown",
172159
},
173160
{
174161
name: "invalid-service-extensions-section",
@@ -201,7 +188,9 @@ func TestServiceUnmarshalError(t *testing.T) {
201188

202189
for _, tt := range testCases {
203190
t.Run(tt.name, func(t *testing.T) {
204-
err := tt.conf.Unmarshal(&service.Config{})
191+
err := tt.conf.Unmarshal(&service.Config{
192+
Telemetry: fakeTelemetryConfig{},
193+
})
205194
require.ErrorContains(t, err, tt.expectError)
206195
})
207196
}

service/config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
package service // import "go.opentelemetry.io/collector/service"
55

66
import (
7+
"go.opentelemetry.io/collector/component"
78
"go.opentelemetry.io/collector/service/extensions"
89
"go.opentelemetry.io/collector/service/pipelines"
9-
"go.opentelemetry.io/collector/service/telemetry/otelconftelemetry"
1010
)
1111

1212
// Config defines the configurable components of the Service.
1313
type Config struct {
1414
// Telemetry is the configuration for collector's own telemetry.
15-
Telemetry otelconftelemetry.Config `mapstructure:"telemetry"`
15+
Telemetry component.Config `mapstructure:"telemetry"`
1616

1717
// Extensions are the ordered list of extensions configured for the service.
1818
Extensions extensions.Config `mapstructure:"extensions,omitempty"`

service/config_test.go

Lines changed: 18 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,16 @@ package service
66
import (
77
"errors"
88
"testing"
9-
"time"
109

1110
"github.com/stretchr/testify/assert"
1211
"github.com/stretchr/testify/require"
13-
config "go.opentelemetry.io/contrib/otelconf/v0.3.0"
14-
"go.uber.org/zap/zapcore"
1512

1613
"go.opentelemetry.io/collector/component"
17-
"go.opentelemetry.io/collector/config/configtelemetry"
1814
"go.opentelemetry.io/collector/confmap"
1915
"go.opentelemetry.io/collector/confmap/xconfmap"
2016
"go.opentelemetry.io/collector/pipeline"
2117
"go.opentelemetry.io/collector/service/extensions"
2218
"go.opentelemetry.io/collector/service/pipelines"
23-
"go.opentelemetry.io/collector/service/telemetry/otelconftelemetry"
2419
)
2520

2621
func TestConfigValidate(t *testing.T) {
@@ -35,10 +30,10 @@ func TestConfigValidate(t *testing.T) {
3530
expected: nil,
3631
},
3732
{
38-
name: "custom-service-telemetrySettings-encoding",
33+
name: "valid-telemetry-config",
3934
cfgFn: func() *Config {
4035
cfg := generateConfig()
41-
cfg.Telemetry.Logs.Encoding = "json"
36+
cfg.Telemetry = fakeTelemetryConfig{Invalid: false}
4237
return cfg
4338
},
4439
expected: nil,
@@ -54,14 +49,13 @@ func TestConfigValidate(t *testing.T) {
5449
expected: errors.New(`references processor "nop" multiple times`),
5550
},
5651
{
57-
name: "invalid-telemetry-metric-config",
52+
name: "invalid-telemetry-config",
5853
cfgFn: func() *Config {
5954
cfg := generateConfig()
60-
cfg.Telemetry.Metrics.Level = configtelemetry.LevelBasic
61-
cfg.Telemetry.Metrics.Readers = nil
55+
cfg.Telemetry = fakeTelemetryConfig{Invalid: true}
6256
return cfg
6357
},
64-
expected: errors.New("collector telemetry metrics reader should exist when metric level is not none"),
58+
expected: errors.New("telemetry: invalid config"),
6559
},
6660
}
6761

@@ -79,80 +73,19 @@ func TestConfigValidate(t *testing.T) {
7973
}
8074

8175
func TestConfmapMarshalConfig(t *testing.T) {
82-
telFactory := otelconftelemetry.NewFactory()
83-
defaultTelConfig := *telFactory.CreateDefaultConfig().(*otelconftelemetry.Config)
8476
conf := confmap.New()
8577

8678
require.NoError(t, conf.Marshal(Config{
87-
Telemetry: defaultTelConfig,
79+
Telemetry: fakeTelemetryConfig{},
8880
}))
8981
assert.Equal(t, map[string]any{
9082
"pipelines": map[string]any(nil),
91-
"telemetry": map[string]any{
92-
"logs": map[string]any{
93-
"encoding": "console",
94-
"level": "info",
95-
"error_output_paths": []any{"stderr"},
96-
"output_paths": []any{"stderr"},
97-
"sampling": map[string]any{
98-
"enabled": true,
99-
"initial": 10,
100-
"thereafter": 100,
101-
"tick": 10 * time.Second,
102-
},
103-
},
104-
"metrics": map[string]any{
105-
"level": "Normal",
106-
"readers": []any{
107-
map[string]any{
108-
"pull": map[string]any{
109-
"exporter": map[string]any{
110-
"prometheus": map[string]any{
111-
"host": "localhost",
112-
"port": 8888,
113-
"with_resource_constant_labels": map[string]any{
114-
"included": []any{},
115-
},
116-
"without_scope_info": true,
117-
"without_type_suffix": true,
118-
"without_units": true,
119-
},
120-
},
121-
},
122-
},
123-
},
124-
},
125-
},
83+
"telemetry": map[string]any{"invalid": false},
12684
}, conf.ToStringMap())
12785
}
12886

12987
func generateConfig() *Config {
13088
return &Config{
131-
Telemetry: otelconftelemetry.Config{
132-
Logs: otelconftelemetry.LogsConfig{
133-
Level: zapcore.DebugLevel,
134-
Development: true,
135-
Encoding: "console",
136-
DisableCaller: true,
137-
DisableStacktrace: true,
138-
OutputPaths: []string{"stderr", "./output-logs"},
139-
ErrorOutputPaths: []string{"stderr", "./error-output-logs"},
140-
InitialFields: map[string]any{"fieldKey": "filed-value"},
141-
},
142-
Metrics: otelconftelemetry.MetricsConfig{
143-
Level: configtelemetry.LevelNormal,
144-
MeterProvider: config.MeterProvider{
145-
Readers: []config.MetricReader{
146-
{
147-
Pull: &config.PullMetricReader{Exporter: config.PullMetricExporter{Prometheus: &config.Prometheus{
148-
Host: newPtr("localhost"),
149-
Port: newPtr(8080),
150-
}}},
151-
},
152-
},
153-
},
154-
},
155-
},
15689
Extensions: extensions.Config{component.MustNewID("nop")},
15790
Pipelines: pipelines.Config{
15891
pipeline.NewID(pipeline.SignalTraces): {
@@ -163,3 +96,14 @@ func generateConfig() *Config {
16396
},
16497
}
16598
}
99+
100+
type fakeTelemetryConfig struct {
101+
Invalid bool `mapstructure:"invalid"`
102+
}
103+
104+
func (cfg fakeTelemetryConfig) Validate() error {
105+
if cfg.Invalid {
106+
return errors.New("invalid config")
107+
}
108+
return nil
109+
}

service/go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ require (
5151
go.opentelemetry.io/contrib/propagators/b3 v1.36.0
5252
go.opentelemetry.io/otel v1.38.0
5353
go.opentelemetry.io/otel/log v0.14.0
54+
go.opentelemetry.io/otel/log/logtest v0.14.0
5455
go.opentelemetry.io/otel/metric v1.38.0
5556
go.opentelemetry.io/otel/sdk v1.38.0
5657
go.opentelemetry.io/otel/sdk/metric v1.38.0
@@ -77,6 +78,7 @@ require (
7778
github.com/gobwas/glob v0.2.3 // indirect
7879
github.com/gogo/protobuf v1.3.2 // indirect
7980
github.com/golang/snappy v1.0.0 // indirect
81+
github.com/google/go-cmp v0.7.0 // indirect
8082
github.com/google/go-tpm v0.9.5 // indirect
8183
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect
8284
github.com/hashicorp/go-version v1.7.0 // indirect

0 commit comments

Comments
 (0)