Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
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 URLs or file paths to write logging output to. This option is only used when `use_internal_logger` is `false`. The URLs could only be with "file" schema or without schema. The URLs with "file" schema must be an absolute path. The URLs without schema are treated as local file paths. "stdout" and "stderr" are interpreted as os.Stdout and os.Stderr.
Copy link
Member

Choose a reason for hiding this comment

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

Let's not mention "URLs", it may be confusing to users. I propose to officially support only bare file paths, regardless of what is internally supported by Zap.

Copy link
Author

Choose a reason for hiding this comment

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

ok, ill also add validation for the paths as well to validate that its not one of the following:
file:///path/to/file (contains ://)
http://example.com (contains ://)
file:path/to/file (matches scheme: pattern)

- `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
9 changes: 9 additions & 0 deletions exporter/debugexporter/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ type Config struct {
// 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 URLs or file paths to write logging output to.
// This option is only used when use_internal_logger is false.
// The URLs could only be with "file" schema or without schema.
// The URLs with "file" schema must be an absolute path.
// The URLs without schema are treated as local file paths.
// "stdout" and "stderr" are interpreted as os.Stdout and os.Stderr.
// (default = ["stdout"])
OutputPaths []string `mapstructure:"output_paths"`

QueueConfig exporterhelper.QueueBatchConfig `mapstructure:"sending_queue"`

// prevent unkeyed literal initialization
Expand Down
13 changes: 13 additions & 0 deletions exporter/debugexporter/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@ func TestUnmarshalConfig(t *testing.T) {
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,
},
},
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

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 to an empty array.

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.

good catch, ill validate it and 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())
}
4 changes: 4 additions & 0 deletions exporter/debugexporter/testdata/config_output_paths.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use_internal_logger: false
output_paths:
- stderr