Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
d1b8a24
add ability to set output_paths
ishaish103 Nov 15, 2025
fbabe6d
Update exporter/debugexporter/README.md
ishaish103 Nov 17, 2025
374c202
fix pr comments
ishaish103 Nov 17, 2025
1e9b18b
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Nov 17, 2025
d8feeba
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Nov 18, 2025
5a3232b
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Nov 19, 2025
b4a6b0e
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Nov 22, 2025
c08384d
add tests
ishaish103 Nov 25, 2025
30c8ec3
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
ishaish103 Nov 25, 2025
4b136fd
Merge branch '10472-debug-exporter-output-paths-ishai' of github.com:…
ishaish103 Nov 25, 2025
8bb3be0
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Nov 25, 2025
d725b74
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Nov 30, 2025
c3ee29e
Address PR review comments: add validation and remove redundant fallback
ishaish103 Dec 3, 2025
fc1885f
Resolve merge conflicts with upstream/main
ishaish103 Dec 3, 2025
15349f4
Fix formatting and regenerate code
ishaish103 Dec 3, 2025
071b0e3
Add Makefile to local module and update generated files
ishaish103 Dec 3, 2025
22f3245
format
ishaish103 Dec 3, 2025
3908483
Fix linter errors
ishaish103 Dec 3, 2025
58b0cad
Fix Windows file handle cleanup in tests
ishaish103 Dec 3, 2025
a88eacb
Fix remaining linter error: use require for error assertion
ishaish103 Dec 3, 2025
a2ee4d0
Exclude local module from test runs
ishaish103 Dec 3, 2025
890e9ba
trigger ci
ishaish103 Dec 3, 2025
e2d1942
make sure to delete file
ishaish103 Dec 3, 2025
a48ff56
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Dec 5, 2025
1c1353a
remove makefile commit
ishaish103 Dec 5, 2025
709a284
Merge branch '10472-debug-exporter-output-paths-ishai' of github.com:…
ishaish103 Dec 5, 2025
b8433b6
add default
ishaish103 Dec 5, 2025
a288646
remove validation
ishaish103 Dec 6, 2025
743e1db
remove validation
ishaish103 Dec 6, 2025
72905b9
fix test
ishaish103 Dec 8, 2025
5b31428
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Dec 9, 2025
435c097
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Dec 10, 2025
be1255f
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Dec 12, 2025
2e01494
improve lock to avoid failing tests
ishaish103 Dec 14, 2025
5038a92
Merge branch '10472-debug-exporter-output-paths-ishai' of github.com:…
ishaish103 Dec 14, 2025
1725f7e
fix cleanup
ishaish103 Dec 14, 2025
83fe581
handle windows cleanup
ishaish103 Dec 14, 2025
25e0e95
windows cleanup fix
ishaish103 Dec 14, 2025
04bdc17
fix lint
ishaish103 Dec 14, 2025
9627bb3
fix cleanup
ishaish103 Dec 14, 2025
b7e964a
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Jan 4, 2026
43dccf8
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Jan 6, 2026
654bee5
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Jan 6, 2026
23ba692
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Jan 6, 2026
3f8587e
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Jan 8, 2026
d0523dd
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Jan 10, 2026
997be1c
Refactor config validation and update error messages for output_paths…
ishaish103 Jan 10, 2026
e59546d
Merge branch '10472-debug-exporter-output-paths-ishai' of github.com:…
ishaish103 Jan 10, 2026
69c5cdf
trigger ci
ishaish103 Jan 10, 2026
5ffb8fa
make gogenerate
ishaish103 Jan 10, 2026
760793c
trigger ci
ishaish103 Jan 10, 2026
6397ad4
format
ishaish103 Jan 10, 2026
8548627
trigger ci
ishaish103 Jan 10, 2026
2cfb4e2
Merge branch 'main' into 10472-debug-exporter-output-paths-ishai
ishaish103 Jan 13, 2026
9c4be19
fix: address PR review comments
ishaish103 Jan 29, 2026
5f3cb9e
Merge upstream/main and resolve conflict
ishaish103 Jan 29, 2026
b1b21e7
fix: address lint and Windows test failures
ishaish103 Jan 29, 2026
349081a
fix: revert unrelated QueueConfig change
ishaish103 Jan 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .chloggen/debug-exporter-output-paths.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
component: exporter/debug

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Add `output_paths` configuration option to control output destination when `use_internal_logger` is false

# One or more tracking issues or pull requests related to the change
issues: [10472]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext: |
When `use_internal_logger` is set to `false`, the debug exporter now supports configuring the output destination via the `output_paths` option.
This allows users to send debug exporter output to `stdout`, `stderr`, or a file path.
The default value is `["stdout"]` to maintain backward compatibility.

# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: []

14 changes: 13 additions & 1 deletion exporter/debugexporter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ The following settings are optional:
Refer to [Zap docs](https://godoc.org/go.uber.org/zap/zapcore#NewSampler) for more details
on how sampling parameters impact number of messages.
- `use_internal_logger` (default = `true`): uses the collector's internal logger for output. See [below](#using-the-collectors-internal-logger) for description.
- `output_paths` (default = `["stdout"]`): a list of file paths to write logging output to. This option is only used when `use_internal_logger` is `false`. Special strings "stdout" and "stderr" are interpreted as os.Stdout and os.Stderr respectively. All other values are treated as file paths.
- `sending_queue` (disabled by default): see [Sending Queue](../exporterhelper/README.md#sending-queue) for the full set of available options.

Example configuration:
Expand All @@ -50,6 +51,16 @@ exporters:
sampling_thereafter: 200
```

Example configuration with custom output path:

```yaml
exporters:
debug:
use_internal_logger: false
output_paths:
- stderr
```

## Verbosity levels

The following subsections describe the output from the exporter depending on the configured verbosity level - `basic`, `normal` and `detailed`.
Expand Down Expand Up @@ -138,7 +149,8 @@ This comes with the following consequences:

When `use_internal_logger` is set to `false`, the exporter does not use the collector's internal logger.
Changing the values in `service::telemetry::logs` has no effect on the exporter's output.
The exporter's output is sent to `stdout`.
The exporter's output is sent to the paths specified in `output_paths` (default: `["stdout"]`).
You can configure `output_paths` to send output to `stderr`, a file, or multiple destinations.

[internal_telemetry]: https://opentelemetry.io/docs/collector/internal-telemetry/
[internal_logs_config]: https://opentelemetry.io/docs/collector/internal-telemetry/#configure-internal-logs
Expand Down
12 changes: 12 additions & 0 deletions exporter/debugexporter/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@
// UseInternalLogger defines whether the exporter sends the output to the collector's internal logger.
UseInternalLogger bool `mapstructure:"use_internal_logger"`

// OutputPaths is a list of file paths to write logging output to.
// This option is only used when use_internal_logger is false.
// Special strings "stdout" and "stderr" are interpreted as os.Stdout and os.Stderr respectively.
// All other values are treated as file paths.
// (default = ["stdout"])
OutputPaths []string `mapstructure:"output_paths"`

QueueConfig exporterhelper.QueueBatchConfig `mapstructure:"sending_queue"`

// prevent unkeyed literal initialization
Expand All @@ -47,5 +54,10 @@
return fmt.Errorf("verbosity level %q is not supported", cfg.Verbosity)
}

// If use_internal_logger is false, output_paths must be specified and non-empty
if !cfg.UseInternalLogger && len(cfg.OutputPaths) == 0 {
return fmt.Errorf("output_paths must be specified and non-empty when use_internal_logger is false")

Check failure on line 59 in exporter/debugexporter/config.go

View workflow job for this annotation

GitHub Actions / CodeQL-Build

error-format: fmt.Errorf can be replaced with errors.New (perfsprint)

Check failure on line 59 in exporter/debugexporter/config.go

View workflow job for this annotation

GitHub Actions / lint

error-format: fmt.Errorf can be replaced with errors.New (perfsprint)
}

return nil
}
64 changes: 59 additions & 5 deletions exporter/debugexporter/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,26 @@
Verbosity: configtelemetry.LevelDetailed,
SamplingInitial: 10,
SamplingThereafter: 50,
UseInternalLogger: false,
OutputPaths: []string{"stdout"},
QueueConfig: queueCfg,
},
},
{
filename: "config_output_paths.yaml",
cfg: &Config{
Verbosity: configtelemetry.LevelBasic,
SamplingInitial: 2,
SamplingThereafter: 1,
UseInternalLogger: false,
OutputPaths: []string{"stderr"},
QueueConfig: queueCfg,
},
},
{
filename: "config_output_paths_empty.yaml",
expectedErr: "output_paths must be specified and non-empty when use_internal_logger is false",
},
{
filename: "config_verbosity_typo.yaml",
expectedErr: "'' has invalid keys: verBosity",
Expand All @@ -53,10 +70,24 @@
factory := NewFactory()
cfg := factory.CreateDefaultConfig()
err = cm.Unmarshal(&cfg)
if tt.expectedErr != "" {
assert.ErrorContains(t, err, tt.expectedErr)
} else {
if err != nil {
if tt.expectedErr != "" {
assert.ErrorContains(t, err, tt.expectedErr)

Check failure on line 75 in exporter/debugexporter/config_test.go

View workflow job for this annotation

GitHub Actions / CodeQL-Build

require-error: for error assertions use require (testifylint)

Check failure on line 75 in exporter/debugexporter/config_test.go

View workflow job for this annotation

GitHub Actions / lint

require-error: for error assertions use require (testifylint)
} else {
require.NoError(t, err)
}
return
}
// Validate the config (validation errors are separate from unmarshal errors)
if cfgCasted, ok := cfg.(*Config); ok {
err = cfgCasted.Validate()
if tt.expectedErr != "" {
assert.ErrorContains(t, err, tt.expectedErr)
return
}
require.NoError(t, err)
}
if tt.expectedErr == "" {
assert.Equal(t, tt.cfg, cfg)
}
})
Expand Down Expand Up @@ -122,7 +153,30 @@
{
name: "verbosity detailed",
cfg: &Config{
Verbosity: configtelemetry.LevelDetailed,
Verbosity: configtelemetry.LevelDetailed,
UseInternalLogger: true, // Default behavior
},
},
{
name: "empty output_paths when use_internal_logger is false",
cfg: &Config{
UseInternalLogger: false,
OutputPaths: []string{},
},
expectedErr: "output_paths must be specified and non-empty when use_internal_logger is false",
},
{
name: "valid output_paths when use_internal_logger is false",
cfg: &Config{
UseInternalLogger: false,
OutputPaths: []string{"stdout"},
},
},
{
name: "empty output_paths when use_internal_logger is true (allowed)",
cfg: &Config{
UseInternalLogger: true,
OutputPaths: []string{},
},
},
}
Expand All @@ -131,7 +185,7 @@
t.Run(tt.name, func(t *testing.T) {
err := tt.cfg.Validate()
if tt.expectedErr != "" {
assert.EqualError(t, err, tt.expectedErr)
assert.ErrorContains(t, err, tt.expectedErr)
} else {
assert.NoError(t, err)
}
Expand Down
10 changes: 10 additions & 0 deletions exporter/debugexporter/exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,16 @@ func createTestCases() []testCase {
return cfg
}(),
},
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test case for when user sets output_paths but does not set use_internal_logger to false.

What should happen then? Shouldn't such config be invalid?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basically the same thing:
throw an error if out_paths is null and set_intenral_logger is false

name: "custom output paths",
config: func() *Config {
cfg := createDefaultConfig().(*Config)
cfg.QueueConfig.QueueSize = 10
cfg.UseInternalLogger = false
cfg.OutputPaths = []string{"stderr"}
return cfg
}(),
},
}
}

Expand Down
9 changes: 7 additions & 2 deletions exporter/debugexporter/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func createDefaultConfig() component.Config {
SamplingInitial: defaultSamplingInitial,
SamplingThereafter: defaultSamplingThereafter,
UseInternalLogger: true,
OutputPaths: []string{"stdout"},
QueueConfig: queueCfg,
}
}
Expand Down Expand Up @@ -128,6 +129,11 @@ func createCustomLogger(exporterConfig *Config) *zap.Logger {
encoderConfig.LevelKey = ""
// Do not prefix the output with current timestamp.
encoderConfig.TimeKey = ""
outputPaths := exporterConfig.OutputPaths
if len(outputPaths) == 0 {
// Default to stdout if not specified
outputPaths = []string{"stdout"}
}
zapConfig := zap.Config{
Level: zap.NewAtomicLevelAt(zap.InfoLevel),
DisableCaller: true,
Expand All @@ -137,8 +143,7 @@ func createCustomLogger(exporterConfig *Config) *zap.Logger {
},
Encoding: "console",
EncoderConfig: encoderConfig,
// Send exporter's output to stdout. This should be made configurable.
OutputPaths: []string{"stdout"},
OutputPaths: outputPaths,
}
return zap.Must(zapConfig.Build())
}
Loading
Loading