From 7ab23f07fb1a4998a5691b146a6e3e68380d4a61 Mon Sep 17 00:00:00 2001 From: odubajDT Date: Thu, 17 Oct 2024 11:29:10 +0200 Subject: [PATCH 01/11] [receiver/zipkin] move global server configuration parameters to a separate parameter Signed-off-by: odubajDT --- .chloggen/refactor-zipkinreceiver.yaml | 27 +++++++ receiver/zipkinreceiver/README.md | 15 +++- receiver/zipkinreceiver/config.go | 44 +++++++++++ receiver/zipkinreceiver/config_test.go | 73 +++++++++++++++++-- receiver/zipkinreceiver/factory.go | 6 +- receiver/zipkinreceiver/testdata/config.yaml | 4 + receiver/zipkinreceiver/trace_receiver.go | 4 +- .../zipkinreceiver/trace_receiver_test.go | 54 +++++++++----- 8 files changed, 194 insertions(+), 33 deletions(-) create mode 100644 .chloggen/refactor-zipkinreceiver.yaml diff --git a/.chloggen/refactor-zipkinreceiver.yaml b/.chloggen/refactor-zipkinreceiver.yaml new file mode 100644 index 000000000000..65b52f8fb2eb --- /dev/null +++ b/.chloggen/refactor-zipkinreceiver.yaml @@ -0,0 +1,27 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: breaking + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: zipkinreceiver + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: "Move global server configuration parameters to a separate parameter." + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [35730] + +# (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: + +# If your change doesn't affect end users or the exported elements of any package, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. +# 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: [] diff --git a/receiver/zipkinreceiver/README.md b/receiver/zipkinreceiver/README.md index cf13a6043fe4..b18256f17b34 100644 --- a/receiver/zipkinreceiver/README.md +++ b/receiver/zipkinreceiver/README.md @@ -24,14 +24,23 @@ receiver definitions. ```yaml receivers: zipkin: + protocols: + http: + parse_string_tags: false ``` -The following settings are configurable: +Supported parameters: -- `endpoint` (default = localhost:9411): host:port on which the receiver is going to receive data.You can temporarily disable the `component.UseLocalHostAsDefaultHost` feature gate to change this to `0.0.0.0:9411`. This feature gate will be removed in a future release. For full list of `ServerConfig` refer [here](https://github.com/open-telemetry/opentelemetry-collector/tree/main/config/confighttp). - `parse_string_tags` (default = false): if enabled, the receiver will attempt to parse string tags/binary annotations into int/bool/float. +- `protocols` defines the protocol that will be used to receive data. -## Advanced Configuration +## HTTP protocol + +The following settings are configurable for the `http` protocol: + +- `endpoint` (default = localhost:9411): host:port on which the receiver is going to receive data. For full list of `ServerConfig` refer [here](https://github.com/open-telemetry/opentelemetry-collector/tree/main/config/confighttp). + +### Advanced Configuration Several helper files are leveraged to provide additional capabilities automatically: diff --git a/receiver/zipkinreceiver/config.go b/receiver/zipkinreceiver/config.go index bd5419568633..9db99464a2fc 100644 --- a/receiver/zipkinreceiver/config.go +++ b/receiver/zipkinreceiver/config.go @@ -4,22 +4,66 @@ package zipkinreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver" import ( + "fmt" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/confighttp" + "go.opentelemetry.io/collector/featuregate" +) + +var disallowHttpDefaultProtocol = featuregate.GlobalRegistry().MustRegister( + "zipkinreceiver.httpDefaultProtocol.disallow", + featuregate.StageAlpha, + featuregate.WithRegisterDescription("When enabled, usage of the default http configuration is disallowed"), + featuregate.WithRegisterFromVersion("v0.112.0"), ) // Config defines configuration for Zipkin receiver. type Config struct { // Configures the receiver server protocol. + // + // Deprecated: Parameter exists for historical compatibility + // and should not be used. To set the server configurations, + // use the Protocols parameter instead. confighttp.ServerConfig `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct // If enabled the zipkin receiver will attempt to parse string tags/binary annotations into int/bool/float. // Disabled by default ParseStringTags bool `mapstructure:"parse_string_tags"` + // Protocols define the supported protocols for the receiver + Protocols ProtocolTypes `mapstructure:"protocols"` +} + +type ProtocolTypes struct { + Http confighttp.ServerConfig `mapstructure:"http"` } var _ component.Config = (*Config)(nil) // Validate checks the receiver configuration is valid func (cfg *Config) Validate() error { + if cfg.isServerConfigDefined() { + if disallowHttpDefaultProtocol.IsEnabled() { + return fmt.Errorf("the inline setting of http server parameters has been deprecated, please use protocols.http parameter instead") + } + cfg.Protocols.Http = cfg.ServerConfig + cfg.ServerConfig = confighttp.ServerConfig{} + } + return nil } + +// IsServerConfigDefined checks if the ServerConfig is defined by the user +func (cfg *Config) isServerConfigDefined() bool { + return cfg.Endpoint != "" || + cfg.TLSSetting != nil || + cfg.CORS != nil || + cfg.Auth != nil || + cfg.MaxRequestBodySize != 0 || + cfg.IncludeMetadata != false || + len(cfg.ResponseHeaders) != 0 || + len(cfg.CompressionAlgorithms) != 0 || + cfg.ReadHeaderTimeout != 0 || + cfg.ReadTimeout != 0 || + cfg.WriteTimeout != 0 || + cfg.IdleTimeout != 0 +} diff --git a/receiver/zipkinreceiver/config_test.go b/receiver/zipkinreceiver/config_test.go index fb0117ba6d15..e7508d51deee 100644 --- a/receiver/zipkinreceiver/config_test.go +++ b/receiver/zipkinreceiver/config_test.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/confighttp" "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/featuregate" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver/internal/metadata" ) @@ -23,8 +24,10 @@ func TestLoadConfig(t *testing.T) { require.NoError(t, err) tests := []struct { - id component.ID - expected component.Config + id component.ID + disallowInline bool + expected component.Config + wantErr bool }{ { id: component.NewID(metadata.Type), @@ -33,25 +36,75 @@ func TestLoadConfig(t *testing.T) { { id: component.NewIDWithName(metadata.Type, "customname"), expected: &Config{ - ServerConfig: confighttp.ServerConfig{ - Endpoint: "localhost:8765", + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: "localhost:8765", + }, }, ParseStringTags: false, }, }, + { + id: component.NewIDWithName(metadata.Type, "customname"), + disallowInline: true, + wantErr: true, + }, + { + id: component.NewIDWithName(metadata.Type, "protocols"), + expected: &Config{ + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: "localhost:8765", + }, + }, + ParseStringTags: false, + }, + }, + { + id: component.NewIDWithName(metadata.Type, "protocols"), + expected: &Config{ + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: "localhost:8765", + }, + }, + ParseStringTags: false, + }, + disallowInline: true, + }, + { + id: component.NewIDWithName(metadata.Type, "parse_strings"), + expected: &Config{ + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: defaultBindEndpoint, + }, + }, + ParseStringTags: true, + }, + }, { id: component.NewIDWithName(metadata.Type, "parse_strings"), expected: &Config{ - ServerConfig: confighttp.ServerConfig{ - Endpoint: defaultBindEndpoint, + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: defaultBindEndpoint, + }, }, ParseStringTags: true, }, + disallowInline: true, }, } for _, tt := range tests { t.Run(tt.id.String(), func(t *testing.T) { + if tt.disallowInline { + require.Nil(t, featuregate.GlobalRegistry().Set(disallowHttpDefaultProtocol.ID(), true)) + t.Cleanup(func() { + require.Nil(t, featuregate.GlobalRegistry().Set(disallowHttpDefaultProtocol.ID(), false)) + }) + } factory := NewFactory() cfg := factory.CreateDefaultConfig() @@ -59,8 +112,12 @@ func TestLoadConfig(t *testing.T) { require.NoError(t, err) require.NoError(t, sub.Unmarshal(cfg)) - assert.NoError(t, component.ValidateConfig(cfg)) - assert.Equal(t, tt.expected, cfg) + if tt.wantErr { + assert.Error(t, component.ValidateConfig(cfg)) + } else { + assert.NoError(t, component.ValidateConfig(cfg)) + assert.Equal(t, tt.expected, cfg) + } }) } } diff --git a/receiver/zipkinreceiver/factory.go b/receiver/zipkinreceiver/factory.go index dd86d7d9c477..1f1a2ec92e65 100644 --- a/receiver/zipkinreceiver/factory.go +++ b/receiver/zipkinreceiver/factory.go @@ -34,8 +34,10 @@ func NewFactory() receiver.Factory { // createDefaultConfig creates the default configuration for Zipkin receiver. func createDefaultConfig() component.Config { return &Config{ - ServerConfig: confighttp.ServerConfig{ - Endpoint: testutil.EndpointForPort(defaultHTTPPort), + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: testutil.EndpointForPort(defaultHTTPPort), + }, }, ParseStringTags: false, } diff --git a/receiver/zipkinreceiver/testdata/config.yaml b/receiver/zipkinreceiver/testdata/config.yaml index f0ccdc3c65ae..8c58da0e0e28 100644 --- a/receiver/zipkinreceiver/testdata/config.yaml +++ b/receiver/zipkinreceiver/testdata/config.yaml @@ -1,5 +1,9 @@ zipkin: zipkin/customname: endpoint: "localhost:8765" +zipkin/protocols: + protocols: + http: + endpoint: "localhost:8765" zipkin/parse_strings: parse_string_tags: true diff --git a/receiver/zipkinreceiver/trace_receiver.go b/receiver/zipkinreceiver/trace_receiver.go index c3f5ceffc547..9d267dc368a1 100644 --- a/receiver/zipkinreceiver/trace_receiver.go +++ b/receiver/zipkinreceiver/trace_receiver.go @@ -95,13 +95,13 @@ func (zr *zipkinReceiver) Start(ctx context.Context, host component.Host) error } var err error - zr.server, err = zr.config.ServerConfig.ToServer(ctx, host, zr.settings.TelemetrySettings, zr) + zr.server, err = zr.config.Protocols.Http.ToServer(ctx, host, zr.settings.TelemetrySettings, zr) if err != nil { return err } var listener net.Listener - listener, err = zr.config.ServerConfig.ToListener(ctx) + listener, err = zr.config.Protocols.Http.ToListener(ctx) if err != nil { return err } diff --git a/receiver/zipkinreceiver/trace_receiver_test.go b/receiver/zipkinreceiver/trace_receiver_test.go index 1f5acd59a923..c71fb21d8017 100644 --- a/receiver/zipkinreceiver/trace_receiver_test.go +++ b/receiver/zipkinreceiver/trace_receiver_test.go @@ -58,8 +58,10 @@ func TestNew(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { cfg := &Config{ - ServerConfig: confighttp.ServerConfig{ - Endpoint: tt.args.address, + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: tt.args.address, + }, }, } got, err := newReceiver(cfg, tt.args.nextConsumer, receivertest.NewNopSettings()) @@ -80,8 +82,10 @@ func TestZipkinReceiverPortAlreadyInUse(t *testing.T) { _, portStr, err := net.SplitHostPort(l.Addr().String()) require.NoError(t, err, "failed to split listener address: %v", err) cfg := &Config{ - ServerConfig: confighttp.ServerConfig{ - Endpoint: "localhost:" + portStr, + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: "localhost:" + portStr, + }, }, } traceReceiver, err := newReceiver(cfg, consumertest.NewNop(), receivertest.NewNopSettings()) @@ -128,8 +132,10 @@ func TestStartTraceReception(t *testing.T) { t.Run(tt.name, func(t *testing.T) { sink := new(consumertest.TracesSink) cfg := &Config{ - ServerConfig: confighttp.ServerConfig{ - Endpoint: "localhost:0", + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: "localhost:0", + }, }, } zr, err := newReceiver(cfg, sink, receivertest.NewNopSettings()) @@ -221,8 +227,10 @@ func TestReceiverContentTypes(t *testing.T) { next := new(consumertest.TracesSink) cfg := &Config{ - ServerConfig: confighttp.ServerConfig{ - Endpoint: "", + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: "", + }, }, } zr, err := newReceiver(cfg, next, receivertest.NewNopSettings()) @@ -248,8 +256,10 @@ func TestReceiverInvalidContentType(t *testing.T) { r.Header.Add("content-type", "application/json") cfg := &Config{ - ServerConfig: confighttp.ServerConfig{ - Endpoint: "", + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: "", + }, }, } zr, err := newReceiver(cfg, consumertest.NewNop(), receivertest.NewNopSettings()) @@ -270,8 +280,10 @@ func TestReceiverConsumerError(t *testing.T) { r.Header.Add("content-type", "application/json") cfg := &Config{ - ServerConfig: confighttp.ServerConfig{ - Endpoint: "localhost:9411", + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: "localhost:9411", + }, }, } zr, err := newReceiver(cfg, consumertest.NewErr(errors.New("consumer error")), receivertest.NewNopSettings()) @@ -292,8 +304,10 @@ func TestReceiverConsumerPermanentError(t *testing.T) { r.Header.Add("content-type", "application/json") cfg := &Config{ - ServerConfig: confighttp.ServerConfig{ - Endpoint: "localhost:9411", + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: "localhost:9411", + }, }, } zr, err := newReceiver(cfg, consumertest.NewErr(consumererror.NewPermanent(errors.New("consumer error"))), receivertest.NewNopSettings()) @@ -418,8 +432,10 @@ func TestReceiverConvertsStringsToTypes(t *testing.T) { next := new(consumertest.TracesSink) cfg := &Config{ - ServerConfig: confighttp.ServerConfig{ - Endpoint: "", + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: "", + }, }, ParseStringTags: true, } @@ -459,8 +475,10 @@ func TestFromBytesWithNoTimestamp(t *testing.T) { require.NoError(t, err, "Failed to read sample JSON file: %v", err) cfg := &Config{ - ServerConfig: confighttp.ServerConfig{ - Endpoint: "", + Protocols: ProtocolTypes{ + Http: confighttp.ServerConfig{ + Endpoint: "", + }, }, ParseStringTags: true, } From f28b4e645ac64db6b486917fc82715b7f5ba9e40 Mon Sep 17 00:00:00 2001 From: odubajDT Date: Thu, 17 Oct 2024 13:15:22 +0200 Subject: [PATCH 02/11] fix linter and test errors Signed-off-by: odubajDT --- exporter/zipkinexporter/zipkin_test.go | 12 ++++++++---- receiver/zipkinreceiver/config.go | 6 +++--- receiver/zipkinreceiver/config_test.go | 10 +++++----- receiver/zipkinreceiver/factory.go | 2 +- receiver/zipkinreceiver/trace_receiver.go | 4 ++-- receiver/zipkinreceiver/trace_receiver_test.go | 18 +++++++++--------- 6 files changed, 28 insertions(+), 24 deletions(-) diff --git a/exporter/zipkinexporter/zipkin_test.go b/exporter/zipkinexporter/zipkin_test.go index 4810ac95c0dd..1899b8115b5b 100644 --- a/exporter/zipkinexporter/zipkin_test.go +++ b/exporter/zipkinexporter/zipkin_test.go @@ -66,8 +66,10 @@ func TestZipkinExporter_roundtripJSON(t *testing.T) { // Run the Zipkin receiver to "receive spans upload from a client application" addr := testutil.GetAvailableLocalAddress(t) recvCfg := &zipkinreceiver.Config{ - ServerConfig: confighttp.ServerConfig{ - Endpoint: addr, + Protocols: zipkinreceiver.ProtocolTypes{ + HTTP: confighttp.ServerConfig{ + Endpoint: addr, + }, }, } zi, err := zipkinreceiver.NewFactory().CreateTraces(context.Background(), receivertest.NewNopSettings(), recvCfg, zexp) @@ -314,8 +316,10 @@ func TestZipkinExporter_roundtripProto(t *testing.T) { // Run the Zipkin receiver to "receive spans upload from a client application" addr := testutil.GetAvailableLocalAddress(t) recvCfg := &zipkinreceiver.Config{ - ServerConfig: confighttp.ServerConfig{ - Endpoint: addr, + Protocols: zipkinreceiver.ProtocolTypes{ + HTTP: confighttp.ServerConfig{ + Endpoint: addr, + }, }, } zi, err := zipkinreceiver.NewFactory().CreateTraces(context.Background(), receivertest.NewNopSettings(), recvCfg, zexp) diff --git a/receiver/zipkinreceiver/config.go b/receiver/zipkinreceiver/config.go index 9db99464a2fc..c4e1099928c0 100644 --- a/receiver/zipkinreceiver/config.go +++ b/receiver/zipkinreceiver/config.go @@ -34,7 +34,7 @@ type Config struct { } type ProtocolTypes struct { - Http confighttp.ServerConfig `mapstructure:"http"` + HTTP confighttp.ServerConfig `mapstructure:"http"` } var _ component.Config = (*Config)(nil) @@ -45,7 +45,7 @@ func (cfg *Config) Validate() error { if disallowHttpDefaultProtocol.IsEnabled() { return fmt.Errorf("the inline setting of http server parameters has been deprecated, please use protocols.http parameter instead") } - cfg.Protocols.Http = cfg.ServerConfig + cfg.Protocols.HTTP = cfg.ServerConfig cfg.ServerConfig = confighttp.ServerConfig{} } @@ -59,7 +59,7 @@ func (cfg *Config) isServerConfigDefined() bool { cfg.CORS != nil || cfg.Auth != nil || cfg.MaxRequestBodySize != 0 || - cfg.IncludeMetadata != false || + cfg.IncludeMetadata || len(cfg.ResponseHeaders) != 0 || len(cfg.CompressionAlgorithms) != 0 || cfg.ReadHeaderTimeout != 0 || diff --git a/receiver/zipkinreceiver/config_test.go b/receiver/zipkinreceiver/config_test.go index e7508d51deee..6aafe770b460 100644 --- a/receiver/zipkinreceiver/config_test.go +++ b/receiver/zipkinreceiver/config_test.go @@ -37,7 +37,7 @@ func TestLoadConfig(t *testing.T) { id: component.NewIDWithName(metadata.Type, "customname"), expected: &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: "localhost:8765", }, }, @@ -53,7 +53,7 @@ func TestLoadConfig(t *testing.T) { id: component.NewIDWithName(metadata.Type, "protocols"), expected: &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: "localhost:8765", }, }, @@ -64,7 +64,7 @@ func TestLoadConfig(t *testing.T) { id: component.NewIDWithName(metadata.Type, "protocols"), expected: &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: "localhost:8765", }, }, @@ -76,7 +76,7 @@ func TestLoadConfig(t *testing.T) { id: component.NewIDWithName(metadata.Type, "parse_strings"), expected: &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: defaultBindEndpoint, }, }, @@ -87,7 +87,7 @@ func TestLoadConfig(t *testing.T) { id: component.NewIDWithName(metadata.Type, "parse_strings"), expected: &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: defaultBindEndpoint, }, }, diff --git a/receiver/zipkinreceiver/factory.go b/receiver/zipkinreceiver/factory.go index 1f1a2ec92e65..d8bcf0a062b3 100644 --- a/receiver/zipkinreceiver/factory.go +++ b/receiver/zipkinreceiver/factory.go @@ -35,7 +35,7 @@ func NewFactory() receiver.Factory { func createDefaultConfig() component.Config { return &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: testutil.EndpointForPort(defaultHTTPPort), }, }, diff --git a/receiver/zipkinreceiver/trace_receiver.go b/receiver/zipkinreceiver/trace_receiver.go index 9d267dc368a1..04cc88d358ad 100644 --- a/receiver/zipkinreceiver/trace_receiver.go +++ b/receiver/zipkinreceiver/trace_receiver.go @@ -95,13 +95,13 @@ func (zr *zipkinReceiver) Start(ctx context.Context, host component.Host) error } var err error - zr.server, err = zr.config.Protocols.Http.ToServer(ctx, host, zr.settings.TelemetrySettings, zr) + zr.server, err = zr.config.Protocols.HTTP.ToServer(ctx, host, zr.settings.TelemetrySettings, zr) if err != nil { return err } var listener net.Listener - listener, err = zr.config.Protocols.Http.ToListener(ctx) + listener, err = zr.config.Protocols.HTTP.ToListener(ctx) if err != nil { return err } diff --git a/receiver/zipkinreceiver/trace_receiver_test.go b/receiver/zipkinreceiver/trace_receiver_test.go index c71fb21d8017..0acf434735a4 100644 --- a/receiver/zipkinreceiver/trace_receiver_test.go +++ b/receiver/zipkinreceiver/trace_receiver_test.go @@ -59,7 +59,7 @@ func TestNew(t *testing.T) { t.Run(tt.name, func(t *testing.T) { cfg := &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: tt.args.address, }, }, @@ -83,7 +83,7 @@ func TestZipkinReceiverPortAlreadyInUse(t *testing.T) { require.NoError(t, err, "failed to split listener address: %v", err) cfg := &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: "localhost:" + portStr, }, }, @@ -133,7 +133,7 @@ func TestStartTraceReception(t *testing.T) { sink := new(consumertest.TracesSink) cfg := &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: "localhost:0", }, }, @@ -228,7 +228,7 @@ func TestReceiverContentTypes(t *testing.T) { next := new(consumertest.TracesSink) cfg := &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: "", }, }, @@ -257,7 +257,7 @@ func TestReceiverInvalidContentType(t *testing.T) { cfg := &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: "", }, }, @@ -281,7 +281,7 @@ func TestReceiverConsumerError(t *testing.T) { cfg := &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: "localhost:9411", }, }, @@ -305,7 +305,7 @@ func TestReceiverConsumerPermanentError(t *testing.T) { cfg := &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: "localhost:9411", }, }, @@ -433,7 +433,7 @@ func TestReceiverConvertsStringsToTypes(t *testing.T) { next := new(consumertest.TracesSink) cfg := &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: "", }, }, @@ -476,7 +476,7 @@ func TestFromBytesWithNoTimestamp(t *testing.T) { cfg := &Config{ Protocols: ProtocolTypes{ - Http: confighttp.ServerConfig{ + HTTP: confighttp.ServerConfig{ Endpoint: "", }, }, From 829d2fb483d1b4dabba5bcfea229286a0fdf85c5 Mon Sep 17 00:00:00 2001 From: odubajDT Date: Thu, 17 Oct 2024 13:30:01 +0200 Subject: [PATCH 03/11] fix lint Signed-off-by: odubajDT --- exporter/logzioexporter/example/config.yaml | 4 +++- receiver/zipkinreceiver/config.go | 4 ++-- receiver/zipkinreceiver/config_test.go | 4 ++-- testbed/datareceivers/zipkin.go | 6 ++++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/exporter/logzioexporter/example/config.yaml b/exporter/logzioexporter/example/config.yaml index 57f47ffd4b4c..a9f108bb90eb 100644 --- a/exporter/logzioexporter/example/config.yaml +++ b/exporter/logzioexporter/example/config.yaml @@ -2,7 +2,9 @@ receivers: opencensus: endpoint: :55678 zipkin: - endpoint: :9411 + protocols: + http: + endpoint: :9411 jaeger: protocols: thrift_http: diff --git a/receiver/zipkinreceiver/config.go b/receiver/zipkinreceiver/config.go index c4e1099928c0..5019f49de40a 100644 --- a/receiver/zipkinreceiver/config.go +++ b/receiver/zipkinreceiver/config.go @@ -11,7 +11,7 @@ import ( "go.opentelemetry.io/collector/featuregate" ) -var disallowHttpDefaultProtocol = featuregate.GlobalRegistry().MustRegister( +var disallowHTTPDefaultProtocol = featuregate.GlobalRegistry().MustRegister( "zipkinreceiver.httpDefaultProtocol.disallow", featuregate.StageAlpha, featuregate.WithRegisterDescription("When enabled, usage of the default http configuration is disallowed"), @@ -42,7 +42,7 @@ var _ component.Config = (*Config)(nil) // Validate checks the receiver configuration is valid func (cfg *Config) Validate() error { if cfg.isServerConfigDefined() { - if disallowHttpDefaultProtocol.IsEnabled() { + if disallowHTTPDefaultProtocol.IsEnabled() { return fmt.Errorf("the inline setting of http server parameters has been deprecated, please use protocols.http parameter instead") } cfg.Protocols.HTTP = cfg.ServerConfig diff --git a/receiver/zipkinreceiver/config_test.go b/receiver/zipkinreceiver/config_test.go index 6aafe770b460..718fd6735744 100644 --- a/receiver/zipkinreceiver/config_test.go +++ b/receiver/zipkinreceiver/config_test.go @@ -100,9 +100,9 @@ func TestLoadConfig(t *testing.T) { for _, tt := range tests { t.Run(tt.id.String(), func(t *testing.T) { if tt.disallowInline { - require.Nil(t, featuregate.GlobalRegistry().Set(disallowHttpDefaultProtocol.ID(), true)) + require.NoError(t, featuregate.GlobalRegistry().Set(disallowHTTPDefaultProtocol.ID(), true)) t.Cleanup(func() { - require.Nil(t, featuregate.GlobalRegistry().Set(disallowHttpDefaultProtocol.ID(), false)) + require.NoError(t, featuregate.GlobalRegistry().Set(disallowHTTPDefaultProtocol.ID(), false)) }) } factory := NewFactory() diff --git a/testbed/datareceivers/zipkin.go b/testbed/datareceivers/zipkin.go index 479f7daeacd7..3b650e46daa6 100644 --- a/testbed/datareceivers/zipkin.go +++ b/testbed/datareceivers/zipkin.go @@ -51,8 +51,10 @@ func (zr *zipkinDataReceiver) GenConfigYAMLStr() string { // Note that this generates an exporter config for agent. return fmt.Sprintf(` zipkin: - endpoint: http://127.0.0.1:%d/api/v2/spans - format: json`, zr.Port) + protocols: + http: + endpoint: http://127.0.0.1:%d/api/v2/spans + format: json`, zr.Port) } func (zr *zipkinDataReceiver) ProtocolName() string { From 250b4b984d1d60d578fc487f228c23ed70e29125 Mon Sep 17 00:00:00 2001 From: odubajDT Date: Thu, 17 Oct 2024 13:36:44 +0200 Subject: [PATCH 04/11] go mod tidy Signed-off-by: odubajDT --- receiver/zipkinreceiver/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/receiver/zipkinreceiver/go.mod b/receiver/zipkinreceiver/go.mod index 74dce00d10d9..3102ede83abe 100644 --- a/receiver/zipkinreceiver/go.mod +++ b/receiver/zipkinreceiver/go.mod @@ -16,6 +16,7 @@ require ( go.opentelemetry.io/collector/consumer v0.113.0 go.opentelemetry.io/collector/consumer/consumererror v0.113.0 go.opentelemetry.io/collector/consumer/consumertest v0.113.0 + go.opentelemetry.io/collector/featuregate v1.19.0 go.opentelemetry.io/collector/pdata v1.19.0 go.opentelemetry.io/collector/receiver v0.113.0 go.opentelemetry.io/collector/receiver/receivertest v0.113.0 @@ -58,7 +59,6 @@ require ( go.opentelemetry.io/collector/consumer/consumerprofiles v0.113.0 // indirect go.opentelemetry.io/collector/extension v0.113.0 // indirect go.opentelemetry.io/collector/extension/auth v0.113.0 // indirect - go.opentelemetry.io/collector/featuregate v1.19.0 // indirect go.opentelemetry.io/collector/pdata/pprofile v0.113.0 // indirect go.opentelemetry.io/collector/pipeline v0.113.0 // indirect go.opentelemetry.io/collector/receiver/receiverprofiles v0.113.0 // indirect From 8d7bf6edb02ca93cbb180c87729859a932eb9c66 Mon Sep 17 00:00:00 2001 From: odubajDT Date: Thu, 17 Oct 2024 13:42:59 +0200 Subject: [PATCH 05/11] revert change on exporter Signed-off-by: odubajDT --- testbed/datareceivers/zipkin.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/testbed/datareceivers/zipkin.go b/testbed/datareceivers/zipkin.go index 3b650e46daa6..479f7daeacd7 100644 --- a/testbed/datareceivers/zipkin.go +++ b/testbed/datareceivers/zipkin.go @@ -51,10 +51,8 @@ func (zr *zipkinDataReceiver) GenConfigYAMLStr() string { // Note that this generates an exporter config for agent. return fmt.Sprintf(` zipkin: - protocols: - http: - endpoint: http://127.0.0.1:%d/api/v2/spans - format: json`, zr.Port) + endpoint: http://127.0.0.1:%d/api/v2/spans + format: json`, zr.Port) } func (zr *zipkinDataReceiver) ProtocolName() string { From 69ec19a11f6eb54ecdafbbc147285de414bd6403 Mon Sep 17 00:00:00 2001 From: odubajDT Date: Thu, 17 Oct 2024 13:56:37 +0200 Subject: [PATCH 06/11] fix corectnes traces test Signed-off-by: odubajDT --- testbed/datasenders/zipkin.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testbed/datasenders/zipkin.go b/testbed/datasenders/zipkin.go index 521dee97eafd..2bb71faed80f 100644 --- a/testbed/datasenders/zipkin.go +++ b/testbed/datasenders/zipkin.go @@ -56,7 +56,9 @@ func (zs *zipkinDataSender) Start() error { func (zs *zipkinDataSender) GenConfigYAMLStr() string { return fmt.Sprintf(` zipkin: - endpoint: %s`, zs.GetEndpoint()) + protocols: + http: + endpoint: %s`, zs.GetEndpoint()) } func (zs *zipkinDataSender) ProtocolName() string { From d3b87732734a75f775f5517f3d3d589767dad278 Mon Sep 17 00:00:00 2001 From: odubajDT Date: Thu, 17 Oct 2024 14:48:57 +0200 Subject: [PATCH 07/11] fix traces tests Signed-off-by: odubajDT --- testbed/datareceivers/zipkin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testbed/datareceivers/zipkin.go b/testbed/datareceivers/zipkin.go index 479f7daeacd7..22cfe4b7b982 100644 --- a/testbed/datareceivers/zipkin.go +++ b/testbed/datareceivers/zipkin.go @@ -31,7 +31,7 @@ func NewZipkinDataReceiver(port int) testbed.DataReceiver { func (zr *zipkinDataReceiver) Start(tc consumer.Traces, _ consumer.Metrics, _ consumer.Logs) error { factory := zipkinreceiver.NewFactory() cfg := factory.CreateDefaultConfig().(*zipkinreceiver.Config) - cfg.Endpoint = fmt.Sprintf("127.0.0.1:%d", zr.Port) + cfg.Protocols.HTTP.Endpoint = fmt.Sprintf("127.0.0.1:%d", zr.Port) set := receivertest.NewNopSettings() var err error From 785fde632f91c8eff1832cf82f61858623bf9be0 Mon Sep 17 00:00:00 2001 From: odubajDT <93584209+odubajDT@users.noreply.github.com> Date: Thu, 14 Nov 2024 08:58:28 +0100 Subject: [PATCH 08/11] Update receiver/zipkinreceiver/config.go Co-authored-by: Andrzej Stencel --- receiver/zipkinreceiver/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/receiver/zipkinreceiver/config.go b/receiver/zipkinreceiver/config.go index 5019f49de40a..f0d869c344c7 100644 --- a/receiver/zipkinreceiver/config.go +++ b/receiver/zipkinreceiver/config.go @@ -15,7 +15,7 @@ var disallowHTTPDefaultProtocol = featuregate.GlobalRegistry().MustRegister( "zipkinreceiver.httpDefaultProtocol.disallow", featuregate.StageAlpha, featuregate.WithRegisterDescription("When enabled, usage of the default http configuration is disallowed"), - featuregate.WithRegisterFromVersion("v0.112.0"), + featuregate.WithRegisterFromVersion("v0.114.0"), ) // Config defines configuration for Zipkin receiver. From 8a59a9add37171c70cded91020453bdada23989b Mon Sep 17 00:00:00 2001 From: odubajDT Date: Thu, 14 Nov 2024 11:13:35 +0100 Subject: [PATCH 09/11] pr review Signed-off-by: odubajDT --- receiver/zipkinreceiver/config.go | 11 ++- receiver/zipkinreceiver/config_test.go | 77 +++++++++++++++----- receiver/zipkinreceiver/factory.go | 3 + receiver/zipkinreceiver/factory_test.go | 36 +++++++++ receiver/zipkinreceiver/testdata/config.yaml | 5 ++ 5 files changed, 112 insertions(+), 20 deletions(-) diff --git a/receiver/zipkinreceiver/config.go b/receiver/zipkinreceiver/config.go index f0d869c344c7..0682f89f665e 100644 --- a/receiver/zipkinreceiver/config.go +++ b/receiver/zipkinreceiver/config.go @@ -18,6 +18,8 @@ var disallowHTTPDefaultProtocol = featuregate.GlobalRegistry().MustRegister( featuregate.WithRegisterFromVersion("v0.114.0"), ) +const deprecationConfigMsg = "the inline setting of http server parameters has been deprecated, please use .protocols.http parameter instead." + // Config defines configuration for Zipkin receiver. type Config struct { // Configures the receiver server protocol. @@ -41,9 +43,12 @@ var _ component.Config = (*Config)(nil) // Validate checks the receiver configuration is valid func (cfg *Config) Validate() error { - if cfg.isServerConfigDefined() { + if isServerConfigDefined(cfg.ServerConfig) { if disallowHTTPDefaultProtocol.IsEnabled() { - return fmt.Errorf("the inline setting of http server parameters has been deprecated, please use protocols.http parameter instead") + return fmt.Errorf(deprecationConfigMsg) + } + if isServerConfigDefined(cfg.Protocols.HTTP) { + return fmt.Errorf("cannot use .protocols.http together with default server config setup") } cfg.Protocols.HTTP = cfg.ServerConfig cfg.ServerConfig = confighttp.ServerConfig{} @@ -53,7 +58,7 @@ func (cfg *Config) Validate() error { } // IsServerConfigDefined checks if the ServerConfig is defined by the user -func (cfg *Config) isServerConfigDefined() bool { +func isServerConfigDefined(cfg confighttp.ServerConfig) bool { return cfg.Endpoint != "" || cfg.TLSSetting != nil || cfg.CORS != nil || diff --git a/receiver/zipkinreceiver/config_test.go b/receiver/zipkinreceiver/config_test.go index 718fd6735744..24c3413c8853 100644 --- a/receiver/zipkinreceiver/config_test.go +++ b/receiver/zipkinreceiver/config_test.go @@ -4,6 +4,7 @@ package zipkinreceiver import ( + "fmt" "path/filepath" "testing" @@ -17,7 +18,7 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver/internal/metadata" ) -func TestLoadConfig(t *testing.T) { +func TestValidateConfig(t *testing.T) { t.Parallel() cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) @@ -27,12 +28,8 @@ func TestLoadConfig(t *testing.T) { id component.ID disallowInline bool expected component.Config - wantErr bool + wantErr error }{ - { - id: component.NewID(metadata.Type), - expected: createDefaultConfig(), - }, { id: component.NewIDWithName(metadata.Type, "customname"), expected: &Config{ @@ -47,7 +44,7 @@ func TestLoadConfig(t *testing.T) { { id: component.NewIDWithName(metadata.Type, "customname"), disallowInline: true, - wantErr: true, + wantErr: fmt.Errorf(deprecationConfigMsg), }, { id: component.NewIDWithName(metadata.Type, "protocols"), @@ -75,26 +72,26 @@ func TestLoadConfig(t *testing.T) { { id: component.NewIDWithName(metadata.Type, "parse_strings"), expected: &Config{ - Protocols: ProtocolTypes{ - HTTP: confighttp.ServerConfig{ - Endpoint: defaultBindEndpoint, - }, - }, ParseStringTags: true, }, }, { id: component.NewIDWithName(metadata.Type, "parse_strings"), expected: &Config{ - Protocols: ProtocolTypes{ - HTTP: confighttp.ServerConfig{ - Endpoint: defaultBindEndpoint, - }, - }, ParseStringTags: true, }, disallowInline: true, }, + { + id: component.NewIDWithName(metadata.Type, "deprecated"), + disallowInline: true, + wantErr: fmt.Errorf(deprecationConfigMsg), + }, + { + id: component.NewIDWithName(metadata.Type, "deprecated"), + disallowInline: false, + wantErr: fmt.Errorf("cannot use .protocols.http together with default server config setup"), + }, } for _, tt := range tests { @@ -105,6 +102,52 @@ func TestLoadConfig(t *testing.T) { require.NoError(t, featuregate.GlobalRegistry().Set(disallowHTTPDefaultProtocol.ID(), false)) }) } + cfg := &Config{} + + sub, err := cm.Sub(tt.id.String()) + require.NoError(t, err) + require.NoError(t, sub.Unmarshal(cfg)) + + if tt.wantErr != nil { + assert.Equal(t, tt.wantErr, component.ValidateConfig(cfg)) + } else { + assert.NoError(t, component.ValidateConfig(cfg)) + assert.Equal(t, tt.expected, cfg) + } + }) + } +} + +func TestLoadConfig(t *testing.T) { + t.Parallel() + + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + + tests := []struct { + id component.ID + expected component.Config + wantErr bool + }{ + { + id: component.NewID(metadata.Type), + expected: createDefaultConfig(), + }, + { + id: component.NewIDWithName(metadata.Type, "parse_strings"), + expected: &Config{ + Protocols: ProtocolTypes{ + HTTP: confighttp.ServerConfig{ + Endpoint: defaultBindEndpoint, + }, + }, + ParseStringTags: true, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.id.String(), func(t *testing.T) { factory := NewFactory() cfg := factory.CreateDefaultConfig() diff --git a/receiver/zipkinreceiver/factory.go b/receiver/zipkinreceiver/factory.go index d8bcf0a062b3..47cb7a600955 100644 --- a/receiver/zipkinreceiver/factory.go +++ b/receiver/zipkinreceiver/factory.go @@ -51,5 +51,8 @@ func createTracesReceiver( nextConsumer consumer.Traces, ) (receiver.Traces, error) { rCfg := cfg.(*Config) + if isServerConfigDefined(rCfg.ServerConfig) { + set.Logger.Warn(deprecationConfigMsg) + } return newReceiver(rCfg, nextConsumer, set) } diff --git a/receiver/zipkinreceiver/factory_test.go b/receiver/zipkinreceiver/factory_test.go index c2051fa198a3..b1e70db4d34a 100644 --- a/receiver/zipkinreceiver/factory_test.go +++ b/receiver/zipkinreceiver/factory_test.go @@ -4,13 +4,18 @@ package zipkinreceiver import ( + "bytes" "context" "testing" + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/testutil" "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/confighttp" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/receiver/receivertest" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" ) func TestCreateDefaultConfig(t *testing.T) { @@ -38,3 +43,34 @@ func TestCreateReceiver(t *testing.T) { assert.NoError(t, err, "receiver creation failed") assert.NotNil(t, tReceiver, "receiver creation failed") } + +func TestCreateReceiverDeprecatedWarning(t *testing.T) { + cfg := &Config{ + ServerConfig: confighttp.ServerConfig{ + Endpoint: testutil.EndpointForPort(defaultHTTPPort), + }, + ParseStringTags: false, + } + + var buffer bytes.Buffer + writer := zapcore.AddSync(&buffer) + + encoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()) + core := zapcore.NewCore(encoder, writer, zapcore.DebugLevel) + logger := zap.New(core) + + set := receivertest.NewNopSettings() + set.Logger = logger + + _, _ = createTracesReceiver( + context.Background(), + set, + cfg, + consumertest.NewNop(), + ) + + logOutput := buffer.String() + if !bytes.Contains([]byte(logOutput), []byte(deprecationConfigMsg)) { + t.Errorf("Expected log message not found. Got: %s", logOutput) + } +} diff --git a/receiver/zipkinreceiver/testdata/config.yaml b/receiver/zipkinreceiver/testdata/config.yaml index 8c58da0e0e28..6028b8d5eea2 100644 --- a/receiver/zipkinreceiver/testdata/config.yaml +++ b/receiver/zipkinreceiver/testdata/config.yaml @@ -7,3 +7,8 @@ zipkin/protocols: endpoint: "localhost:8765" zipkin/parse_strings: parse_string_tags: true +zipkin/deprecated: + endpoint: "localhost:8766" + protocols: + http: + endpoint: "localhost:8765" From fec6669d592804952b05baddbc2402d00ea8ea49 Mon Sep 17 00:00:00 2001 From: odubajDT Date: Thu, 14 Nov 2024 11:15:36 +0100 Subject: [PATCH 10/11] check err Signed-off-by: odubajDT --- receiver/zipkinreceiver/factory_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/receiver/zipkinreceiver/factory_test.go b/receiver/zipkinreceiver/factory_test.go index b1e70db4d34a..593d848c3438 100644 --- a/receiver/zipkinreceiver/factory_test.go +++ b/receiver/zipkinreceiver/factory_test.go @@ -62,13 +62,15 @@ func TestCreateReceiverDeprecatedWarning(t *testing.T) { set := receivertest.NewNopSettings() set.Logger = logger - _, _ = createTracesReceiver( + _, err := createTracesReceiver( context.Background(), set, cfg, consumertest.NewNop(), ) + assert.NoError(t, err) + logOutput := buffer.String() if !bytes.Contains([]byte(logOutput), []byte(deprecationConfigMsg)) { t.Errorf("Expected log message not found. Got: %s", logOutput) From 5c8e10f3d96834638df3bd272da871d62a9366ff Mon Sep 17 00:00:00 2001 From: odubajDT Date: Thu, 14 Nov 2024 11:24:53 +0100 Subject: [PATCH 11/11] fix lint Signed-off-by: odubajDT --- receiver/zipkinreceiver/factory_test.go | 3 ++- receiver/zipkinreceiver/go.mod | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/receiver/zipkinreceiver/factory_test.go b/receiver/zipkinreceiver/factory_test.go index 593d848c3438..94a920c0b9f0 100644 --- a/receiver/zipkinreceiver/factory_test.go +++ b/receiver/zipkinreceiver/factory_test.go @@ -8,7 +8,6 @@ import ( "context" "testing" - "github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/testutil" "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/config/confighttp" @@ -16,6 +15,8 @@ import ( "go.opentelemetry.io/collector/receiver/receivertest" "go.uber.org/zap" "go.uber.org/zap/zapcore" + + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/testutil" ) func TestCreateDefaultConfig(t *testing.T) { diff --git a/receiver/zipkinreceiver/go.mod b/receiver/zipkinreceiver/go.mod index 3102ede83abe..afa935527813 100644 --- a/receiver/zipkinreceiver/go.mod +++ b/receiver/zipkinreceiver/go.mod @@ -22,6 +22,7 @@ require ( go.opentelemetry.io/collector/receiver/receivertest v0.113.0 go.opentelemetry.io/collector/semconv v0.113.0 go.uber.org/goleak v1.3.0 + go.uber.org/zap v1.27.0 google.golang.org/protobuf v1.35.1 ) @@ -69,7 +70,6 @@ require ( go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.27.0 // indirect golang.org/x/net v0.30.0 // indirect golang.org/x/sys v0.26.0 // indirect golang.org/x/text v0.19.0 // indirect