Skip to content

Commit a6035e0

Browse files
committed
[exporter/debug] Add output_paths configuration option
Adds output_paths config field to debug exporter, allowing users to redirect output to stderr or file paths when use_internal_logger is false. - Extends Config struct with OutputPaths []string field - Updates createCustomLogger to honor configured paths (defaults to stdout) - Adds validation to prevent use with use_internal_logger=true - Adds validation to reject empty path values - Updates README with new configuration option - Adds test coverage for output_paths scenarios Fixes #10472
1 parent fbd5d3f commit a6035e0

File tree

7 files changed

+96
-3
lines changed

7 files changed

+96
-3
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. receiver/otlp)
7+
component: exporter/debug
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Add `output_paths` configuration option to allow redirecting output when `use_internal_logger` is false
11+
12+
# One or more tracking issues or pull requests related to the change
13+
issues: [10472]
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+
The `output_paths` option accepts an array of destinations (stdout, stderr, or file paths) and defaults to stdout.
20+
This option can only be used when `use_internal_logger` is set to false.
21+
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: [user]

exporter/debugexporter/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ The following settings are optional:
3838
Refer to [Zap docs](https://godoc.org/go.uber.org/zap/zapcore#NewSampler) for more details
3939
on how sampling parameters impact number of messages.
4040
- `use_internal_logger` (default = `true`): uses the collector's internal logger for output. See [below](#using-the-collectors-internal-logger) for description.
41+
- `output_paths` (default = `[stdout]` when `use_internal_logger` is `false`): list of destinations for the exporter's output when bypassing the collector logger. Accepts `stdout`, `stderr`, or filesystem paths supported by Zap.
4142
- `sending_queue` (disabled by default): see [Sending Queue](../exporterhelper/README.md#sending-queue) for the full set of available options.
4243

4344
Example configuration:
@@ -138,7 +139,7 @@ This comes with the following consequences:
138139

139140
When `use_internal_logger` is set to `false`, the exporter does not use the collector's internal logger.
140141
Changing the values in `service::telemetry::logs` has no effect on the exporter's output.
141-
The exporter's output is sent to `stdout`.
142+
The exporter's output is sent to `stdout` by default and can be redirected via `output_paths`.
142143

143144
[internal_telemetry]: https://opentelemetry.io/docs/collector/internal-telemetry/
144145
[internal_logs_config]: https://opentelemetry.io/docs/collector/internal-telemetry/#configure-internal-logs

exporter/debugexporter/config.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ type Config struct {
3434
// UseInternalLogger defines whether the exporter sends the output to the collector's internal logger.
3535
UseInternalLogger bool `mapstructure:"use_internal_logger"`
3636

37+
// OutputPaths holds the list of destinations for the exporter's output when UseInternalLogger is false.
38+
OutputPaths []string `mapstructure:"output_paths"`
39+
3740
QueueConfig configoptional.Optional[exporterhelper.QueueBatchConfig] `mapstructure:"sending_queue"`
3841

3942
// prevent unkeyed literal initialization
@@ -48,5 +51,16 @@ func (cfg *Config) Validate() error {
4851
return fmt.Errorf("verbosity level %q is not supported", cfg.Verbosity)
4952
}
5053

54+
if len(cfg.OutputPaths) > 0 {
55+
if cfg.UseInternalLogger {
56+
return fmt.Errorf("output_paths requires use_internal_logger to be false")
57+
}
58+
for _, path := range cfg.OutputPaths {
59+
if path == "" {
60+
return fmt.Errorf("output_paths cannot contain empty values")
61+
}
62+
}
63+
}
64+
5165
return nil
5266
}

exporter/debugexporter/config_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func TestUnmarshalConfig(t *testing.T) {
3737
Verbosity: configtelemetry.LevelDetailed,
3838
SamplingInitial: 10,
3939
SamplingThereafter: 50,
40+
OutputPaths: []string{"stderr"},
4041
QueueConfig: configoptional.Default(queueCfg),
4142
},
4243
},
@@ -81,6 +82,16 @@ func Test_UnmarshalMarshalled(t *testing.T) {
8182
Verbosity: configtelemetry.LevelDetailed,
8283
},
8384
},
85+
"OutputPathsSpecified": {
86+
inCfg: &Config{
87+
UseInternalLogger: false,
88+
OutputPaths: []string{"stderr"},
89+
},
90+
expectedConfig: &Config{
91+
UseInternalLogger: false,
92+
OutputPaths: []string{"stderr"},
93+
},
94+
},
8495
} {
8596
t.Run(name, func(t *testing.T) {
8697
conf := confmap.New()
@@ -125,6 +136,29 @@ func TestValidate(t *testing.T) {
125136
Verbosity: configtelemetry.LevelDetailed,
126137
},
127138
},
139+
{
140+
name: "output paths with internal logger",
141+
cfg: &Config{
142+
UseInternalLogger: true,
143+
OutputPaths: []string{"stderr"},
144+
},
145+
expectedErr: "output_paths requires use_internal_logger to be false",
146+
},
147+
{
148+
name: "output paths empty entry",
149+
cfg: &Config{
150+
UseInternalLogger: false,
151+
OutputPaths: []string{""},
152+
},
153+
expectedErr: "output_paths cannot contain empty values",
154+
},
155+
{
156+
name: "output paths valid",
157+
cfg: &Config{
158+
UseInternalLogger: false,
159+
OutputPaths: []string{"stderr"},
160+
},
161+
},
128162
}
129163

130164
for _, tt := range tests {

exporter/debugexporter/exporter_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,17 @@ func createTestCases() []testCase {
128128
return cfg
129129
}(),
130130
},
131+
{
132+
name: "custom output paths",
133+
config: func() *Config {
134+
cfg := createDefaultConfig().(*Config)
135+
cfg.QueueConfig = configoptional.Some(exporterhelper.NewDefaultQueueConfig())
136+
cfg.QueueConfig.Get().QueueSize = 10
137+
cfg.UseInternalLogger = false
138+
cfg.OutputPaths = []string{"stderr"}
139+
return cfg
140+
}(),
141+
},
131142
}
132143
}
133144

exporter/debugexporter/factory.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ func createCustomLogger(exporterConfig *Config) *zap.Logger {
126126
encoderConfig.LevelKey = ""
127127
// Do not prefix the output with current timestamp.
128128
encoderConfig.TimeKey = ""
129+
outputPaths := exporterConfig.OutputPaths
130+
if len(outputPaths) == 0 {
131+
outputPaths = []string{"stdout"}
132+
}
129133
zapConfig := zap.Config{
130134
Level: zap.NewAtomicLevelAt(zap.InfoLevel),
131135
DisableCaller: true,
@@ -135,8 +139,8 @@ func createCustomLogger(exporterConfig *Config) *zap.Logger {
135139
},
136140
Encoding: "console",
137141
EncoderConfig: encoderConfig,
138-
// Send exporter's output to stdout. This should be made configurable.
139-
OutputPaths: []string{"stdout"},
142+
// Honor optional output paths (stdout by default).
143+
OutputPaths: outputPaths,
140144
}
141145
return zap.Must(zapConfig.Build())
142146
}

exporter/debugexporter/testdata/config_verbosity.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ verbosity: detailed
22
sampling_initial: 10
33
sampling_thereafter: 50
44
use_internal_logger: false
5+
output_paths:
6+
- stderr

0 commit comments

Comments
 (0)