Skip to content

Commit 6e6386e

Browse files
feat(telemetry): export ExtraConfig and CosmosExtra types (cosmos#26006)
2 parents 78056b4 + 479e219 commit 6e6386e

File tree

4 files changed

+84
-102
lines changed

4 files changed

+84
-102
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
7979

8080
### Improvements
8181

82+
* (telemetry) [#26006](https://github.com/cosmos/cosmos-sdk/pull/26006) Export `ExtensionOptions` type for programmatic otel.yaml generation.
8283
* [#25955](https://github.com/cosmos/cosmos-sdk/pull/25955) Use cosmos/btree directly instead of replacing it in go.mods
8384
* (types) [#25342](https://github.com/cosmos/cosmos-sdk/pull/25342) Undeprecated `EmitEvent` and `EmitEvents` on the `EventManager`. These functions will continue to be maintained.
8485
* (types) [#24668](https://github.com/cosmos/cosmos-sdk/pull/24668) Scope the global config to a particular binary so that multiple SDK binaries can be properly run on the same machine.

telemetry/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ logger_provider:
5656
endpoint: http://localhost:4317
5757

5858

59-
cosmos_extra:
59+
extensions:
6060
instruments:
6161
host: {} # enable optional host instrumentation with go.opentelemetry.io/contrib/instrumentation/host
6262
runtime: {} # enable optional runtime instrumentation with go.opentelemetry.io/contrib/instrumentation/runtime

telemetry/config.go

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ func InitializeOpenTelemetry(filePath string) error {
7171
if openTelemetrySDK != nil {
7272
return nil
7373
}
74-
var err error
7574

7675
var opts []otelconf.ConfigurationOption
7776

@@ -99,29 +98,28 @@ func InitializeOpenTelemetry(filePath string) error {
9998

10099
opts = append(opts, otelconf.WithOpenTelemetryConfiguration(*cfg))
101100

102-
// parse cosmos extra config
103-
var extraCfg extraConfig
104-
err = yaml.Unmarshal(bz, &extraCfg)
105-
if err == nil {
106-
if extraCfg.CosmosExtra != nil {
107-
extra := *extraCfg.CosmosExtra
108-
for name, cfg := range extra.Instruments {
109-
inst := registry.Get(name)
110-
if inst == nil {
111-
return fmt.Errorf("unknown instrument: %s", name)
112-
}
113-
fmt.Printf("Initializing %s instrumentation\n", name)
114-
if err := inst.Start(cfg); err != nil {
115-
return fmt.Errorf("failed to start %s instrumentation: %w", name, err)
116-
}
101+
// parse extensions config (features not yet supported by otelconf)
102+
var supplemental struct {
103+
Extensions *ExtensionOptions `yaml:"extensions"`
104+
}
105+
if err := yaml.Unmarshal(bz, &supplemental); err == nil && supplemental.Extensions != nil {
106+
extra := *supplemental.Extensions
107+
for name, cfg := range extra.Instruments {
108+
inst := registry.Get(name)
109+
if inst == nil {
110+
return fmt.Errorf("unknown instrument: %s", name)
117111
}
118-
119-
// TODO: this code should be removed once propagation is properly supported by otelconf.
120-
if len(extra.Propagators) > 0 {
121-
propagator := initPropagator(extra.Propagators)
122-
otel.SetTextMapPropagator(propagator)
112+
fmt.Printf("Initializing %s instrumentation\n", name)
113+
if err := inst.Start(cfg); err != nil {
114+
return fmt.Errorf("failed to start %s instrumentation: %w", name, err)
123115
}
124116
}
117+
118+
// TODO: this code should be removed once propagation is properly supported by otelconf.
119+
if len(extra.Propagators) > 0 {
120+
propagator := initPropagator(extra.Propagators)
121+
otel.SetTextMapPropagator(propagator)
122+
}
125123
}
126124

127125
otelSDK, err := otelconf.NewSDK(opts...)
@@ -175,19 +173,16 @@ func setNoop() {
175173
logglobal.SetLoggerProvider(lognoop.NewLoggerProvider())
176174
}
177175

178-
type extraConfig struct {
179-
CosmosExtra *cosmosExtra `json:"cosmos_extra" yaml:"cosmos_extra" mapstructure:"cosmos_extra"`
180-
}
181-
182-
// cosmosExtra provides extensions to the OpenTelemetry declarative configuration.
183-
// These options allow features not yet supported by otelconf, such as writing traces/metrics/logs to local
184-
// files, enabling additional host/runtime instrumentation, and configuring custom propagators.
176+
// ExtensionOptions provides configuration for OpenTelemetry features not yet
177+
// supported by [otelconf], such as writing traces/metrics/logs to local files,
178+
// enabling additional host/runtime instrumentation, and configuring custom
179+
// propagators.
185180
//
186-
// When present in otel.yaml under the `cosmos_extra` key, these fields
181+
// When present in otel.yaml under the `extensions` key, these fields
187182
// augment/override portions of the OpenTelemetry SDK initialization.
188183
//
189184
// For an example configuration, see the README in this package.
190-
type cosmosExtra struct {
185+
type ExtensionOptions struct {
191186
// TraceFile is an optional path to a file where spans should be exported
192187
// using the stdouttrace exporter. If empty, no file-based trace export is
193188
// configured.

telemetry/config_test.go

Lines changed: 57 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -7,72 +7,66 @@ import (
77
"go.yaml.in/yaml/v3"
88
)
99

10-
func TestCosmosExtraUnmarshal(t *testing.T) {
10+
func TestExtensionOptionsUnmarshal(t *testing.T) {
1111
tests := []struct {
1212
name string
1313
yaml string
14-
expected extraConfig
14+
expected *ExtensionOptions
1515
}{
1616
{
1717
name: "instruments with empty config",
1818
yaml: `
19-
cosmos_extra:
19+
extensions:
2020
instruments:
2121
host: {}
2222
runtime: {}
2323
`,
24-
expected: extraConfig{
25-
CosmosExtra: &cosmosExtra{
26-
Instruments: map[string]map[string]any{
27-
"host": {},
28-
"runtime": {},
29-
},
24+
expected: &ExtensionOptions{
25+
Instruments: map[string]map[string]any{
26+
"host": {},
27+
"runtime": {},
3028
},
3129
},
3230
},
3331
{
3432
name: "instruments with options",
3533
yaml: `
36-
cosmos_extra:
34+
extensions:
3735
instruments:
3836
host: {}
3937
diskio:
4038
disable_virtual_device_filter: true
4139
`,
42-
expected: extraConfig{
43-
CosmosExtra: &cosmosExtra{
44-
Instruments: map[string]map[string]any{
45-
"host": {},
46-
"diskio": {
47-
"disable_virtual_device_filter": true,
48-
},
40+
expected: &ExtensionOptions{
41+
Instruments: map[string]map[string]any{
42+
"host": {},
43+
"diskio": {
44+
"disable_virtual_device_filter": true,
4945
},
5046
},
5147
},
5248
},
5349
{
5450
name: "instruments with propagators",
5551
yaml: `
56-
cosmos_extra:
52+
extensions:
5753
instruments:
5854
host: {}
5955
propagators:
6056
- tracecontext
6157
- baggage
6258
`,
63-
expected: extraConfig{
64-
CosmosExtra: &cosmosExtra{
65-
Instruments: map[string]map[string]any{
66-
"host": {},
67-
},
68-
Propagators: []string{"tracecontext", "baggage"},
59+
expected: &ExtensionOptions{
60+
Instruments: map[string]map[string]any{
61+
"host": {},
6962
},
63+
Propagators: []string{"tracecontext", "baggage"},
7064
},
7165
},
7266
{
7367
name: "full config",
7468
yaml: `
75-
cosmos_extra:
69+
extensions:
7670
trace_file: /tmp/traces.json
7771
metrics_file: /tmp/metrics.json
7872
instruments:
@@ -83,50 +77,42 @@ cosmos_extra:
8377
propagators:
8478
- tracecontext
8579
`,
86-
expected: extraConfig{
87-
CosmosExtra: &cosmosExtra{
88-
TraceFile: "/tmp/traces.json",
89-
MetricsFile: "/tmp/metrics.json",
90-
Instruments: map[string]map[string]any{
91-
"host": {},
92-
"runtime": {},
93-
"diskio": {
94-
"disable_virtual_device_filter": true,
95-
},
80+
expected: &ExtensionOptions{
81+
TraceFile: "/tmp/traces.json",
82+
MetricsFile: "/tmp/metrics.json",
83+
Instruments: map[string]map[string]any{
84+
"host": {},
85+
"runtime": {},
86+
"diskio": {
87+
"disable_virtual_device_filter": true,
9688
},
97-
Propagators: []string{"tracecontext"},
9889
},
90+
Propagators: []string{"tracecontext"},
9991
},
10092
},
10193
{
102-
name: "empty cosmos_extra (null)",
94+
name: "empty extensions (null)",
10395
yaml: `
104-
cosmos_extra:
96+
extensions:
10597
`,
106-
expected: extraConfig{
107-
CosmosExtra: nil, // YAML with just "cosmos_extra:" and no value results in nil
108-
},
98+
expected: nil,
10999
},
110100
{
111-
name: "empty cosmos_extra (empty object)",
101+
name: "empty extensions (empty object)",
112102
yaml: `
113-
cosmos_extra: {}
103+
extensions: {}
114104
`,
115-
expected: extraConfig{
116-
CosmosExtra: &cosmosExtra{},
117-
},
105+
expected: &ExtensionOptions{},
118106
},
119107
{
120-
name: "no cosmos_extra",
108+
name: "no extensions",
121109
yaml: `
122110
some_other_key: value
123111
`,
124-
expected: extraConfig{
125-
CosmosExtra: nil,
126-
},
112+
expected: nil,
127113
},
128114
{
129-
name: "realistic otel.yaml with cosmos_extra",
115+
name: "realistic otel.yaml with extensions",
130116
yaml: `
131117
file_format: "1.0-rc.3"
132118
resource:
@@ -149,7 +135,7 @@ meter_provider:
149135
host: 0.0.0.0
150136
port: 9464
151137
152-
cosmos_extra:
138+
extensions:
153139
instruments:
154140
host: {}
155141
runtime: {}
@@ -158,42 +144,42 @@ cosmos_extra:
158144
propagators:
159145
- tracecontext
160146
`,
161-
expected: extraConfig{
162-
CosmosExtra: &cosmosExtra{
163-
Instruments: map[string]map[string]any{
164-
"host": {},
165-
"runtime": {},
166-
"diskio": {
167-
"disable_virtual_device_filter": true,
168-
},
147+
expected: &ExtensionOptions{
148+
Instruments: map[string]map[string]any{
149+
"host": {},
150+
"runtime": {},
151+
"diskio": {
152+
"disable_virtual_device_filter": true,
169153
},
170-
Propagators: []string{"tracecontext"},
171154
},
155+
Propagators: []string{"tracecontext"},
172156
},
173157
},
174158
}
175159

176160
for _, tc := range tests {
177161
t.Run(tc.name, func(t *testing.T) {
178-
var cfg extraConfig
162+
var cfg struct {
163+
Extensions *ExtensionOptions `yaml:"extensions"`
164+
}
179165
err := yaml.Unmarshal([]byte(tc.yaml), &cfg)
180166
require.NoError(t, err)
181167

182-
if tc.expected.CosmosExtra == nil {
183-
require.Nil(t, cfg.CosmosExtra)
168+
if tc.expected == nil {
169+
require.Nil(t, cfg.Extensions)
184170
return
185171
}
186172

187-
require.NotNil(t, cfg.CosmosExtra)
188-
require.Equal(t, tc.expected.CosmosExtra.TraceFile, cfg.CosmosExtra.TraceFile)
189-
require.Equal(t, tc.expected.CosmosExtra.MetricsFile, cfg.CosmosExtra.MetricsFile)
190-
require.Equal(t, tc.expected.CosmosExtra.Propagators, cfg.CosmosExtra.Propagators)
173+
require.NotNil(t, cfg.Extensions)
174+
require.Equal(t, tc.expected.TraceFile, cfg.Extensions.TraceFile)
175+
require.Equal(t, tc.expected.MetricsFile, cfg.Extensions.MetricsFile)
176+
require.Equal(t, tc.expected.Propagators, cfg.Extensions.Propagators)
191177

192-
require.Equal(t, len(tc.expected.CosmosExtra.Instruments), len(cfg.CosmosExtra.Instruments),
178+
require.Equal(t, len(tc.expected.Instruments), len(cfg.Extensions.Instruments),
193179
"instruments count mismatch")
194180

195-
for name, expectedOpts := range tc.expected.CosmosExtra.Instruments {
196-
actualOpts, ok := cfg.CosmosExtra.Instruments[name]
181+
for name, expectedOpts := range tc.expected.Instruments {
182+
actualOpts, ok := cfg.Extensions.Instruments[name]
197183
require.True(t, ok, "missing instrument: %s", name)
198184
require.Equal(t, len(expectedOpts), len(actualOpts),
199185
"options count mismatch for instrument %s", name)

0 commit comments

Comments
 (0)