From 6c2051a4e3c7d1669152ee92341ef51e08059c20 Mon Sep 17 00:00:00 2001 From: Antonio Jimenez Date: Wed, 6 Sep 2023 13:53:31 +0200 Subject: [PATCH] Merge master --- ...ponents-command-with-stability-levels.yaml | 25 ++ .../scripts/release-create-tracking-issue.sh | 2 +- CHANGELOG-API.md | 19 ++ CHANGELOG.md | 13 + CONTRIBUTING.md | 44 +++ cmd/builder/internal/builder/config.go | 2 +- .../internal/builder/templates/go.mod.tmpl | 5 + cmd/builder/internal/config/default.yaml | 22 +- cmd/builder/test/core.builder.yaml | 8 +- cmd/otelcorecol/builder-config.yaml | 22 +- cmd/otelcorecol/go.mod | 65 +++-- cmd/otelcorecol/go.sum | 15 +- cmd/otelcorecol/main.go | 2 +- component/go.mod | 4 +- config/configauth/README.md | 11 +- config/configauth/go.mod | 10 +- config/configgrpc/README.md | 4 + config/configgrpc/configgrpc.go | 12 +- config/configgrpc/configgrpc_test.go | 18 +- config/configgrpc/go.mod | 32 +-- config/confighttp/README.md | 6 + config/confighttp/confighttp_test.go | 32 ++- config/confighttp/go.mod | 22 +- config/configtls/go.mod | 2 +- connector/forwardconnector/go.mod | 12 +- connector/go.mod | 10 +- consumer/go.mod | 2 +- docs/release.md | 28 +- examples/k8s/otel-config.yaml | 4 +- exporter/exporterhelper/README.md | 3 - exporter/exporterhelper/common.go | 54 ++-- exporter/exporterhelper/common_test.go | 6 +- .../internal/bounded_memory_queue.go | 40 ++- .../internal/bounded_memory_queue_test.go | 49 ++-- .../exporterhelper/internal/mock_storage.go | 93 ++++++ .../internal/persistent_queue.go | 88 ++++-- .../internal/persistent_queue_test.go | 176 ++++++++---- .../internal/persistent_storage.go | 15 +- .../internal/persistent_storage_test.go | 96 +------ .../internal/producer_consumer_queue.go | 22 +- exporter/exporterhelper/logs.go | 28 +- exporter/exporterhelper/logs_test.go | 80 ++++++ exporter/exporterhelper/metrics.go | 28 +- exporter/exporterhelper/metrics_test.go | 79 ++++++ exporter/exporterhelper/queued_retry.go | 146 +++------- exporter/exporterhelper/queued_retry_test.go | 213 +++----------- exporter/exporterhelper/request.go | 4 + exporter/exporterhelper/traces.go | 28 +- exporter/exporterhelper/traces_test.go | 81 ++++++ exporter/go.mod | 17 +- exporter/go.sum | 1 - exporter/loggingexporter/go.mod | 18 +- exporter/otlpexporter/README.md | 2 +- exporter/otlpexporter/config.go | 7 +- exporter/otlpexporter/config_test.go | 3 - exporter/otlpexporter/factory.go | 1 - exporter/otlpexporter/factory_test.go | 26 +- exporter/otlpexporter/go.mod | 34 +-- exporter/otlpexporter/testdata/config.yaml | 2 - exporter/otlphttpexporter/README.md | 3 - exporter/otlphttpexporter/config.go | 7 +- exporter/otlphttpexporter/config_test.go | 3 - exporter/otlphttpexporter/factory.go | 1 - exporter/otlphttpexporter/factory_test.go | 22 +- exporter/otlphttpexporter/go.mod | 38 +-- exporter/otlphttpexporter/go.sum | 2 +- exporter/otlphttpexporter/otlp.go | 29 +- exporter/otlphttpexporter/otlp_test.go | 66 ++++- .../otlphttpexporter/testdata/config.yaml | 2 - extension/auth/go.mod | 8 +- extension/ballastextension/go.mod | 10 +- extension/go.mod | 6 +- extension/zpagesextension/go.mod | 12 +- go.mod | 31 +- go.sum | 16 +- internal/tools/go.mod | 26 +- internal/tools/go.sum | 59 ++-- otelcol/command_components.go | 67 ++++- otelcol/command_components_test.go | 53 +++- processor/batchprocessor/go.mod | 16 +- processor/go.mod | 10 +- processor/memorylimiterprocessor/go.mod | 16 +- receiver/go.mod | 14 +- receiver/otlpreceiver/README.md | 2 + receiver/otlpreceiver/go.mod | 38 +-- service/internal/proctelemetry/config.go | 153 ++++++++-- service/internal/proctelemetry/config_test.go | 264 +++++++++++++++++- service/service_test.go | 2 +- service/telemetry/config.go | 39 ++- service/telemetry/config_test.go | 8 + versions.yaml | 2 +- 91 files changed, 1908 insertions(+), 1010 deletions(-) create mode 100644 .chloggen/components-command-with-stability-levels.yaml create mode 100644 exporter/exporterhelper/internal/mock_storage.go diff --git a/.chloggen/components-command-with-stability-levels.yaml b/.chloggen/components-command-with-stability-levels.yaml new file mode 100644 index 00000000000..f4eb16e601e --- /dev/null +++ b/.chloggen/components-command-with-stability-levels.yaml @@ -0,0 +1,25 @@ +# 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: components command + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: The "components" command now lists the component's stability levels. + +# One or more tracking issues or pull requests related to the change +issues: [8289] + +# (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: Note that the format of this output is NOT stable and can change between versions. + +# 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: [] \ No newline at end of file diff --git a/.github/workflows/scripts/release-create-tracking-issue.sh b/.github/workflows/scripts/release-create-tracking-issue.sh index 1293804bb57..f85db07ce7d 100755 --- a/.github/workflows/scripts/release-create-tracking-issue.sh +++ b/.github/workflows/scripts/release-create-tracking-issue.sh @@ -11,7 +11,7 @@ if [ "${CANDIDATE_BETA}" == "" ]; then RELEASE_VERSION="v${CANDIDATE_STABLE}" fi -EXISTING_ISSUE=$( gh issue list --search "Release ${RELEASE_VERSION}" --json url --jq '.[].url' --repo "${REPO}" ) +EXISTING_ISSUE=$( gh issue list --search "in:title Release ${RELEASE_VERSION}" --json url --jq '.[].url' --repo "${REPO}" --state open --label release ) if [ "${EXISTING_ISSUE}" != "" ]; then echo "Issue already exists: ${EXISTING_ISSUE}" diff --git a/CHANGELOG-API.md b/CHANGELOG-API.md index ec94b835899..a8d78fa8a55 100644 --- a/CHANGELOG-API.md +++ b/CHANGELOG-API.md @@ -7,6 +7,25 @@ If you are looking for user-facing changes, check out [CHANGELOG.md](./CHANGELOG +## v0.84.0 + +### 💡 Enhancements 💡 + +- `exporter/exporterhelper`: Introduce a new exporter helper that operates over client-provided requests instead of pdata (#7874) + The following experimental API is introduced in exporter/exporterhelper package: + - `NewLogsRequestExporter`: a new exporter helper for logs. + - `NewMetricsRequestExporter`: a new exporter helper for metrics. + - `NewTracesRequestExporter`: a new exporter helper for traces. + - `Request`: an interface for client-defined requests. + - `RequestItemsCounter`: an optional interface for counting the number of items in a Request. + - `LogsConverter`: an interface for converting plog.Logs to Request. + - `MetricsConverter`: an interface for converting pmetric.Metrics to Request. + - `TracesConverter`: an interface for converting ptrace.Traces to Request. + All the new APIs are intended to be used by exporters that need to operate over client-provided requests instead of pdata. + +- `otlpreceiver`: Export HTTPConfig as part of the API for creating the otlpreceiver configuration. (#8175) + Changes signature of receiver/otlpreceiver/config.go type httpServerSettings to HTTPConfig. + ## v0.83.0 ### 🛑 Breaking changes 🛑 diff --git a/CHANGELOG.md b/CHANGELOG.md index a3b0c42b2a1..d603e979ff6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,19 @@ If you are looking for developer-facing changes, check out [CHANGELOG-API.md](./ +## v0.84.0 + +### 💡 Enhancements 💡 + +- `loggingexporter`: Adds exemplars logging to the logging exporter when `detailed` verbosity level is set. (#7912) +- `configgrpc`: Allow any registered gRPC load balancer name to be used. (#8262) +- `service`: add OTLP export for internal traces (#8106) +- `configgrpc`: Add support for :authority pseudo-header in grpc client (#8228) + +### 🧰 Bug fixes 🧰 + +- `otlphttpexporter`: Fix the handling of the HTTP response to ignore responses not encoded as protobuf (#8263) + ## v0.83.0 ### 💡 Enhancements 💡 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7e723082cee..b8c2865fbd8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -494,6 +494,50 @@ that each of the following steps is done in a separate version: 1. On `v0.N+2`, we change `func GetFoo() Foo` to `func GetFoo(context.Context) Foo` if desired or remove it entirely if needed. +#### Configuration changes + +##### Alpha components + +Configuration for alpha components can be changed with minimal notice. Documenting them as part of the changelog is +sufficient. We still recommend giving users one or two minor version's notice before breaking the configuration, such as +when removing or renaming a configuration option. Providing a migration path in the component's repository is NOT +required for alpha components, although still recommended. + +- when adding a new configuration option, components MAY mark the new option as required and are not required to provide + a reasonable default. +- when renaming a configuration option, components MAY treat the old name as an alias to the new one and log a WARN + level message in case the old option is being used. +- when removing a configuration option, components MAY keep the old option for a few minor releases and log a WARN level + message instructing users to remove the option. + +##### Beta components + +One of the requirements for a component to be marked as beta is to have its configuration options stabilized. Therefore, +backward incompatible changes should be rare events for beta components. Users of those components are not expecting to +have their Collector instances failing at startup because of a configuration change. When doing backward incompatible +changes, component owners should add the migration path to a place within the component's repository, linked from the +component's main README. This is to ensure that people using older instructions can understand how to migrate to the +latest version of the component. + +When adding a new required option: +- the option MUST come with a sensible default value + +When renaming or removing a configuration option: +- the option MUST be deprecated in one version +- a WARN level message should be logged, with a link to a place within the component's repository where the change is + documented and a migration path is provided +- the option MUST be kept for at least N+1 version, and MAY be hidden behind a feature gate in N+2 +- the option and the WARN level message MAY be removed after N+2 or 6 months, whichever comes later + +Additionally, when removing an option: +- the option MAY be made non operational already by the same version where it is deprecated + +##### Stable components + +Stable component MUST be compatible between minor versions, unless critical security issues are found. In that case, the +component owner MUST provide a migration path and a reasonable time frame for users to upgrade. The same rules from beta +components apply to stable when it comes to configuration changes. + ### Specification Tracking The [OpenTelemetry Specification](https://github.com/open-telemetry/opentelemetry-specification) can be a rapidly diff --git a/cmd/builder/internal/builder/config.go b/cmd/builder/internal/builder/config.go index 32864446be5..9b2b2a84b52 100644 --- a/cmd/builder/internal/builder/config.go +++ b/cmd/builder/internal/builder/config.go @@ -15,7 +15,7 @@ import ( "go.uber.org/zap" ) -const defaultOtelColVersion = "0.83.0" +const defaultOtelColVersion = "0.84.0" // ErrInvalidGoMod indicates an invalid gomod var ErrInvalidGoMod = errors.New("invalid gomod specification for module") diff --git a/cmd/builder/internal/builder/templates/go.mod.tmpl b/cmd/builder/internal/builder/templates/go.mod.tmpl index 5aebc67da17..b134bf4b3cb 100644 --- a/cmd/builder/internal/builder/templates/go.mod.tmpl +++ b/cmd/builder/internal/builder/templates/go.mod.tmpl @@ -23,6 +23,11 @@ require ( go.opentelemetry.io/collector v{{.Distribution.OtelColVersion}} ) +require ( + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect +) + {{- range .Connectors}} {{if ne .Path ""}}replace {{.GoMod}} => {{.Path}}{{end}} {{- end}} diff --git a/cmd/builder/internal/config/default.yaml b/cmd/builder/internal/config/default.yaml index 513e2114793..3426f016d62 100644 --- a/cmd/builder/internal/config/default.yaml +++ b/cmd/builder/internal/config/default.yaml @@ -2,21 +2,21 @@ dist: module: go.opentelemetry.io/collector/cmd/otelcorecol name: otelcorecol description: Local OpenTelemetry Collector binary, testing only. - version: 0.83.0-dev - otelcol_version: 0.83.0 + version: 0.84.0-dev + otelcol_version: 0.84.0 receivers: - - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.83.0 + - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.84.0 exporters: - - gomod: go.opentelemetry.io/collector/exporter/loggingexporter v0.83.0 - - gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.83.0 - - gomod: go.opentelemetry.io/collector/exporter/otlphttpexporter v0.83.0 + - gomod: go.opentelemetry.io/collector/exporter/loggingexporter v0.84.0 + - gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.84.0 + - gomod: go.opentelemetry.io/collector/exporter/otlphttpexporter v0.84.0 extensions: - - gomod: go.opentelemetry.io/collector/extension/ballastextension v0.83.0 - - gomod: go.opentelemetry.io/collector/extension/zpagesextension v0.83.0 + - gomod: go.opentelemetry.io/collector/extension/ballastextension v0.84.0 + - gomod: go.opentelemetry.io/collector/extension/zpagesextension v0.84.0 processors: - - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.83.0 - - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.83.0 + - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.84.0 + - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.84.0 connectors: - - gomod: go.opentelemetry.io/collector/connector/forwardconnector v0.83.0 + - gomod: go.opentelemetry.io/collector/connector/forwardconnector v0.84.0 diff --git a/cmd/builder/test/core.builder.yaml b/cmd/builder/test/core.builder.yaml index c397a464842..74178015c32 100644 --- a/cmd/builder/test/core.builder.yaml +++ b/cmd/builder/test/core.builder.yaml @@ -1,20 +1,20 @@ dist: module: go.opentelemetry.io/collector/builder/test/core - otelcol_version: 0.83.0 + otelcol_version: 0.84.0 extensions: - import: go.opentelemetry.io/collector/extension/zpagesextension - gomod: go.opentelemetry.io/collector v0.83.0 + gomod: go.opentelemetry.io/collector v0.84.0 path: ${WORKSPACE_DIR} receivers: - import: go.opentelemetry.io/collector/receiver/otlpreceiver - gomod: go.opentelemetry.io/collector v0.83.0 + gomod: go.opentelemetry.io/collector v0.84.0 path: ${WORKSPACE_DIR} exporters: - import: go.opentelemetry.io/collector/exporter/loggingexporter - gomod: go.opentelemetry.io/collector v0.83.0 + gomod: go.opentelemetry.io/collector v0.84.0 path: ${WORKSPACE_DIR} replaces: diff --git a/cmd/otelcorecol/builder-config.yaml b/cmd/otelcorecol/builder-config.yaml index cecf2237e6b..52e06757d18 100644 --- a/cmd/otelcorecol/builder-config.yaml +++ b/cmd/otelcorecol/builder-config.yaml @@ -2,23 +2,23 @@ dist: module: go.opentelemetry.io/collector/cmd/otelcorecol name: otelcorecol description: Local OpenTelemetry Collector binary, testing only. - version: 0.83.0-dev - otelcol_version: 0.83.0 + version: 0.84.0-dev + otelcol_version: 0.84.0 receivers: - - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.83.0 + - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.84.0 exporters: - - gomod: go.opentelemetry.io/collector/exporter/loggingexporter v0.83.0 - - gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.83.0 - - gomod: go.opentelemetry.io/collector/exporter/otlphttpexporter v0.83.0 + - gomod: go.opentelemetry.io/collector/exporter/loggingexporter v0.84.0 + - gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.84.0 + - gomod: go.opentelemetry.io/collector/exporter/otlphttpexporter v0.84.0 extensions: - - gomod: go.opentelemetry.io/collector/extension/ballastextension v0.83.0 - - gomod: go.opentelemetry.io/collector/extension/zpagesextension v0.83.0 + - gomod: go.opentelemetry.io/collector/extension/ballastextension v0.84.0 + - gomod: go.opentelemetry.io/collector/extension/zpagesextension v0.84.0 processors: - - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.83.0 - - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.83.0 + - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.84.0 + - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.84.0 connectors: - - gomod: go.opentelemetry.io/collector/connector/forwardconnector v0.83.0 + - gomod: go.opentelemetry.io/collector/connector/forwardconnector v0.84.0 replaces: - go.opentelemetry.io/collector => ../../ diff --git a/cmd/otelcorecol/go.mod b/cmd/otelcorecol/go.mod index ec3550a8f46..816f2479fd6 100644 --- a/cmd/otelcorecol/go.mod +++ b/cmd/otelcorecol/go.mod @@ -6,22 +6,22 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/connector v0.83.0 - go.opentelemetry.io/collector/connector/forwardconnector v0.83.0 - go.opentelemetry.io/collector/exporter v0.83.0 - go.opentelemetry.io/collector/exporter/loggingexporter v0.83.0 - go.opentelemetry.io/collector/exporter/otlpexporter v0.83.0 - go.opentelemetry.io/collector/exporter/otlphttpexporter v0.83.0 - go.opentelemetry.io/collector/extension v0.83.0 - go.opentelemetry.io/collector/extension/ballastextension v0.83.0 - go.opentelemetry.io/collector/extension/zpagesextension v0.83.0 - go.opentelemetry.io/collector/processor v0.83.0 - go.opentelemetry.io/collector/processor/batchprocessor v0.83.0 - go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.83.0 - go.opentelemetry.io/collector/receiver v0.83.0 - go.opentelemetry.io/collector/receiver/otlpreceiver v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/connector v0.84.0 + go.opentelemetry.io/collector/connector/forwardconnector v0.84.0 + go.opentelemetry.io/collector/exporter v0.84.0 + go.opentelemetry.io/collector/exporter/loggingexporter v0.84.0 + go.opentelemetry.io/collector/exporter/otlpexporter v0.84.0 + go.opentelemetry.io/collector/exporter/otlphttpexporter v0.84.0 + go.opentelemetry.io/collector/extension v0.84.0 + go.opentelemetry.io/collector/extension/ballastextension v0.84.0 + go.opentelemetry.io/collector/extension/zpagesextension v0.84.0 + go.opentelemetry.io/collector/processor v0.84.0 + go.opentelemetry.io/collector/processor/batchprocessor v0.84.0 + go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.84.0 + go.opentelemetry.io/collector/receiver v0.84.0 + go.opentelemetry.io/collector/receiver/otlpreceiver v0.84.0 golang.org/x/sys v0.11.0 ) @@ -42,7 +42,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.3.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -74,21 +74,21 @@ require ( github.com/tklauser/numcpus v0.6.0 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/config/configauth v0.83.0 // indirect - go.opentelemetry.io/collector/config/configcompression v0.83.0 // indirect - go.opentelemetry.io/collector/config/configgrpc v0.83.0 // indirect - go.opentelemetry.io/collector/config/confighttp v0.83.0 // indirect - go.opentelemetry.io/collector/config/confignet v0.83.0 // indirect - go.opentelemetry.io/collector/config/configopaque v0.83.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 // indirect - go.opentelemetry.io/collector/config/configtls v0.83.0 // indirect - go.opentelemetry.io/collector/config/internal v0.83.0 // indirect - go.opentelemetry.io/collector/confmap v0.83.0 // indirect - go.opentelemetry.io/collector/consumer v0.83.0 // indirect - go.opentelemetry.io/collector/extension/auth v0.83.0 // indirect + go.opentelemetry.io/collector/config/configauth v0.84.0 // indirect + go.opentelemetry.io/collector/config/configcompression v0.84.0 // indirect + go.opentelemetry.io/collector/config/configgrpc v0.84.0 // indirect + go.opentelemetry.io/collector/config/confighttp v0.84.0 // indirect + go.opentelemetry.io/collector/config/confignet v0.84.0 // indirect + go.opentelemetry.io/collector/config/configopaque v0.84.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect + go.opentelemetry.io/collector/config/configtls v0.84.0 // indirect + go.opentelemetry.io/collector/config/internal v0.84.0 // indirect + go.opentelemetry.io/collector/confmap v0.84.0 // indirect + go.opentelemetry.io/collector/consumer v0.84.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/semconv v0.83.0 // indirect + go.opentelemetry.io/collector/semconv v0.84.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.1-0.20230612162650-64be7e574a17 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.17.0 // indirect @@ -99,6 +99,9 @@ require ( go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.39.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.39.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.39.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0 // indirect go.opentelemetry.io/otel/exporters/prometheus v0.39.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.39.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0 // indirect @@ -111,7 +114,7 @@ require ( go.uber.org/zap v1.25.0 // indirect golang.org/x/net v0.14.0 // indirect golang.org/x/text v0.12.0 // indirect - gonum.org/v1/gonum v0.13.0 // indirect + gonum.org/v1/gonum v0.14.0 // indirect google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect diff --git a/cmd/otelcorecol/go.sum b/cmd/otelcorecol/go.sum index 20259ebadc1..d65a2677cdf 100644 --- a/cmd/otelcorecol/go.sum +++ b/cmd/otelcorecol/go.sum @@ -711,8 +711,9 @@ github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3 github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= @@ -935,6 +936,12 @@ go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.39.0 h1:rm+ go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.39.0/go.mod h1:sWFbI3jJ+6JdjOVepA5blpv/TJ20Hw+26561iMbWcwU= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.39.0 h1:IZXpCEtI7BbX01DRQEWTGDkvjMB6hEhiEZXS+eg2YqY= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.39.0/go.mod h1:xY111jIZtWb+pUUgT4UiiSonAaY2cD2Ts5zvuKLki3o= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 h1:cbsD4cUcviQGXdw8+bo5x2wazq10SKz8hEbtCRPcU78= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0/go.mod h1:JgXSGah17croqhJfhByOLVY719k1emAXC8MVhCIJlRs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 h1:TVQp/bboR4mhZSav+MdgXB8FaRho1RC8UwVn3T0vjVc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0/go.mod h1:I33vtIe0sR96wfrUcilIzLoA3mLHhRmz9S9Te0S3gDo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0 h1:iqjq9LAB8aK++sKVcELezzn655JnBNdsDhghU4G/So8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0/go.mod h1:hGXzO5bhhSHZnKvrDaXB82Y9DRFour0Nz/KrBh7reWw= go.opentelemetry.io/otel/exporters/prometheus v0.39.0 h1:whAaiHxOatgtKd+w0dOi//1KUxj3KoPINZdtDaDj3IA= go.opentelemetry.io/otel/exporters/prometheus v0.39.0/go.mod h1:4jo5Q4CROlCpSPsXLhymi+LYrDXd2ObU5wbKayfZs7Y= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.39.0 h1:fl2WmyenEf6LYYlfHAtCUEDyGcpwJNqD4dHGO7PVm4w= @@ -953,7 +960,7 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= @@ -1224,8 +1231,8 @@ gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJ gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= -gonum.org/v1/gonum v0.13.0 h1:a0T3bh+7fhRyqeNbiC3qVHYmkiQgit3wnNan/2c0HMM= -gonum.org/v1/gonum v0.13.0/go.mod h1:/WPYRckkfWrhWefxyYTfrTtQR0KH4iyHNuzxqXAKyAU= +gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= +gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= diff --git a/cmd/otelcorecol/main.go b/cmd/otelcorecol/main.go index 073e6c61932..e8c326be4b3 100644 --- a/cmd/otelcorecol/main.go +++ b/cmd/otelcorecol/main.go @@ -19,7 +19,7 @@ func main() { info := component.BuildInfo{ Command: "otelcorecol", Description: "Local OpenTelemetry Collector binary, testing only.", - Version: "0.83.0-dev", + Version: "0.84.0-dev", } if err := run(otelcol.CollectorSettings{BuildInfo: info, Factories: factories}); err != nil { diff --git a/component/go.mod b/component/go.mod index 581bfbeed8f..06358b1a1d6 100644 --- a/component/go.mod +++ b/component/go.mod @@ -4,8 +4,8 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 - go.opentelemetry.io/collector/confmap v0.83.0 + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 + go.opentelemetry.io/collector/confmap v0.84.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 go.opentelemetry.io/otel/metric v1.16.0 go.opentelemetry.io/otel/trace v1.16.0 diff --git a/config/configauth/README.md b/config/configauth/README.md index 86f36bde07f..4848881f2a7 100644 --- a/config/configauth/README.md +++ b/config/configauth/README.md @@ -8,11 +8,16 @@ This module defines necessary interfaces to implement server and client type aut The currently known authenticators are: - Server Authenticators - - [oidc](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/oidcauthextension) + - [Basic Auth Extension](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/basicauthextension) + - [Bearer Token Extension](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/bearertokenauthextension) + - [OIDC Extension](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/oidcauthextension) - Client Authenticators - - [oauth2](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/oauth2clientauthextension) - - [BearerToken](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/bearertokenauthextension) + - [ASAP Client Authentication Extension](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/asapauthextension) + - [Basic Auth Extension](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/basicauthextension) + - [Bearer Token Extension](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/bearertokenauthextension) + - [OAuth2 Client Extension](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/oauth2clientauthextension) + - [Sigv4 Extension](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/sigv4authextension) Examples: ```yaml diff --git a/config/configauth/go.mod b/config/configauth/go.mod index c0bcd10455a..48473a68847 100644 --- a/config/configauth/go.mod +++ b/config/configauth/go.mod @@ -4,9 +4,9 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/extension v0.83.0 - go.opentelemetry.io/collector/extension/auth v0.83.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/extension v0.84.0 + go.opentelemetry.io/collector/extension/auth v0.84.0 ) require ( @@ -20,8 +20,8 @@ require ( github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 // indirect - go.opentelemetry.io/collector/confmap v0.83.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect + go.opentelemetry.io/collector/confmap v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect go.opentelemetry.io/otel v1.16.0 // indirect diff --git a/config/configgrpc/README.md b/config/configgrpc/README.md index 4ee6f541e67..b9cf2f01be2 100644 --- a/config/configgrpc/README.md +++ b/config/configgrpc/README.md @@ -26,6 +26,7 @@ README](../configtls/README.md). - `timeout` - [`read_buffer_size`](https://godoc.org/google.golang.org/grpc#ReadBufferSize) - [`write_buffer_size`](https://godoc.org/google.golang.org/grpc#WriteBufferSize) +- [`auth`](../configauth/README.md) Please note that [`per_rpc_auth`](https://pkg.go.dev/google.golang.org/grpc#PerRPCCredentials) which allows the credentials to send for every RPC is now moved to become an [extension](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/extension/bearertokenauthextension). Note that this feature isn't about sending the headers only during the initial connection as an `authorization` header under the `headers` would do: this is sent for every RPC performed during an established connection. @@ -35,6 +36,8 @@ Example: exporters: otlp: endpoint: otelcol2:55690 + auth: + authenticator: some-authenticator-extension tls: ca_file: ca.pem cert_file: cert.pem @@ -107,3 +110,4 @@ see [confignet README](../confignet/README.md). - [`read_buffer_size`](https://godoc.org/google.golang.org/grpc#ReadBufferSize) - [`tls`](../configtls/README.md) - [`write_buffer_size`](https://godoc.org/google.golang.org/grpc#WriteBufferSize) +- [`auth`](../configauth/README.md) diff --git a/config/configgrpc/configgrpc.go b/config/configgrpc/configgrpc.go index 7b643b046a3..f6da798f165 100644 --- a/config/configgrpc/configgrpc.go +++ b/config/configgrpc/configgrpc.go @@ -17,7 +17,7 @@ import ( "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "go.opentelemetry.io/otel" "google.golang.org/grpc" - "google.golang.org/grpc/balancer/roundrobin" + "google.golang.org/grpc/balancer" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/encoding/gzip" @@ -38,9 +38,6 @@ import ( var errMetadataNotFound = errors.New("no request metadata found") -// Allowed balancer names to be set in grpclb_policy to discover the servers. -var allowedBalancerNames = []string{roundrobin.Name, grpc.PickFirstBalancerName} - // KeepaliveClientConfig exposes the keepalive.ClientParameters to be used by the exporter. // Refer to the original data-structure for the meaning of each parameter: // https://godoc.org/google.golang.org/grpc/keepalive#ClientParameters @@ -269,12 +266,7 @@ func (gcs *GRPCClientSettings) toDialOptions(host component.Host, settings compo } func validateBalancerName(balancerName string) bool { - for _, item := range allowedBalancerNames { - if item == balancerName { - return true - } - } - return false + return balancer.Get(balancerName) != nil } // ToListener returns the net.Listener constructed from the settings. diff --git a/config/configgrpc/configgrpc_test.go b/config/configgrpc/configgrpc_test.go index 38040261f75..175848a5ebf 100644 --- a/config/configgrpc/configgrpc_test.go +++ b/config/configgrpc/configgrpc_test.go @@ -18,6 +18,7 @@ import ( "go.uber.org/zap" "go.uber.org/zap/zaptest/observer" "google.golang.org/grpc" + "google.golang.org/grpc/balancer" "google.golang.org/grpc/metadata" "google.golang.org/grpc/peer" @@ -35,6 +36,21 @@ import ( "go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp" ) +// testBalancerBuilder facilitates testing validateBalancerName(). +type testBalancerBuilder struct{} + +func (testBalancerBuilder) Build(_ balancer.ClientConn, _ balancer.BuildOptions) balancer.Balancer { + return nil +} + +func (testBalancerBuilder) Name() string { + return "configgrpc_balancer_test" +} + +func init() { + balancer.Register(testBalancerBuilder{}) +} + func TestDefaultGrpcClientSettings(t *testing.T) { tt, err := obsreporttest.SetupTelemetry(component.NewID("component")) require.NoError(t, err) @@ -137,7 +153,7 @@ func TestAllGrpcClientSettings(t *testing.T) { ReadBufferSize: 1024, WriteBufferSize: 1024, WaitForReady: true, - BalancerName: "round_robin", + BalancerName: "configgrpc_balancer_test", Authority: "pseudo-authority", Auth: &configauth.Authentication{AuthenticatorID: component.NewID("testauth")}, }, diff --git a/config/configgrpc/go.mod b/config/configgrpc/go.mod index 5057eeecef8..5a8007b0174 100644 --- a/config/configgrpc/go.mod +++ b/config/configgrpc/go.mod @@ -5,15 +5,15 @@ go 1.20 require ( github.com/mostynb/go-grpc-compression v1.2.0 github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/config/configauth v0.83.0 - go.opentelemetry.io/collector/config/configcompression v0.83.0 - go.opentelemetry.io/collector/config/confignet v0.83.0 - go.opentelemetry.io/collector/config/configopaque v0.83.0 - go.opentelemetry.io/collector/config/configtls v0.83.0 - go.opentelemetry.io/collector/config/internal v0.83.0 - go.opentelemetry.io/collector/extension/auth v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/config/configauth v0.84.0 + go.opentelemetry.io/collector/config/configcompression v0.84.0 + go.opentelemetry.io/collector/config/confignet v0.84.0 + go.opentelemetry.io/collector/config/configopaque v0.84.0 + go.opentelemetry.io/collector/config/configtls v0.84.0 + go.opentelemetry.io/collector/config/internal v0.84.0 + go.opentelemetry.io/collector/extension/auth v0.84.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.1-0.20230612162650-64be7e574a17 go.opentelemetry.io/otel v1.16.0 @@ -54,14 +54,14 @@ require ( github.com/prometheus/procfs v0.10.1 // indirect github.com/prometheus/statsd_exporter v0.22.7 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 // indirect - go.opentelemetry.io/collector/confmap v0.83.0 // indirect - go.opentelemetry.io/collector/consumer v0.83.0 // indirect - go.opentelemetry.io/collector/exporter v0.83.0 // indirect - go.opentelemetry.io/collector/extension v0.83.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect + go.opentelemetry.io/collector/confmap v0.84.0 // indirect + go.opentelemetry.io/collector/consumer v0.84.0 // indirect + go.opentelemetry.io/collector/exporter v0.84.0 // indirect + go.opentelemetry.io/collector/extension v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/processor v0.83.0 // indirect - go.opentelemetry.io/collector/receiver v0.83.0 // indirect + go.opentelemetry.io/collector/processor v0.84.0 // indirect + go.opentelemetry.io/collector/receiver v0.84.0 // indirect go.opentelemetry.io/otel/exporters/prometheus v0.39.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect go.opentelemetry.io/otel/sdk v1.16.0 // indirect diff --git a/config/confighttp/README.md b/config/confighttp/README.md index 996a10c47b7..ea1881a7402 100644 --- a/config/confighttp/README.md +++ b/config/confighttp/README.md @@ -27,6 +27,7 @@ README](../configtls/README.md). - [`max_idle_conns_per_host`](https://golang.org/pkg/net/http/#Transport) - [`max_conns_per_host`](https://golang.org/pkg/net/http/#Transport) - [`idle_conn_timeout`](https://golang.org/pkg/net/http/#Transport) +- [`auth`](../configauth/README.md) Example: @@ -34,6 +35,8 @@ Example: exporter: otlp: endpoint: otelcol2:55690 + auth: + authenticator: some-authenticator-extension tls: ca_file: ca.pem cert_file: cert.pem @@ -66,6 +69,7 @@ will not be enabled. not set, browsers use a default of 5 seconds. - `endpoint`: Valid value syntax available [here](https://github.com/grpc/grpc/blob/master/doc/naming.md) - [`tls`](../configtls/README.md) +- [`auth`](../configauth/README.md) You can enable [`attribute processor`][attribute-processor] to append any http header to span's attribute using custom key. You also need to enable the "include_metadata" @@ -77,6 +81,8 @@ receivers: protocols: http: include_metadata: true + auth: + authenticator: some-authenticator-extension cors: allowed_origins: - https://foo.bar.com diff --git a/config/confighttp/confighttp_test.go b/config/confighttp/confighttp_test.go index a5460fe6b56..2110c2c816d 100644 --- a/config/confighttp/confighttp_test.go +++ b/config/confighttp/confighttp_test.go @@ -661,7 +661,7 @@ func TestHttpCors(t *testing.T) { tests := []struct { name string - CORSSettings + *CORSSettings allowedWorks bool disallowedWorks bool @@ -673,9 +673,16 @@ func TestHttpCors(t *testing.T) { disallowedWorks: false, extraHeaderWorks: false, }, + { + name: "emptyCORS", + CORSSettings: &CORSSettings{}, + allowedWorks: false, + disallowedWorks: false, + extraHeaderWorks: false, + }, { name: "OriginCORS", - CORSSettings: CORSSettings{ + CORSSettings: &CORSSettings{ AllowedOrigins: []string{"allowed-*.com"}, }, allowedWorks: true, @@ -684,7 +691,7 @@ func TestHttpCors(t *testing.T) { }, { name: "CacheableCORS", - CORSSettings: CORSSettings{ + CORSSettings: &CORSSettings{ AllowedOrigins: []string{"allowed-*.com"}, MaxAge: 360, }, @@ -694,7 +701,7 @@ func TestHttpCors(t *testing.T) { }, { name: "HeaderCORS", - CORSSettings: CORSSettings{ + CORSSettings: &CORSSettings{ AllowedOrigins: []string{"allowed-*.com"}, AllowedHeaders: []string{"ExtraHeader"}, }, @@ -708,7 +715,7 @@ func TestHttpCors(t *testing.T) { t.Run(tt.name, func(t *testing.T) { hss := &HTTPServerSettings{ Endpoint: "localhost:0", - CORS: &tt.CORSSettings, + CORS: tt.CORSSettings, } ln, err := hss.ToListener() @@ -733,17 +740,18 @@ func TestHttpCors(t *testing.T) { url := fmt.Sprintf("http://%s", ln.Addr().String()) expectedStatus := http.StatusNoContent - if len(tt.AllowedOrigins) == 0 { + if tt.CORSSettings == nil || len(tt.AllowedOrigins) == 0 { expectedStatus = http.StatusOK } + // Verify allowed domain gets responses that allow CORS. - verifyCorsResp(t, url, "allowed-origin.com", tt.MaxAge, false, expectedStatus, tt.allowedWorks) + verifyCorsResp(t, url, "allowed-origin.com", tt.CORSSettings, false, expectedStatus, tt.allowedWorks) // Verify allowed domain and extra headers gets responses that allow CORS. - verifyCorsResp(t, url, "allowed-origin.com", tt.MaxAge, true, expectedStatus, tt.extraHeaderWorks) + verifyCorsResp(t, url, "allowed-origin.com", tt.CORSSettings, true, expectedStatus, tt.extraHeaderWorks) // Verify disallowed domain gets responses that disallow CORS. - verifyCorsResp(t, url, "disallowed-origin.com", tt.MaxAge, false, expectedStatus, tt.disallowedWorks) + verifyCorsResp(t, url, "disallowed-origin.com", tt.CORSSettings, false, expectedStatus, tt.disallowedWorks) require.NoError(t, s.Close()) }) @@ -859,7 +867,7 @@ func TestHttpServerHeaders(t *testing.T) { } } -func verifyCorsResp(t *testing.T, url string, origin string, maxAge int, extraHeader bool, wantStatus int, wantAllowed bool) { +func verifyCorsResp(t *testing.T, url string, origin string, set *CORSSettings, extraHeader bool, wantStatus int, wantAllowed bool) { req, err := http.NewRequest(http.MethodOptions, url, nil) require.NoError(t, err, "Error creating trace OPTIONS request: %v", err) req.Header.Set("Origin", origin) @@ -888,8 +896,8 @@ func verifyCorsResp(t *testing.T, url string, origin string, maxAge int, extraHe if wantAllowed { wantAllowOrigin = origin wantAllowMethods = "POST" - if maxAge != 0 { - wantMaxAge = fmt.Sprintf("%d", maxAge) + if set != nil && set.MaxAge != 0 { + wantMaxAge = fmt.Sprintf("%d", set.MaxAge) } } assert.Equal(t, wantAllowOrigin, gotAllowOrigin) diff --git a/config/confighttp/go.mod b/config/confighttp/go.mod index 7234011f142..74338754571 100644 --- a/config/confighttp/go.mod +++ b/config/confighttp/go.mod @@ -7,15 +7,15 @@ require ( github.com/klauspost/compress v1.16.7 github.com/rs/cors v1.9.0 github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/config/configauth v0.83.0 - go.opentelemetry.io/collector/config/configcompression v0.83.0 - go.opentelemetry.io/collector/config/configopaque v0.83.0 - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 - go.opentelemetry.io/collector/config/configtls v0.83.0 - go.opentelemetry.io/collector/config/internal v0.83.0 - go.opentelemetry.io/collector/extension/auth v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/config/configauth v0.84.0 + go.opentelemetry.io/collector/config/configcompression v0.84.0 + go.opentelemetry.io/collector/config/configopaque v0.84.0 + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 + go.opentelemetry.io/collector/config/configtls v0.84.0 + go.opentelemetry.io/collector/config/internal v0.84.0 + go.opentelemetry.io/collector/extension/auth v0.84.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 go.opentelemetry.io/otel v1.16.0 go.uber.org/zap v1.25.0 @@ -37,8 +37,8 @@ require ( github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/collector/confmap v0.83.0 // indirect - go.opentelemetry.io/collector/extension v0.83.0 // indirect + go.opentelemetry.io/collector/confmap v0.84.0 // indirect + go.opentelemetry.io/collector/extension v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect diff --git a/config/configtls/go.mod b/config/configtls/go.mod index d178eec404a..c4122dc2641 100644 --- a/config/configtls/go.mod +++ b/config/configtls/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/fsnotify/fsnotify v1.6.0 github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/config/configopaque v0.83.0 + go.opentelemetry.io/collector/config/configopaque v0.84.0 ) require ( diff --git a/connector/forwardconnector/go.mod b/connector/forwardconnector/go.mod index a646f9371bc..034f8893b1c 100644 --- a/connector/forwardconnector/go.mod +++ b/connector/forwardconnector/go.mod @@ -4,9 +4,9 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/connector v0.83.0 - go.opentelemetry.io/collector/consumer v0.83.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/connector v0.84.0 + go.opentelemetry.io/collector/consumer v0.84.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 ) @@ -24,9 +24,9 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/collector v0.83.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 // indirect - go.opentelemetry.io/collector/confmap v0.83.0 // indirect + go.opentelemetry.io/collector v0.84.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect + go.opentelemetry.io/collector/confmap v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect go.opentelemetry.io/otel v1.16.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect diff --git a/connector/go.mod b/connector/go.mod index 3652ca01c63..fc7f100a3fd 100644 --- a/connector/go.mod +++ b/connector/go.mod @@ -4,9 +4,9 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/consumer v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/consumer v0.84.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 go.uber.org/zap v1.25.0 ) @@ -25,8 +25,8 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 // indirect - go.opentelemetry.io/collector/confmap v0.83.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect + go.opentelemetry.io/collector/confmap v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect go.opentelemetry.io/otel v1.16.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect diff --git a/consumer/go.mod b/consumer/go.mod index 430de4132e6..0d3fd5606e1 100644 --- a/consumer/go.mod +++ b/consumer/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.83.0 + go.opentelemetry.io/collector v0.84.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 ) diff --git a/docs/release.md b/docs/release.md index ae37752973f..29cd0735777 100644 --- a/docs/release.md +++ b/docs/release.md @@ -25,18 +25,18 @@ It is possible that a core approver isn't a contrib approver. In that case, the ## Releasing opentelemetry-collector -1. Determine the version number that will be assigned to the release. During the beta phase, we increment the minor version number and set the patch number to 0. In this document, we are using `v0.55.0` as the version to be released, following `v0.54.0`. - Check if stable modules have any changes since the last release by running `make check-changes PREVIOUS_VERSION=v1.0.0-rc9 MODSET=stable`. If there are no changes, there is no need to release new version for stable modules. +1. Update Contrib to use the latest in development version of Core. Run `make update-otel` in Contrib root directory and if it results in any changes submit a draft PR to Contrib. Ensure the CI passes before proceeding. This is to ensure that the latest core does not break contrib in any way. We’ll update it once more to the final release number later. -2. Manually run the action [Automation - Prepare Release](https://github.com/open-telemetry/opentelemetry-collector/actions/workflows/prepare-release.yml). This action will create an issue to track the progress of the release and a pull request to update the changelog and version numbers in the repo. **While this PR is open all merging in Core should be haulted**. +2. Determine the version number that will be assigned to the release. During the beta phase, we increment the minor version number and set the patch number to 0. In this document, we are using `v0.85.0` as the version to be released, following `v0.54.0`. + Check if stable modules have any changes since the last release by running `make check-changes PREVIOUS_VERSION=v1.0.0-rcv0014 MODSET=stable`. If there are no changes, there is no need to release new version for stable modules. + +3. Manually run the action [Automation - Prepare Release](https://github.com/open-telemetry/opentelemetry-collector/actions/workflows/prepare-release.yml). This action will create an issue to track the progress of the release and a pull request to update the changelog and version numbers in the repo. **While this PR is open all merging in Core should be haulted**. - When prompted, enter the version numbers determined in Step 1, but do not include a leading `v`. - If not intending to release stable modeles, do not specify a version for `Release candidate version stable`. - If the PR needs updated in any way you can make the changes in a fork and PR those changes into the `prepare-release-prs/x` branch. You do not need to wait for the CI to pass in this prep-to-prep PR. - 🛑 **Do not move forward until this PR is merged.** 🛑 -3. Update Contrib to use the latest in development version of Core. Run `make update-otel` in Contrib root directory and if it results in any changes submit a PR to Contrib with the changes as draft. This is to ensure that the latest core does not break contrib in any way. We’ll update it once more to the final release number later. - -4. Check out the commit created by merging the PR created by `Automation - Prepare Release` (e.g. `prepare-release-prs/0.55.0`) and create a branch named `release/` (e.g. `release/v0.55.x`). Push the new branch to `open-telemetry/opentelemetry-collector`. +4. Check out the commit created by merging the PR created by `Automation - Prepare Release` (e.g. `prepare-release-prs/0.85.0`) and create a branch named `release/` (e.g. `release/v0.85.x`). Push the new branch to `open-telemetry/opentelemetry-collector`. 5. Make sure you are on `release/`. Tag the module groups with the new release version by running: - `make push-tags MODSET=beta` for beta modules group, @@ -46,10 +46,10 @@ It is possible that a core approver isn't a contrib approver. In that case, the 6. The release script for the collector builder should create a new GitHub release for the builder. This is a separate release from the core, but we might join them in the future if it makes sense. -7. A new `v0.55.0` release should be automatically created on Github by now. Edit it and use the contents from the CHANGELOG.md as the release's description. +7. A new `v0.85.0` release should be automatically created on Github by now. Edit it and use the contents from the CHANGELOG.md and CHANGELOG-API.md as the release's description. 8. If you created a draft PR to Contrib in step 3, update the PR to use the newly released Core version and set it to Ready for Review. - - Run `make update-otel OTEL_VERSION=v0.55.0 OTEL_RC_VERSION=1.0.0-rcv0014` + - Run `make update-otel OTEL_VERSION=v0.85.0 OTEL_RC_VERSION=v1.0.0-rcv0014` - Manually update `cmd/otelcontribcol/builder-config.yaml` - Manually update `cmd/oteltestbedcol/builder-config.yaml` - Run `make genotelcontribcol` @@ -62,11 +62,11 @@ It is possible that a core approver isn't a contrib approver. In that case, the - If the PR needs updated in any way you can make the changes in a fork and PR those changes into the `prepare-release-prs/x` branch. You do not need to wait for the CI to pass in this prep-to-prep PR. - 🛑 **Do not move forward until this PR is merged.** 🛑 -2. Check out the commit created by merging the PR created by `Automation - Prepare Release` (e.g. `prepare-release-prs/0.55.0`) and create a branch named `release/` (e.g. `release/v0.55.x`). Push the new branch to `open-telemetry/opentelemetry-collector-contrib`. +2. Check out the commit created by merging the PR created by `Automation - Prepare Release` (e.g. `prepare-release-prs/0.85.0`) and create a branch named `release/` (e.g. `release/v0.85.x`). Push the new branch to `open-telemetry/opentelemetry-collector-contrib`. 3. Make sure you are on `release/`. Tag all the module groups (`contrib-base`) with the new release version by running the `make push-tags MODSET=contrib-base` command. If you set your remote using `https` you need to include `REMOTE=https://github.com/open-telemetry/opentelemetry-collector-contrib.git` in each command. Wait for the new tag build to pass successfully. -4. A new `v0.55.0` release should be automatically created on Github by now. Edit it and use the contents from the CHANGELOG.md as the release's description. +4. A new `v0.85.0` release should be automatically created on Github by now. Edit it and use the contents from the CHANGELOG.md as the release's description. ## Producing the artifacts @@ -79,7 +79,7 @@ The last step of the release process creates artifacts for the new version of th 3. Create a pull request with the change and ensure the build completes successfully. See [example](https://github.com/open-telemetry/opentelemetry-collector-releases/pull/71). - 🛑 **Do not move forward until this PR is merged.** 🛑 -4. Check out the commit created by merging the PR and tag with the new release version by running the `make push-tags TAG=v0.55.0` command. If you set your remote using `https` you need to include `REMOTE=https://github.com/open-telemetry/opentelemetry-collector-releases.git` in each command. Wait for the new tag build to pass successfully. +4. Check out the commit created by merging the PR and tag with the new release version by running the `make push-tags TAG=v0.85.0` command. If you set your remote using `https` you need to include `REMOTE=https://github.com/open-telemetry/opentelemetry-collector-releases.git` in each command. Wait for the new tag build to pass successfully. 5. Ensure the "Release" action passes, this will @@ -89,7 +89,7 @@ The last step of the release process creates artifacts for the new version of th ## Troubleshooting -1. `unknown revision internal/coreinternal/v0.55.0` -- This is typically an indication that there's a dependency on a new module. You can fix it by adding a new `replaces` entry to the `go.mod` for the affected module. +1. `unknown revision internal/coreinternal/v0.85.0` -- This is typically an indication that there's a dependency on a new module. You can fix it by adding a new `replaces` entry to the `go.mod` for the affected module. 2. `commitChangesToNewBranch failed: invalid merge` -- This is a [known issue](https://github.com/open-telemetry/opentelemetry-go-build-tools/issues/47) with our release tooling. The current workaround is to clone a fresh copy of the repository and try again. Note that you may need to set up a `fork` remote pointing to your own fork for the release tooling to work properly. 3. `could not run Go Mod Tidy: go mod tidy failed` when running `multimod` -- This is a [known issue](https://github.com/open-telemetry/opentelemetry-go-build-tools/issues/46) with our release tooling. The current workaround is to run `make gotidy` manually after the multimod tool fails and commit the result. 4. `Incorrect version "X" of "go.opentelemetry.io/collector/component" is included in "X"` in CI after `make update-otel` -- It could be because the make target was run too soon after updating Core and the goproxy hasn't updated yet. Try running `export GOPROXY=direct` and then `make update-otel`. @@ -136,7 +136,7 @@ The following documents the procedure to release a bugfix 2. Create a pull request to update version number against the `release/` branch. 3. Once those changes have been merged, create a pull request to the `main` branch from the `release/` branch. 4. Enable the **Merge pull request** setting in the repository's **Settings** tab. -5. Tag all the modules with the new release version by running the `make add-tag` command (e.g. `make add-tag TAG=v0.55.0`). Push them to `open-telemetry/opentelemetry-collector` with `make push-tag TAG=v0.55.0`. Wait for the new tag build to pass successfully. +5. Tag all the modules with the new release version by running the `make add-tag` command (e.g. `make add-tag TAG=v0.85.0`). Push them to `open-telemetry/opentelemetry-collector` with `make push-tag TAG=v0.85.0`. Wait for the new tag build to pass successfully. 6. **IMPORTANT**: The pull request to bring the changes from the release branch *MUST* be merged using the **Merge pull request** method, and *NOT* squashed using “**Squash and merge**”. This is important as it allows us to ensure the commit SHA from the release branch is also on the main branch. **Not following this step will cause much go dependency sadness.** 7. Once the branch has been merged, it will be auto-deleted. Restore the release branch via GitHub. 8. Once the patch is release, disable the **Merge pull request** setting. @@ -145,10 +145,10 @@ The following documents the procedure to release a bugfix | Date | Version | Release manager | |------------|---------|-----------------| -| 2023-08-28 | v0.84.0 | @dmitryax | | 2023-09-11 | v0.85.0 | @codeboten | | 2023-09-25 | v0.86.0 | @bogdandrutu | | 2023-10-09 | v0.87.0 | @Aneurysm9 | | 2023-10-23 | v0.88.0 | @mx-psi | | 2023-11-06 | v0.89.0 | @jpkrohling | | 2023-11-20 | v0.90.0 | @djaglowski | +| 2023-12-04 | v0.84.0 | @dmitryax | \ No newline at end of file diff --git a/examples/k8s/otel-config.yaml b/examples/k8s/otel-config.yaml index a140794dc3a..162d12e19b6 100644 --- a/examples/k8s/otel-config.yaml +++ b/examples/k8s/otel-config.yaml @@ -68,7 +68,7 @@ spec: - command: - "/otelcol" - "--config=/conf/otel-agent-config.yaml" - image: otel/opentelemetry-collector:0.83.0 + image: otel/opentelemetry-collector:0.84.0 name: otel-agent resources: limits: @@ -187,7 +187,7 @@ spec: - command: - "/otelcol" - "--config=/conf/otel-collector-config.yaml" - image: otel/opentelemetry-collector:0.83.0 + image: otel/opentelemetry-collector:0.84.0 name: otel-collector resources: limits: diff --git a/exporter/exporterhelper/README.md b/exporter/exporterhelper/README.md index 5eb598addd2..ccbb7ac0096 100644 --- a/exporter/exporterhelper/README.md +++ b/exporter/exporterhelper/README.md @@ -24,9 +24,6 @@ The following configuration options can be modified: [the batch processor](https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor/batchprocessor) is used, the metric `batch_send_size` can be used for estimation) - `timeout` (default = 5s): Time to wait per individual attempt to send data to a backend -- `sampled_logger`: The logger sampler configuration. It caps the CPU and I/O load of logging while keeping a representative subset of your logs. - - `enabled` (default = true). Enables/disables sampling of logging messages. - When setting `debug` log level the sampling will be disabled regardless of the value of this property. The `initial_interval`, `max_interval`, `max_elapsed_time`, and `timeout` options accept [duration strings](https://pkg.go.dev/time#ParseDuration), diff --git a/exporter/exporterhelper/common.go b/exporter/exporterhelper/common.go index 201331f83cb..3dfe4c41311 100644 --- a/exporter/exporterhelper/common.go +++ b/exporter/exporterhelper/common.go @@ -27,19 +27,6 @@ func NewDefaultTimeoutSettings() TimeoutSettings { } } -// SampledLoggerSettings configures the logger sampler. -type SampledLoggerSettings struct { - // Enabled enables/disables the sampledLogger. When setting `debug` log level the sampling will be disabled regardless of the value of this property. - Enabled bool `mapstructure:"enabled"` -} - -// NewDefaultSampledLoggerSettings returns the default settings for SampledLoggerSettings. -func NewDefaultSampledLoggerSettings() SampledLoggerSettings { - return SampledLoggerSettings{ - Enabled: true, - } -} - // requestSender is an abstraction of a sender for a request independent of the type of the data (traces, metrics, logs). type requestSender interface { send(req internal.Request) error @@ -69,41 +56,31 @@ func (req *baseRequest) OnProcessingFinished() { } } -type queueSettings struct { - config QueueSettings - marshaler internal.RequestMarshaler - unmarshaler internal.RequestUnmarshaler -} - -func (qs *queueSettings) persistenceEnabled() bool { - return qs.config.StorageID != nil && qs.marshaler != nil && qs.unmarshaler != nil -} - // baseSettings represents all the options that users can configure. type baseSettings struct { component.StartFunc component.ShutdownFunc consumerOptions []consumer.Option TimeoutSettings - queueSettings + queue internal.ProducerConsumerQueue RetrySettings - SampledLoggerSettings requestExporter bool + marshaler internal.RequestMarshaler + unmarshaler internal.RequestUnmarshaler } // newBaseSettings returns the baseSettings starting from the default and applying all configured options. // requestExporter indicates whether the base settings are for a new request exporter or not. -func newBaseSettings(requestExporter bool, options ...Option) *baseSettings { +// TODO: The first three arguments will be removed when the old exporter helpers will be updated to call the new ones. +func newBaseSettings(requestExporter bool, marshaler internal.RequestMarshaler, + unmarshaler internal.RequestUnmarshaler, options ...Option) *baseSettings { bs := &baseSettings{ requestExporter: requestExporter, TimeoutSettings: NewDefaultTimeoutSettings(), - // TODO: Enable queuing by default (call DefaultQueueSettings) - queueSettings: queueSettings{ - config: QueueSettings{Enabled: false}, - }, // TODO: Enable retry by default (call DefaultRetrySettings) - RetrySettings: RetrySettings{Enabled: false}, - SampledLoggerSettings: NewDefaultSampledLoggerSettings(), + RetrySettings: RetrySettings{Enabled: false}, + marshaler: marshaler, + unmarshaler: unmarshaler, } for _, op := range options { @@ -156,7 +133,14 @@ func WithQueue(config QueueSettings) Option { if o.requestExporter { panic("queueing is not available for the new request exporters yet") } - o.queueSettings.config = config + if !config.Enabled { + return + } + if config.StorageID == nil { + o.queue = internal.NewBoundedMemoryQueue(config.QueueSize, config.NumConsumers) + return + } + o.queue = internal.NewPersistentQueue(config.QueueSize, config.NumConsumers, *config.StorageID, o.marshaler, o.unmarshaler) } } @@ -187,7 +171,7 @@ func newBaseExporter(set exporter.CreateSettings, bs *baseSettings, signal compo return nil, err } - be.qrSender = newQueuedRetrySender(set.ID, signal, bs.queueSettings, bs.RetrySettings, bs.SampledLoggerSettings, &timeoutSender{cfg: bs.TimeoutSettings}, set.Logger) + be.qrSender = newQueuedRetrySender(set.ID, signal, bs.queue, bs.RetrySettings, &timeoutSender{cfg: bs.TimeoutSettings}, set.Logger) be.sender = be.qrSender be.StartFunc = func(ctx context.Context, host component.Host) error { // First start the wrapped exporter. @@ -196,7 +180,7 @@ func newBaseExporter(set exporter.CreateSettings, bs *baseSettings, signal compo } // If no error then start the queuedRetrySender. - return be.qrSender.start(ctx, host) + return be.qrSender.start(ctx, host, set) } be.ShutdownFunc = func(ctx context.Context) error { // First shutdown the queued retry sender diff --git a/exporter/exporterhelper/common_test.go b/exporter/exporterhelper/common_test.go index 9c5bcbe2513..076cd55b00e 100644 --- a/exporter/exporterhelper/common_test.go +++ b/exporter/exporterhelper/common_test.go @@ -32,11 +32,11 @@ var ( ) func TestBaseExporter(t *testing.T) { - be, err := newBaseExporter(defaultSettings, newBaseSettings(false), "") + be, err := newBaseExporter(defaultSettings, newBaseSettings(false, nil, nil), "") require.NoError(t, err) require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) require.NoError(t, be.Shutdown(context.Background())) - be, err = newBaseExporter(defaultSettings, newBaseSettings(true), "") + be, err = newBaseExporter(defaultSettings, newBaseSettings(true, nil, nil), "") require.NoError(t, err) require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) require.NoError(t, be.Shutdown(context.Background())) @@ -47,7 +47,7 @@ func TestBaseExporterWithOptions(t *testing.T) { be, err := newBaseExporter( defaultSettings, newBaseSettings( - false, + false, nil, nil, WithStart(func(ctx context.Context, host component.Host) error { return want }), WithShutdown(func(ctx context.Context) error { return want }), WithTimeout(NewDefaultTimeoutSettings())), diff --git a/exporter/exporterhelper/internal/bounded_memory_queue.go b/exporter/exporterhelper/internal/bounded_memory_queue.go index 7425cd8548e..c7f8655338a 100644 --- a/exporter/exporterhelper/internal/bounded_memory_queue.go +++ b/exporter/exporterhelper/internal/bounded_memory_queue.go @@ -6,37 +6,42 @@ package internal // import "go.opentelemetry.io/collector/exporter/exporterhelper/internal" import ( + "context" "sync" "sync/atomic" + + "go.opentelemetry.io/collector/component" ) // boundedMemoryQueue implements a producer-consumer exchange similar to a ring buffer queue, // where the queue is bounded and if it fills up due to slow consumers, the new items written by // the producer are dropped. type boundedMemoryQueue struct { - stopWG sync.WaitGroup - size *atomic.Uint32 - stopped *atomic.Bool - items chan Request - capacity uint32 + stopWG sync.WaitGroup + size *atomic.Uint32 + stopped *atomic.Bool + items chan Request + capacity uint32 + numConsumers int } // NewBoundedMemoryQueue constructs the new queue of specified capacity, and with an optional // callback for dropped items (e.g. useful to emit metrics). -func NewBoundedMemoryQueue(capacity int) ProducerConsumerQueue { +func NewBoundedMemoryQueue(capacity int, numConsumers int) ProducerConsumerQueue { return &boundedMemoryQueue{ - items: make(chan Request, capacity), - stopped: &atomic.Bool{}, - size: &atomic.Uint32{}, - capacity: uint32(capacity), + items: make(chan Request, capacity), + stopped: &atomic.Bool{}, + size: &atomic.Uint32{}, + capacity: uint32(capacity), + numConsumers: numConsumers, } } // StartConsumers starts a given number of goroutines consuming items from the queue // and passing them into the consumer callback. -func (q *boundedMemoryQueue) StartConsumers(numWorkers int, callback func(item Request)) { +func (q *boundedMemoryQueue) Start(_ context.Context, _ component.Host, set QueueSettings) error { var startWG sync.WaitGroup - for i := 0; i < numWorkers; i++ { + for i := 0; i < q.numConsumers; i++ { q.stopWG.Add(1) startWG.Add(1) go func() { @@ -44,11 +49,12 @@ func (q *boundedMemoryQueue) StartConsumers(numWorkers int, callback func(item R defer q.stopWG.Done() for item := range q.items { q.size.Add(^uint32(0)) - callback(item) + set.Callback(item) } }() } startWG.Wait() + return nil } // Produce is used by the producer to submit new item to the queue. Returns false in case of queue overflow. @@ -87,3 +93,11 @@ func (q *boundedMemoryQueue) Stop() { func (q *boundedMemoryQueue) Size() int { return int(q.size.Load()) } + +func (q *boundedMemoryQueue) Capacity() int { + return int(q.capacity) +} + +func (q *boundedMemoryQueue) IsPersistent() bool { + return false +} diff --git a/exporter/exporterhelper/internal/bounded_memory_queue_test.go b/exporter/exporterhelper/internal/bounded_memory_queue_test.go index 43207104916..9fe809cf2a2 100644 --- a/exporter/exporterhelper/internal/bounded_memory_queue_test.go +++ b/exporter/exporterhelper/internal/bounded_memory_queue_test.go @@ -6,6 +6,7 @@ package internal import ( + "context" "reflect" "sync" "sync/atomic" @@ -14,8 +15,20 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/exporter/exportertest" ) +func newNopQueueSettings(callback func(item Request)) QueueSettings { + return QueueSettings{ + CreateSettings: exportertest.NewNopCreateSettings(), + DataType: component.DataTypeMetrics, + Callback: callback, + } +} + type stringRequest struct { Request str string @@ -29,7 +42,7 @@ func newStringRequest(str string) Request { // We want to test the overflow behavior, so we block the consumer // by holding a startLock before submitting items to the queue. func helper(t *testing.T, startConsumers func(q ProducerConsumerQueue, consumerFn func(item Request))) { - q := NewBoundedMemoryQueue(1) + q := NewBoundedMemoryQueue(1, 1) var startLock sync.Mutex @@ -88,7 +101,7 @@ func helper(t *testing.T, startConsumers func(q ProducerConsumerQueue, consumerF func TestBoundedQueue(t *testing.T) { helper(t, func(q ProducerConsumerQueue, consumerFn func(item Request)) { - q.StartConsumers(1, consumerFn) + assert.NoError(t, q.Start(context.Background(), componenttest.NewNopHost(), newNopQueueSettings(consumerFn))) }) } @@ -99,14 +112,14 @@ func TestBoundedQueue(t *testing.T) { // only after Stop will mean the consumers are still locked while // trying to perform the final consumptions. func TestShutdownWhileNotEmpty(t *testing.T) { - q := NewBoundedMemoryQueue(10) + q := NewBoundedMemoryQueue(10, 1) consumerState := newConsumerState(t) - q.StartConsumers(1, func(item Request) { + assert.NoError(t, q.Start(context.Background(), componenttest.NewNopHost(), newNopQueueSettings(func(item Request) { consumerState.record(item.(stringRequest).str) time.Sleep(1 * time.Second) - }) + }))) q.Produce(newStringRequest("a")) q.Produce(newStringRequest("b")) @@ -183,30 +196,10 @@ func (s *consumerState) assertConsumed(expected map[string]bool) { } func TestZeroSize(t *testing.T) { - q := NewBoundedMemoryQueue(0) + q := NewBoundedMemoryQueue(0, 1) - q.StartConsumers(1, func(item Request) { - }) + err := q.Start(context.Background(), componenttest.NewNopHost(), newNopQueueSettings(func(item Request) {})) + assert.NoError(t, err) assert.False(t, q.Produce(newStringRequest("a"))) // in process } - -func BenchmarkBoundedQueue(b *testing.B) { - q := NewBoundedMemoryQueue(1000) - - q.StartConsumers(10, func(item Request) {}) - - for n := 0; n < b.N; n++ { - q.Produce(newStringRequest("a")) - } -} - -func BenchmarkBoundedQueueWithFactory(b *testing.B) { - q := NewBoundedMemoryQueue(1000) - - q.StartConsumers(10, func(item Request) {}) - - for n := 0; n < b.N; n++ { - q.Produce(newStringRequest("a")) - } -} diff --git a/exporter/exporterhelper/internal/mock_storage.go b/exporter/exporterhelper/internal/mock_storage.go new file mode 100644 index 00000000000..8d45d53ab7b --- /dev/null +++ b/exporter/exporterhelper/internal/mock_storage.go @@ -0,0 +1,93 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package internal // import "go.opentelemetry.io/collector/exporter/exporterhelper/internal" + +import ( + "context" + "errors" + "sync" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/extension/experimental/storage" +) + +type mockStorageExtension struct { + component.StartFunc + component.ShutdownFunc + getClientError error +} + +func (m mockStorageExtension) GetClient(_ context.Context, _ component.Kind, _ component.ID, _ string) (storage.Client, error) { + if m.getClientError != nil { + return nil, m.getClientError + } + return &mockStorageClient{st: map[string][]byte{}}, nil +} + +func NewMockStorageExtension() storage.Extension { + return &mockStorageExtension{} +} + +type mockStorageClient struct { + st map[string][]byte + mux sync.Mutex + closeCounter uint64 +} + +func (m *mockStorageClient) Get(_ context.Context, s string) ([]byte, error) { + m.mux.Lock() + defer m.mux.Unlock() + + val, found := m.st[s] + if !found { + return nil, nil + } + + return val, nil +} + +func (m *mockStorageClient) Set(_ context.Context, s string, bytes []byte) error { + m.mux.Lock() + defer m.mux.Unlock() + + m.st[s] = bytes + return nil +} + +func (m *mockStorageClient) Delete(_ context.Context, s string) error { + m.mux.Lock() + defer m.mux.Unlock() + + delete(m.st, s) + return nil +} + +func (m *mockStorageClient) Close(_ context.Context) error { + m.closeCounter++ + return nil +} + +func (m *mockStorageClient) Batch(_ context.Context, ops ...storage.Operation) error { + m.mux.Lock() + defer m.mux.Unlock() + + for _, op := range ops { + switch op.Type { + case storage.Get: + op.Value = m.st[op.Key] + case storage.Set: + m.st[op.Key] = op.Value + case storage.Delete: + delete(m.st, op.Key) + default: + return errors.New("wrong operation type") + } + } + + return nil +} + +func (m *mockStorageClient) getCloseCount() uint64 { + return m.closeCounter +} diff --git a/exporter/exporterhelper/internal/persistent_queue.go b/exporter/exporterhelper/internal/persistent_queue.go index 63a617daebd..ba1dcc67230 100644 --- a/exporter/exporterhelper/internal/persistent_queue.go +++ b/exporter/exporterhelper/internal/persistent_queue.go @@ -5,28 +5,34 @@ package internal // import "go.opentelemetry.io/collector/exporter/exporterhelpe import ( "context" + "errors" "fmt" "sync" - "go.uber.org/zap" - "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/extension/experimental/storage" ) -// Monkey patching for unit test var ( + // Monkey patching for unit test stopStorage = func(queue *persistentQueue) { queue.storage.stop() } + errNoStorageClient = errors.New("no storage client extension found") + errWrongExtensionType = errors.New("requested extension is not a storage extension") ) // persistentQueue holds the queue backed by file storage type persistentQueue struct { - stopWG sync.WaitGroup - stopOnce sync.Once - stopChan chan struct{} - storage *persistentContiguousStorage + stopWG sync.WaitGroup + stopOnce sync.Once + stopChan chan struct{} + storageID component.ID + storage *persistentContiguousStorage + capacity uint64 + numConsumers int + marshaler RequestMarshaler + unmarshaler RequestUnmarshaler } // buildPersistentStorageName returns a name that is constructed out of queue name and signal type. This is done @@ -35,40 +41,42 @@ func buildPersistentStorageName(name string, signal component.DataType) string { return fmt.Sprintf("%s-%s", name, signal) } -type PersistentQueueSettings struct { - Name string - Signal component.DataType - Capacity uint64 - Logger *zap.Logger - Client storage.Client - Unmarshaler RequestUnmarshaler - Marshaler RequestMarshaler -} - // NewPersistentQueue creates a new queue backed by file storage; name and signal must be a unique combination that identifies the queue storage -func NewPersistentQueue(ctx context.Context, params PersistentQueueSettings) ProducerConsumerQueue { +func NewPersistentQueue(capacity int, numConsumers int, storageID component.ID, marshaler RequestMarshaler, + unmarshaler RequestUnmarshaler) ProducerConsumerQueue { return &persistentQueue{ - stopChan: make(chan struct{}), - storage: newPersistentContiguousStorage(ctx, buildPersistentStorageName(params.Name, params.Signal), params), + capacity: uint64(capacity), + numConsumers: numConsumers, + storageID: storageID, + marshaler: marshaler, + unmarshaler: unmarshaler, + stopChan: make(chan struct{}), } } -// StartConsumers starts the given number of consumers which will be consuming items -func (pq *persistentQueue) StartConsumers(numWorkers int, callback func(item Request)) { - for i := 0; i < numWorkers; i++ { +// Start starts the persistentQueue with the given number of consumers. +func (pq *persistentQueue) Start(ctx context.Context, host component.Host, set QueueSettings) error { + storageClient, err := toStorageClient(ctx, pq.storageID, host, set.ID, set.DataType) + if err != nil { + return err + } + storageName := buildPersistentStorageName(set.ID.Name(), set.DataType) + pq.storage = newPersistentContiguousStorage(ctx, storageName, storageClient, set.Logger, pq.capacity, pq.marshaler, pq.unmarshaler) + for i := 0; i < pq.numConsumers; i++ { pq.stopWG.Add(1) go func() { defer pq.stopWG.Done() for { select { case req := <-pq.storage.get(): - callback(req) + set.Callback(req) case <-pq.stopChan: return } } }() } + return nil } // Produce adds an item to the queue and returns true if it was accepted @@ -91,3 +99,35 @@ func (pq *persistentQueue) Stop() { func (pq *persistentQueue) Size() int { return int(pq.storage.size()) } + +func (pq *persistentQueue) Capacity() int { + return int(pq.capacity) +} + +func (pq *persistentQueue) IsPersistent() bool { + return true +} + +func toStorageClient(ctx context.Context, storageID component.ID, host component.Host, ownerID component.ID, signal component.DataType) (storage.Client, error) { + extension, err := getStorageExtension(host.GetExtensions(), storageID) + if err != nil { + return nil, err + } + + client, err := extension.GetClient(ctx, component.KindExporter, ownerID, string(signal)) + if err != nil { + return nil, err + } + + return client, err +} + +func getStorageExtension(extensions map[component.ID]component.Component, storageID component.ID) (storage.Extension, error) { + if ext, found := extensions[storageID]; found { + if storageExt, ok := ext.(storage.Extension); ok { + return storageExt, nil + } + return nil, errWrongExtensionType + } + return nil, errNoStorageClient +} diff --git a/exporter/exporterhelper/internal/persistent_queue_test.go b/exporter/exporterhelper/internal/persistent_queue_test.go index 8b1ffb7674e..3b282a439bb 100644 --- a/exporter/exporterhelper/internal/persistent_queue_test.go +++ b/exporter/exporterhelper/internal/persistent_queue_test.go @@ -5,56 +5,68 @@ package internal import ( "context" + "errors" "fmt" + "strconv" "sync/atomic" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.uber.org/zap" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/extension/experimental/storage" + "go.opentelemetry.io/collector/extension/extensiontest" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/ptrace" ) -func createTestQueue(extension storage.Extension, capacity int) *persistentQueue { - logger := zap.NewNop() +type mockHost struct { + component.Host + ext map[component.ID]component.Component +} - client, err := extension.GetClient(context.Background(), component.KindReceiver, component.ID{}, "") - if err != nil { - panic(err) - } +func (nh *mockHost) GetExtensions() map[component.ID]component.Component { + return nh.ext +} - wq := NewPersistentQueue(context.Background(), PersistentQueueSettings{ - Name: "foo", - Signal: component.DataTypeTraces, - Capacity: uint64(capacity), - Logger: logger, - Client: client, - Unmarshaler: newFakeTracesRequestUnmarshalerFunc(), - Marshaler: newFakeTracesRequestMarshalerFunc(), - }) - return wq.(*persistentQueue) +// createTestQueue creates and starts a fake queue with the given capacity and number of consumers. +func createTestQueue(t *testing.T, capacity, numConsumers int, callback func(item Request)) ProducerConsumerQueue { + pq := NewPersistentQueue(capacity, numConsumers, component.ID{}, newFakeTracesRequestMarshalerFunc(), + newFakeTracesRequestUnmarshalerFunc()) + host := &mockHost{ext: map[component.ID]component.Component{ + {}: createStorageExtension(t.TempDir()), + }} + err := pq.Start(context.Background(), host, newNopQueueSettings(callback)) + require.NoError(t, err) + t.Cleanup(pq.Stop) + return pq } func TestPersistentQueue_Capacity(t *testing.T) { path := t.TempDir() for i := 0; i < 100; i++ { - ext := createStorageExtension(path) - t.Cleanup(func() { require.NoError(t, ext.Shutdown(context.Background())) }) + pq := NewPersistentQueue(5, 1, component.ID{}, newFakeTracesRequestMarshalerFunc(), + newFakeTracesRequestUnmarshalerFunc()) + host := &mockHost{ext: map[component.ID]component.Component{ + {}: createStorageExtension(path), + }} + err := pq.Start(context.Background(), host, newNopQueueSettings(func(req Request) {})) + require.NoError(t, err) + + // Stop consumer to imitate queue overflow + close(pq.(*persistentQueue).stopChan) + pq.(*persistentQueue).stopWG.Wait() - wq := createTestQueue(ext, 5) - assert.Equal(t, 0, wq.Size()) + assert.Equal(t, 0, pq.Size()) traces := newTraces(1, 10) req := newFakeTracesRequest(traces) for i := 0; i < 10; i++ { - result := wq.Produce(req) + result := pq.Produce(req) if i < 6 { assert.True(t, result) } else { @@ -65,26 +77,20 @@ func TestPersistentQueue_Capacity(t *testing.T) { // so the capacity could be used in full if i == 0 { assert.Eventually(t, func() bool { - return wq.Size() == 0 + return pq.Size() == 0 }, 5*time.Second, 10*time.Millisecond) } } - assert.Equal(t, 5, wq.Size()) + assert.Equal(t, 5, pq.Size()) + stopStorage(pq.(*persistentQueue)) } } func TestPersistentQueue_Close(t *testing.T) { - path := t.TempDir() - - ext := createStorageExtension(path) - t.Cleanup(func() { assert.NoError(t, ext.Shutdown(context.Background())) }) - - wq := createTestQueue(ext, 1001) + wq := createTestQueue(t, 1001, 100, func(item Request) {}) traces := newTraces(1, 10) req := newFakeTracesRequest(traces) - wq.StartConsumers(100, func(item Request) {}) - for i := 0; i < 1000; i++ { wq.Produce(req) } @@ -100,12 +106,7 @@ func TestPersistentQueue_Close(t *testing.T) { // Verify storage closes after queue consumers. If not in this order, successfully consumed items won't be updated in storage func TestPersistentQueue_Close_StorageCloseAfterConsumers(t *testing.T) { - path := t.TempDir() - - ext := createStorageExtension(path) - t.Cleanup(func() { assert.NoError(t, ext.Shutdown(context.Background())) }) - - wq := createTestQueue(ext, 1001) + wq := createTestQueue(t, 1001, 1, func(item Request) {}) traces := newTraces(1, 10) lastRequestProcessedTime := time.Now() @@ -121,8 +122,6 @@ func TestPersistentQueue_Close_StorageCloseAfterConsumers(t *testing.T) { queue.storage.stop() } - wq.StartConsumers(1, func(item Request) {}) - for i := 0; i < 1000; i++ { wq.Produce(req) } @@ -162,19 +161,11 @@ func TestPersistentQueue_ConsumersProducers(t *testing.T) { for _, c := range cases { t.Run(fmt.Sprintf("#messages: %d #consumers: %d", c.numMessagesProduced, c.numConsumers), func(t *testing.T) { - path := t.TempDir() - traces := newTraces(1, 10) req := newFakeTracesRequest(traces) - ext := createStorageExtension(path) - tq := createTestQueue(ext, 1000) - - defer tq.Stop() - t.Cleanup(func() { assert.NoError(t, ext.Shutdown(context.Background())) }) - numMessagesConsumed := &atomic.Int32{} - tq.StartConsumers(c.numConsumers, func(item Request) { + tq := createTestQueue(t, 1000, c.numConsumers, func(item Request) { if item != nil { numMessagesConsumed.Add(int32(1)) } @@ -217,3 +208,90 @@ func newTraces(numTraces int, numSpans int) ptrace.Traces { return traces } + +func TestToStorageClient(t *testing.T) { + getStorageClientError := errors.New("unable to create storage client") + testCases := []struct { + desc string + storage storage.Extension + numStorages int + storageIndex int + expectedError error + getClientError error + }{ + { + desc: "obtain storage extension by name", + numStorages: 2, + storageIndex: 0, + expectedError: nil, + }, + { + desc: "fail on not existing storage extension", + numStorages: 2, + storageIndex: 100, + expectedError: errNoStorageClient, + }, + { + desc: "invalid extension type", + numStorages: 2, + storageIndex: 100, + expectedError: errNoStorageClient, + }, + { + desc: "fail on error getting storage client from extension", + numStorages: 1, + storageIndex: 0, + expectedError: getStorageClientError, + getClientError: getStorageClientError, + }, + } + + for _, tC := range testCases { + t.Run(tC.desc, func(t *testing.T) { + storageID := component.NewIDWithName("file_storage", strconv.Itoa(tC.storageIndex)) + + var extensions = map[component.ID]component.Component{} + for i := 0; i < tC.numStorages; i++ { + extensions[component.NewIDWithName("file_storage", + strconv.Itoa(i))] = &mockStorageExtension{getClientError: tC.getClientError} + } + host := &mockHost{ext: extensions} + ownerID := component.NewID("foo_exporter") + + // execute + client, err := toStorageClient(context.Background(), storageID, host, ownerID, component.DataTypeTraces) + + // verify + if tC.expectedError != nil { + assert.ErrorIs(t, err, tC.expectedError) + assert.Nil(t, client) + } else { + assert.NoError(t, err) + assert.NotNil(t, client) + } + }) + } +} + +func TestInvalidStorageExtensionType(t *testing.T) { + storageID := component.NewIDWithName("extension", "extension") + + // make a test extension + factory := extensiontest.NewNopFactory() + extConfig := factory.CreateDefaultConfig() + settings := extensiontest.NewNopCreateSettings() + extension, err := factory.CreateExtension(context.Background(), settings, extConfig) + assert.NoError(t, err) + var extensions = map[component.ID]component.Component{ + storageID: extension, + } + host := &mockHost{ext: extensions} + ownerID := component.NewID("foo_exporter") + + // execute + client, err := toStorageClient(context.Background(), storageID, host, ownerID, component.DataTypeTraces) + + // we should get an error about the extension type + assert.ErrorIs(t, err, errWrongExtensionType) + assert.Nil(t, client) +} diff --git a/exporter/exporterhelper/internal/persistent_storage.go b/exporter/exporterhelper/internal/persistent_storage.go index cbbcf2e03c5..49f204bbb0d 100644 --- a/exporter/exporterhelper/internal/persistent_storage.go +++ b/exporter/exporterhelper/internal/persistent_storage.go @@ -81,15 +81,16 @@ var ( // newPersistentContiguousStorage creates a new file-storage extension backed queue; // queueName parameter must be a unique value that identifies the queue. -func newPersistentContiguousStorage(ctx context.Context, queueName string, set PersistentQueueSettings) *persistentContiguousStorage { +func newPersistentContiguousStorage(ctx context.Context, queueName string, client storage.Client, + logger *zap.Logger, capacity uint64, marshaler RequestMarshaler, unmarshaler RequestUnmarshaler) *persistentContiguousStorage { pcs := &persistentContiguousStorage{ - logger: set.Logger, - client: set.Client, + logger: logger, + client: client, queueName: queueName, - unmarshaler: set.Unmarshaler, - marshaler: set.Marshaler, - capacity: set.Capacity, - putChan: make(chan struct{}, set.Capacity), + unmarshaler: unmarshaler, + marshaler: marshaler, + capacity: capacity, + putChan: make(chan struct{}, capacity), reqChan: make(chan Request), stopChan: make(chan struct{}), itemsCount: &atomic.Uint64{}, diff --git a/exporter/exporterhelper/internal/persistent_storage_test.go b/exporter/exporterhelper/internal/persistent_storage_test.go index 5d33fc11064..1059279027a 100644 --- a/exporter/exporterhelper/internal/persistent_storage_test.go +++ b/exporter/exporterhelper/internal/persistent_storage_test.go @@ -24,7 +24,7 @@ import ( func createStorageExtension(_ string) storage.Extension { // After having storage moved to core, we could leverage storagetest.NewTestExtension(nil, path) - return newMockStorageExtension() + return NewMockStorageExtension() } func createTestClient(extension storage.Extension) storage.Client { @@ -36,13 +36,8 @@ func createTestClient(extension storage.Extension) storage.Client { } func createTestPersistentStorageWithLoggingAndCapacity(client storage.Client, logger *zap.Logger, capacity uint64) *persistentContiguousStorage { - return newPersistentContiguousStorage(context.Background(), "foo", PersistentQueueSettings{ - Capacity: capacity, - Logger: logger, - Client: client, - Unmarshaler: newFakeTracesRequestUnmarshalerFunc(), - Marshaler: newFakeTracesRequestMarshalerFunc(), - }) + return newPersistentContiguousStorage(context.Background(), "foo", client, logger, capacity, + newFakeTracesRequestMarshalerFunc(), newFakeTracesRequestUnmarshalerFunc()) } func createTestPersistentStorage(client storage.Client) *persistentContiguousStorage { @@ -62,11 +57,6 @@ func newFakeTracesRequest(td ptrace.Traces) *fakeTracesRequest { } } -func (fd *fakeTracesRequest) Marshal() ([]byte, error) { - marshaler := &ptrace.ProtoMarshaler{} - return marshaler.MarshalTraces(fd.td) -} - func (fd *fakeTracesRequest) OnProcessingFinished() { if fd.processingFinishedCallback != nil { fd.processingFinishedCallback() @@ -360,7 +350,7 @@ func TestPersistentStorage_RepeatPutCloseReadClose(t *testing.T) { // No more items ext := createStorageExtension(path) - wq := createTestQueue(ext, 1000) + wq := createTestQueue(t, 1000, 1, func(Request) {}) require.Equal(t, 0, wq.Size()) require.NoError(t, ext.Shutdown(context.Background())) } @@ -480,7 +470,7 @@ func TestPersistentStorage_StorageFull(t *testing.T) { var err error traces := newTraces(5, 10) req := newFakeTracesRequest(traces) - marshaled, err := req.Marshal() + marshaled, err := newFakeTracesRequestMarshalerFunc()(req) require.NoError(t, err) maxSizeInBytes := len(marshaled) * 5 // arbitrary small number freeSpaceInBytes := 1 @@ -580,82 +570,6 @@ func requireCurrentlyDispatchedItemsEqual(t *testing.T, pcs *persistentContiguou }, 5*time.Second, 10*time.Millisecond) } -type mockStorageExtension struct { - component.StartFunc - component.ShutdownFunc -} - -func (m mockStorageExtension) GetClient(_ context.Context, _ component.Kind, _ component.ID, _ string) (storage.Client, error) { - return &mockStorageClient{st: map[string][]byte{}}, nil -} - -func newMockStorageExtension() storage.Extension { - return &mockStorageExtension{} -} - -type mockStorageClient struct { - st map[string][]byte - mux sync.Mutex - closeCounter uint64 -} - -func (m *mockStorageClient) Get(_ context.Context, s string) ([]byte, error) { - m.mux.Lock() - defer m.mux.Unlock() - - val, found := m.st[s] - if !found { - return nil, nil - } - - return val, nil -} - -func (m *mockStorageClient) Set(_ context.Context, s string, bytes []byte) error { - m.mux.Lock() - defer m.mux.Unlock() - - m.st[s] = bytes - return nil -} - -func (m *mockStorageClient) Delete(_ context.Context, s string) error { - m.mux.Lock() - defer m.mux.Unlock() - - delete(m.st, s) - return nil -} - -func (m *mockStorageClient) Close(_ context.Context) error { - m.closeCounter++ - return nil -} - -func (m *mockStorageClient) Batch(_ context.Context, ops ...storage.Operation) error { - m.mux.Lock() - defer m.mux.Unlock() - - for _, op := range ops { - switch op.Type { - case storage.Get: - op.Value = m.st[op.Key] - case storage.Set: - m.st[op.Key] = op.Value - case storage.Delete: - delete(m.st, op.Key) - default: - return errors.New("wrong operation type") - } - } - - return nil -} - -func (m *mockStorageClient) getCloseCount() uint64 { - return m.closeCounter -} - func newFakeBoundedStorageClient(maxSizeInBytes int) *fakeBoundedStorageClient { return &fakeBoundedStorageClient{ st: map[string][]byte{}, diff --git a/exporter/exporterhelper/internal/producer_consumer_queue.go b/exporter/exporterhelper/internal/producer_consumer_queue.go index c6a1e3a23bd..7b17106a564 100644 --- a/exporter/exporterhelper/internal/producer_consumer_queue.go +++ b/exporter/exporterhelper/internal/producer_consumer_queue.go @@ -5,12 +5,25 @@ package internal // import "go.opentelemetry.io/collector/exporter/exporterhelper/internal" +import ( + "context" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/exporter" +) + +type QueueSettings struct { + exporter.CreateSettings + DataType component.DataType + Callback func(item Request) +} + // ProducerConsumerQueue defines a producer-consumer exchange which can be backed by e.g. the memory-based ring buffer queue // (boundedMemoryQueue) or via a disk-based queue (persistentQueue) type ProducerConsumerQueue interface { - // StartConsumers starts a given number of goroutines consuming items from the queue + // Start starts the queue with a given number of goroutines consuming items from the queue // and passing them into the consumer callback. - StartConsumers(num int, callback func(item Request)) + Start(ctx context.Context, host component.Host, set QueueSettings) error // Produce is used by the producer to submit new item to the queue. Returns false if the item wasn't added // to the queue due to queue overflow. Produce(item Request) bool @@ -19,4 +32,9 @@ type ProducerConsumerQueue interface { // Stop stops all consumers, as well as the length reporter if started, // and releases the items channel. It blocks until all consumers have stopped. Stop() + // Capacity returns the capacity of the queue. + Capacity() int + // IsPersistent returns true if the queue is persistent. + // TODO: Do not expose this method if the interface moves to a public package. + IsPersistent() bool } diff --git a/exporter/exporterhelper/logs.go b/exporter/exporterhelper/logs.go index 0fdf1fc3858..ef22d50dd02 100644 --- a/exporter/exporterhelper/logs.go +++ b/exporter/exporterhelper/logs.go @@ -89,9 +89,7 @@ func NewLogsExporter( return nil, errNilPushLogsData } - bs := newBaseSettings(false, options...) - bs.marshaler = logsRequestMarshaler - bs.unmarshaler = newLogsRequestUnmarshalerFunc(pusher) + bs := newBaseSettings(false, logsRequestMarshaler, newLogsRequestUnmarshalerFunc(pusher), options...) be, err := newBaseExporter(set, bs, component.DataTypeLogs) if err != nil { return nil, err @@ -118,12 +116,17 @@ func NewLogsExporter( }, err } +// LogsConverter provides an interface for converting plog.Logs into a request. +// This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type LogsConverter interface { // RequestFromLogs converts plog.Logs data into a request. RequestFromLogs(context.Context, plog.Logs) (Request, error) } // NewLogsRequestExporter creates new logs exporter based on custom LogsConverter and RequestSender. +// This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. func NewLogsRequestExporter( _ context.Context, set exporter.CreateSettings, @@ -138,14 +141,18 @@ func NewLogsRequestExporter( return nil, errNilLogsConverter } - bs := newBaseSettings(true, options...) + bs := newBaseSettings(true, nil, nil, options...) be, err := newBaseExporter(set, bs, component.DataTypeLogs) if err != nil { return nil, err } - - // TODO: Add new observability tracing/metrics to the new exporterhelper. + be.wrapConsumerSender(func(nextSender requestSender) requestSender { + return &logsExporterWithObservability{ + obsrep: be.obsrep, + nextSender: nextSender, + } + }) lc, err := consumer.NewLogs(func(ctx context.Context, ld plog.Logs) error { req, cErr := converter.RequestFromLogs(ctx, ld) @@ -155,10 +162,15 @@ func NewLogsRequestExporter( zap.Error(err)) return consumererror.NewPermanent(cErr) } - return be.sender.send(&request{ + r := &request{ baseRequest: baseRequest{ctx: ctx}, Request: req, - }) + } + sErr := be.sender.send(r) + if errors.Is(sErr, errSendingQueueIsFull) { + be.obsrep.recordLogsEnqueueFailure(r.Context(), int64(r.Count())) + } + return sErr }, bs.consumerOptions...) return &logsExporter{ diff --git a/exporter/exporterhelper/logs_test.go b/exporter/exporterhelper/logs_test.go index 14e35679ff4..070679b2e96 100644 --- a/exporter/exporterhelper/logs_test.go +++ b/exporter/exporterhelper/logs_test.go @@ -7,6 +7,7 @@ import ( "context" "errors" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -20,7 +21,9 @@ import ( "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumererror" + "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exporterhelper/internal" "go.opentelemetry.io/collector/exporter/exportertest" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" "go.opentelemetry.io/collector/internal/testdata" @@ -148,6 +151,30 @@ func TestLogsRequestExporter_Default_ExportError(t *testing.T) { require.Equal(t, want, le.ConsumeLogs(context.Background(), ld)) } +func TestLogsExporter_WithPersistentQueue(t *testing.T) { + qCfg := NewDefaultQueueSettings() + storageID := component.NewIDWithName("file_storage", "storage") + qCfg.StorageID = &storageID + rCfg := NewDefaultRetrySettings() + ts := consumertest.LogsSink{} + set := exportertest.NewNopCreateSettings() + set.ID = component.NewIDWithName("test_logs", "with_persistent_queue") + te, err := NewLogsExporter(context.Background(), set, &fakeLogsExporterConfig, ts.ConsumeLogs, WithRetry(rCfg), WithQueue(qCfg)) + require.NoError(t, err) + + host := &mockHost{ext: map[component.ID]component.Component{ + storageID: internal.NewMockStorageExtension(), + }} + require.NoError(t, te.Start(context.Background(), host)) + t.Cleanup(func() { require.NoError(t, te.Shutdown(context.Background())) }) + + traces := testdata.GenerateLogs(2) + require.NoError(t, te.ConsumeLogs(context.Background(), traces)) + require.Eventually(t, func() bool { + return len(ts.AllLogs()) == 1 && ts.LogRecordCount() == 2 + }, 500*time.Millisecond, 10*time.Millisecond) +} + func TestLogsExporter_WithRecordMetrics(t *testing.T) { tt, err := obsreporttest.SetupTelemetry(fakeLogsExporterName) require.NoError(t, err) @@ -160,6 +187,18 @@ func TestLogsExporter_WithRecordMetrics(t *testing.T) { checkRecordedMetricsForLogsExporter(t, tt, le, nil) } +func TestLogsRequestExporter_WithRecordMetrics(t *testing.T) { + tt, err := obsreporttest.SetupTelemetry(fakeLogsExporterName) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + le, err := NewLogsRequestExporter(context.Background(), tt.ToExporterCreateSettings(), &fakeRequestConverter{}) + require.NoError(t, err) + require.NotNil(t, le) + + checkRecordedMetricsForLogsExporter(t, tt, le, nil) +} + func TestLogsExporter_WithRecordMetrics_ReturnError(t *testing.T) { want := errors.New("my_error") tt, err := obsreporttest.SetupTelemetry(fakeLogsExporterName) @@ -173,6 +212,20 @@ func TestLogsExporter_WithRecordMetrics_ReturnError(t *testing.T) { checkRecordedMetricsForLogsExporter(t, tt, le, want) } +func TestLogsRequestExporter_WithRecordMetrics_ExportError(t *testing.T) { + want := errors.New("export_error") + tt, err := obsreporttest.SetupTelemetry(fakeLogsExporterName) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + le, err := NewLogsRequestExporter(context.Background(), tt.ToExporterCreateSettings(), + &fakeRequestConverter{requestError: want}) + require.Nil(t, err) + require.NotNil(t, le) + + checkRecordedMetricsForLogsExporter(t, tt, le, want) +} + func TestLogsExporter_WithRecordEnqueueFailedMetrics(t *testing.T) { tt, err := obsreporttest.SetupTelemetry(fakeLogsExporterName) require.NoError(t, err) @@ -211,6 +264,19 @@ func TestLogsExporter_WithSpan(t *testing.T) { checkWrapSpanForLogsExporter(t, sr, set.TracerProvider.Tracer("test"), le, nil, 1) } +func TestLogsRequestExporter_WithSpan(t *testing.T) { + set := exportertest.NewNopCreateSettings() + sr := new(tracetest.SpanRecorder) + set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) + otel.SetTracerProvider(set.TracerProvider) + defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + + le, err := NewLogsRequestExporter(context.Background(), set, &fakeRequestConverter{}) + require.Nil(t, err) + require.NotNil(t, le) + checkWrapSpanForLogsExporter(t, sr, set.TracerProvider.Tracer("test"), le, nil, 1) +} + func TestLogsExporter_WithSpan_ReturnError(t *testing.T) { set := exportertest.NewNopCreateSettings() sr := new(tracetest.SpanRecorder) @@ -225,6 +291,20 @@ func TestLogsExporter_WithSpan_ReturnError(t *testing.T) { checkWrapSpanForLogsExporter(t, sr, set.TracerProvider.Tracer("test"), le, want, 1) } +func TestLogsRequestExporter_WithSpan_ReturnError(t *testing.T) { + set := exportertest.NewNopCreateSettings() + sr := new(tracetest.SpanRecorder) + set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) + otel.SetTracerProvider(set.TracerProvider) + defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + + want := errors.New("my_error") + le, err := NewLogsRequestExporter(context.Background(), set, &fakeRequestConverter{requestError: want}) + require.Nil(t, err) + require.NotNil(t, le) + checkWrapSpanForLogsExporter(t, sr, set.TracerProvider.Tracer("test"), le, want, 1) +} + func TestLogsExporter_WithShutdown(t *testing.T) { shutdownCalled := false shutdown := func(context.Context) error { shutdownCalled = true; return nil } diff --git a/exporter/exporterhelper/metrics.go b/exporter/exporterhelper/metrics.go index 906d0d6f855..a13b010e955 100644 --- a/exporter/exporterhelper/metrics.go +++ b/exporter/exporterhelper/metrics.go @@ -89,9 +89,7 @@ func NewMetricsExporter( return nil, errNilPushMetricsData } - bs := newBaseSettings(false, options...) - bs.marshaler = metricsRequestMarshaler - bs.unmarshaler = newMetricsRequestUnmarshalerFunc(pusher) + bs := newBaseSettings(false, metricsRequestMarshaler, newMetricsRequestUnmarshalerFunc(pusher), options...) be, err := newBaseExporter(set, bs, component.DataTypeMetrics) if err != nil { return nil, err @@ -118,12 +116,17 @@ func NewMetricsExporter( }, err } +// MetricsConverter provides an interface for converting pmetric.Metrics into a request. +// This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type MetricsConverter interface { // RequestFromMetrics converts pdata.Metrics into a request. RequestFromMetrics(context.Context, pmetric.Metrics) (Request, error) } // NewMetricsRequestExporter creates a new metrics exporter based on a custom MetricsConverter and RequestSender. +// This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. func NewMetricsRequestExporter( _ context.Context, set exporter.CreateSettings, @@ -138,14 +141,18 @@ func NewMetricsRequestExporter( return nil, errNilMetricsConverter } - bs := newBaseSettings(true, options...) + bs := newBaseSettings(true, nil, nil, options...) be, err := newBaseExporter(set, bs, component.DataTypeMetrics) if err != nil { return nil, err } - - // TODO: Add new observability tracing/metrics to the new exporterhelper. + be.wrapConsumerSender(func(nextSender requestSender) requestSender { + return &metricsSenderWithObservability{ + obsrep: be.obsrep, + nextSender: nextSender, + } + }) mc, err := consumer.NewMetrics(func(ctx context.Context, md pmetric.Metrics) error { req, cErr := converter.RequestFromMetrics(ctx, md) @@ -155,10 +162,15 @@ func NewMetricsRequestExporter( zap.Error(err)) return consumererror.NewPermanent(cErr) } - return be.sender.send(&request{ + r := &request{ Request: req, baseRequest: baseRequest{ctx: ctx}, - }) + } + sErr := be.sender.send(r) + if errors.Is(sErr, errSendingQueueIsFull) { + be.obsrep.recordMetricsEnqueueFailure(r.Context(), int64(r.Count())) + } + return sErr }, bs.consumerOptions...) return &metricsExporter{ diff --git a/exporter/exporterhelper/metrics_test.go b/exporter/exporterhelper/metrics_test.go index c8ea7587219..354a0686f89 100644 --- a/exporter/exporterhelper/metrics_test.go +++ b/exporter/exporterhelper/metrics_test.go @@ -7,6 +7,7 @@ import ( "context" "errors" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -20,7 +21,9 @@ import ( "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumererror" + "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exporterhelper/internal" "go.opentelemetry.io/collector/exporter/exportertest" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" "go.opentelemetry.io/collector/internal/testdata" @@ -149,6 +152,30 @@ func TestMetricsRequestExporter_Default_ExportError(t *testing.T) { require.Equal(t, want, me.ConsumeMetrics(context.Background(), md)) } +func TestMetricsExporter_WithPersistentQueue(t *testing.T) { + qCfg := NewDefaultQueueSettings() + storageID := component.NewIDWithName("file_storage", "storage") + qCfg.StorageID = &storageID + rCfg := NewDefaultRetrySettings() + ms := consumertest.MetricsSink{} + set := exportertest.NewNopCreateSettings() + set.ID = component.NewIDWithName("test_metrics", "with_persistent_queue") + te, err := NewMetricsExporter(context.Background(), set, &fakeTracesExporterConfig, ms.ConsumeMetrics, WithRetry(rCfg), WithQueue(qCfg)) + require.NoError(t, err) + + host := &mockHost{ext: map[component.ID]component.Component{ + storageID: internal.NewMockStorageExtension(), + }} + require.NoError(t, te.Start(context.Background(), host)) + t.Cleanup(func() { require.NoError(t, te.Shutdown(context.Background())) }) + + metrics := testdata.GenerateMetrics(2) + require.NoError(t, te.ConsumeMetrics(context.Background(), metrics)) + require.Eventually(t, func() bool { + return len(ms.AllMetrics()) == 1 && ms.DataPointCount() == 4 + }, 500*time.Millisecond, 10*time.Millisecond) +} + func TestMetricsExporter_WithRecordMetrics(t *testing.T) { tt, err := obsreporttest.SetupTelemetry(fakeMetricsExporterName) require.NoError(t, err) @@ -161,6 +188,18 @@ func TestMetricsExporter_WithRecordMetrics(t *testing.T) { checkRecordedMetricsForMetricsExporter(t, tt, me, nil) } +func TestMetricsRequestExporter_WithRecordMetrics(t *testing.T) { + tt, err := obsreporttest.SetupTelemetry(fakeMetricsExporterName) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + me, err := NewMetricsRequestExporter(context.Background(), tt.ToExporterCreateSettings(), fakeRequestConverter{}) + require.NoError(t, err) + require.NotNil(t, me) + + checkRecordedMetricsForMetricsExporter(t, tt, me, nil) +} + func TestMetricsExporter_WithRecordMetrics_ReturnError(t *testing.T) { want := errors.New("my_error") tt, err := obsreporttest.SetupTelemetry(fakeMetricsExporterName) @@ -174,6 +213,19 @@ func TestMetricsExporter_WithRecordMetrics_ReturnError(t *testing.T) { checkRecordedMetricsForMetricsExporter(t, tt, me, want) } +func TestMetricsRequestExporter_WithRecordMetrics_ExportError(t *testing.T) { + want := errors.New("my_error") + tt, err := obsreporttest.SetupTelemetry(fakeMetricsExporterName) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + me, err := NewMetricsRequestExporter(context.Background(), tt.ToExporterCreateSettings(), fakeRequestConverter{requestError: want}) + require.NoError(t, err) + require.NotNil(t, me) + + checkRecordedMetricsForMetricsExporter(t, tt, me, want) +} + func TestMetricsExporter_WithRecordEnqueueFailedMetrics(t *testing.T) { tt, err := obsreporttest.SetupTelemetry(fakeMetricsExporterName) require.NoError(t, err) @@ -212,6 +264,19 @@ func TestMetricsExporter_WithSpan(t *testing.T) { checkWrapSpanForMetricsExporter(t, sr, set.TracerProvider.Tracer("test"), me, nil, 2) } +func TestMetricsRequestExporter_WithSpan(t *testing.T) { + set := exportertest.NewNopCreateSettings() + sr := new(tracetest.SpanRecorder) + set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) + otel.SetTracerProvider(set.TracerProvider) + defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + + me, err := NewMetricsRequestExporter(context.Background(), set, fakeRequestConverter{}) + require.NoError(t, err) + require.NotNil(t, me) + checkWrapSpanForMetricsExporter(t, sr, set.TracerProvider.Tracer("test"), me, nil, 2) +} + func TestMetricsExporter_WithSpan_ReturnError(t *testing.T) { set := exportertest.NewNopCreateSettings() sr := new(tracetest.SpanRecorder) @@ -226,6 +291,20 @@ func TestMetricsExporter_WithSpan_ReturnError(t *testing.T) { checkWrapSpanForMetricsExporter(t, sr, set.TracerProvider.Tracer("test"), me, want, 2) } +func TestMetricsRequestExporter_WithSpan_ExportError(t *testing.T) { + set := exportertest.NewNopCreateSettings() + sr := new(tracetest.SpanRecorder) + set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) + otel.SetTracerProvider(set.TracerProvider) + defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + + want := errors.New("my_error") + me, err := NewMetricsRequestExporter(context.Background(), set, fakeRequestConverter{requestError: want}) + require.NoError(t, err) + require.NotNil(t, me) + checkWrapSpanForMetricsExporter(t, sr, set.TracerProvider.Tracer("test"), me, want, 2) +} + func TestMetricsExporter_WithShutdown(t *testing.T) { shutdownCalled := false shutdown := func(context.Context) error { shutdownCalled = true; return nil } diff --git a/exporter/exporterhelper/queued_retry.go b/exporter/exporterhelper/queued_retry.go index e80517f98ac..2e2bc1f9a82 100644 --- a/exporter/exporterhelper/queued_retry.go +++ b/exporter/exporterhelper/queued_retry.go @@ -18,18 +18,14 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/consumer/consumererror" + "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exporterhelper/internal" - "go.opentelemetry.io/collector/extension/experimental/storage" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" ) const defaultQueueSize = 1000 -var ( - errSendingQueueIsFull = errors.New("sending_queue is full") - errNoStorageClient = errors.New("no storage client extension found") - errWrongExtensionType = errors.New("requested extension is not a storage extension") -) +var errSendingQueueIsFull = errors.New("sending_queue is full") // QueueSettings defines configuration for queueing batches before sending to the consumerSender. type QueueSettings struct { @@ -73,7 +69,6 @@ type queuedRetrySender struct { fullName string id component.ID signal component.DataType - queueSettings queueSettings consumerSender requestSender queue internal.ProducerConsumerQueue retryStopCh chan struct{} @@ -82,20 +77,22 @@ type queuedRetrySender struct { requeuingEnabled bool } -func newQueuedRetrySender(id component.ID, signal component.DataType, qs queueSettings, rCfg RetrySettings, - lCfg SampledLoggerSettings, nextSender requestSender, logger *zap.Logger) *queuedRetrySender { +func newQueuedRetrySender(id component.ID, signal component.DataType, queue internal.ProducerConsumerQueue, + rCfg RetrySettings, nextSender requestSender, logger *zap.Logger) *queuedRetrySender { retryStopCh := make(chan struct{}) - newLogger := createSampledLogger(logger, lCfg) + sampledLogger := createSampledLogger(logger) traceAttr := attribute.String(obsmetrics.ExporterKey, id.String()) qrs := &queuedRetrySender{ fullName: id.String(), id: id, signal: signal, - queueSettings: qs, + queue: queue, retryStopCh: retryStopCh, traceAttribute: traceAttr, - logger: newLogger, + logger: sampledLogger, + // TODO: this can be further exposed as a config param rather than relying on a type of queue + requeuingEnabled: queue != nil && queue.IsPersistent(), } qrs.consumerSender = &retrySender{ @@ -103,70 +100,14 @@ func newQueuedRetrySender(id component.ID, signal component.DataType, qs queueSe cfg: rCfg, nextSender: nextSender, stopCh: retryStopCh, - logger: newLogger, + logger: sampledLogger, // Following three functions actually depend on queuedRetrySender onTemporaryFailure: qrs.onTemporaryFailure, } - if !qs.persistenceEnabled() { - qrs.queue = internal.NewBoundedMemoryQueue(qs.config.QueueSize) - } - // The Persistent Queue is initialized separately as it needs extra information about the component - return qrs } -func getStorageExtension(extensions map[component.ID]component.Component, storageID component.ID) (storage.Extension, error) { - if ext, found := extensions[storageID]; found { - if storageExt, ok := ext.(storage.Extension); ok { - return storageExt, nil - } - return nil, errWrongExtensionType - } - return nil, errNoStorageClient -} - -func toStorageClient(ctx context.Context, storageID component.ID, host component.Host, ownerID component.ID, signal component.DataType) (storage.Client, error) { - extension, err := getStorageExtension(host.GetExtensions(), storageID) - if err != nil { - return nil, err - } - - client, err := extension.GetClient(ctx, component.KindExporter, ownerID, string(signal)) - if err != nil { - return nil, err - } - - return client, err -} - -// initializePersistentQueue uses extra information for initialization available from component.Host -func (qrs *queuedRetrySender) initializePersistentQueue(ctx context.Context, host component.Host) error { - if !qrs.queueSettings.persistenceEnabled() { - return nil - } - - storageClient, err := toStorageClient(ctx, *qrs.queueSettings.config.StorageID, host, qrs.id, qrs.signal) - if err != nil { - return err - } - - qrs.queue = internal.NewPersistentQueue(ctx, internal.PersistentQueueSettings{ - Name: qrs.fullName, - Signal: qrs.signal, - Capacity: uint64(qrs.queueSettings.config.QueueSize), - Logger: qrs.logger, - Client: storageClient, - Marshaler: qrs.queueSettings.marshaler, - Unmarshaler: qrs.queueSettings.unmarshaler, - }) - - // TODO: this can be further exposed as a config param rather than relying on a type of queue - qrs.requeuingEnabled = true - - return nil -} - func (qrs *queuedRetrySender) onTemporaryFailure(logger *zap.Logger, req internal.Request, err error) error { if !qrs.requeuingEnabled || qrs.queue == nil { logger.Error( @@ -193,30 +134,35 @@ func (qrs *queuedRetrySender) onTemporaryFailure(logger *zap.Logger, req interna } // start is invoked during service startup. -func (qrs *queuedRetrySender) start(ctx context.Context, host component.Host) error { - if err := qrs.initializePersistentQueue(ctx, host); err != nil { - return err +func (qrs *queuedRetrySender) start(ctx context.Context, host component.Host, set exporter.CreateSettings) error { + if qrs.queue == nil { + return nil } - qrs.queue.StartConsumers(qrs.queueSettings.config.NumConsumers, func(item internal.Request) { - _ = qrs.consumerSender.send(item) - item.OnProcessingFinished() + err := qrs.queue.Start(ctx, host, internal.QueueSettings{ + CreateSettings: set, + DataType: qrs.signal, + Callback: func(item internal.Request) { + _ = qrs.consumerSender.send(item) + item.OnProcessingFinished() + }, }) + if err != nil { + return err + } // Start reporting queue length metric - if qrs.queueSettings.config.Enabled { - err := globalInstruments.queueSize.UpsertEntry(func() int64 { - return int64(qrs.queue.Size()) - }, metricdata.NewLabelValue(qrs.fullName)) - if err != nil { - return fmt.Errorf("failed to create retry queue size metric: %w", err) - } - err = globalInstruments.queueCapacity.UpsertEntry(func() int64 { - return int64(qrs.queueSettings.config.QueueSize) - }, metricdata.NewLabelValue(qrs.fullName)) - if err != nil { - return fmt.Errorf("failed to create retry queue capacity metric: %w", err) - } + err = globalInstruments.queueSize.UpsertEntry(func() int64 { + return int64(qrs.queue.Size()) + }, metricdata.NewLabelValue(qrs.fullName)) + if err != nil { + return fmt.Errorf("failed to create retry queue size metric: %w", err) + } + err = globalInstruments.queueCapacity.UpsertEntry(func() int64 { + return int64(qrs.queue.Capacity()) + }, metricdata.NewLabelValue(qrs.fullName)) + if err != nil { + return fmt.Errorf("failed to create retry queue capacity metric: %w", err) } return nil @@ -224,19 +170,17 @@ func (qrs *queuedRetrySender) start(ctx context.Context, host component.Host) er // shutdown is invoked during service shutdown. func (qrs *queuedRetrySender) shutdown() { - // Cleanup queue metrics reporting - if qrs.queueSettings.config.Enabled { - _ = globalInstruments.queueSize.UpsertEntry(func() int64 { - return int64(0) - }, metricdata.NewLabelValue(qrs.fullName)) - } - // First Stop the retry goroutines, so that unblocks the queue numWorkers. close(qrs.retryStopCh) - // Stop the queued sender, this will drain the queue and will call the retry (which is stopped) that will only - // try once every request. if qrs.queue != nil { + // Cleanup queue metrics reporting + _ = globalInstruments.queueSize.UpsertEntry(func() int64 { + return int64(0) + }, metricdata.NewLabelValue(qrs.fullName)) + + // Stop the queued sender, this will drain the queue and will call the retry (which is stopped) that will only + // try once every request. qrs.queue.Stop() } } @@ -273,9 +217,9 @@ func NewDefaultRetrySettings() RetrySettings { } } -func createSampledLogger(logger *zap.Logger, lCfg SampledLoggerSettings) *zap.Logger { - if !lCfg.Enabled || logger.Core().Enabled(zapcore.DebugLevel) { - // Debugging is enabled or log sampling is disabled. Don't do any sampling. +func createSampledLogger(logger *zap.Logger) *zap.Logger { + if logger.Core().Enabled(zapcore.DebugLevel) { + // Debugging is enabled. Don't do any sampling. return logger } @@ -294,7 +238,7 @@ func createSampledLogger(logger *zap.Logger, lCfg SampledLoggerSettings) *zap.Lo // send implements the requestSender interface func (qrs *queuedRetrySender) send(req internal.Request) error { - if !qrs.queueSettings.config.Enabled { + if qrs.queue == nil { err := qrs.consumerSender.send(req) if err != nil { qrs.logger.Error( diff --git a/exporter/exporterhelper/queued_retry_test.go b/exporter/exporterhelper/queued_retry_test.go index e75ea62eb9c..3e2f1fb694c 100644 --- a/exporter/exporterhelper/queued_retry_test.go +++ b/exporter/exporterhelper/queued_retry_test.go @@ -7,7 +7,6 @@ import ( "context" "errors" "fmt" - "strconv" "sync" "sync/atomic" "testing" @@ -18,18 +17,15 @@ import ( "go.opencensus.io/metric/metricdata" "go.opencensus.io/metric/metricproducer" "go.opencensus.io/tag" - "go.uber.org/zap" - "go.uber.org/zap/zaptest" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/exporter/exporterhelper/internal" + "go.opentelemetry.io/collector/exporter/exportertest" "go.opentelemetry.io/collector/extension/experimental/storage" - "go.opentelemetry.io/collector/extension/extensiontest" "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/obsreport/obsreporttest" - "go.opentelemetry.io/collector/pdata/ptrace" ) func mockRequestUnmarshaler(mr *mockRequest) internal.RequestUnmarshaler { @@ -46,9 +42,7 @@ func TestQueuedRetry_DropOnPermanentError(t *testing.T) { qCfg := NewDefaultQueueSettings() rCfg := NewDefaultRetrySettings() mockR := newMockRequest(context.Background(), 2, consumererror.NewPermanent(errors.New("bad data"))) - bs := newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)) - bs.marshaler = mockRequestMarshaler - bs.unmarshaler = mockRequestUnmarshaler(mockR) + bs := newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)) be, err := newBaseExporter(defaultSettings, bs, "") require.NoError(t, err) ocs := newObservabilityConsumerSender(be.qrSender.consumerSender) @@ -73,9 +67,9 @@ func TestQueuedRetry_DropOnNoRetry(t *testing.T) { qCfg := NewDefaultQueueSettings() rCfg := NewDefaultRetrySettings() rCfg.Enabled = false - bs := newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)) - bs.marshaler = mockRequestMarshaler - bs.unmarshaler = mockRequestUnmarshaler(newMockRequest(context.Background(), 2, errors.New("transient error"))) + bs := newBaseSettings(false, mockRequestMarshaler, + mockRequestUnmarshaler(newMockRequest(context.Background(), 2, errors.New("transient error"))), + WithRetry(rCfg), WithQueue(qCfg)) be, err := newBaseExporter(defaultSettings, bs, "") require.NoError(t, err) ocs := newObservabilityConsumerSender(be.qrSender.consumerSender) @@ -102,7 +96,7 @@ func TestQueuedRetry_OnError(t *testing.T) { qCfg.NumConsumers = 1 rCfg := NewDefaultRetrySettings() rCfg.InitialInterval = 0 - be, err := newBaseExporter(defaultSettings, newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)), "") + be, err := newBaseExporter(defaultSettings, newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)), "") require.NoError(t, err) ocs := newObservabilityConsumerSender(be.qrSender.consumerSender) be.qrSender.consumerSender = ocs @@ -129,7 +123,7 @@ func TestQueuedRetry_StopWhileWaiting(t *testing.T) { qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 1 rCfg := NewDefaultRetrySettings() - be, err := newBaseExporter(defaultSettings, newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)), "") + be, err := newBaseExporter(defaultSettings, newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)), "") require.NoError(t, err) ocs := newObservabilityConsumerSender(be.qrSender.consumerSender) be.qrSender.consumerSender = ocs @@ -163,7 +157,7 @@ func TestQueuedRetry_DoNotPreserveCancellation(t *testing.T) { qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 1 rCfg := NewDefaultRetrySettings() - be, err := newBaseExporter(defaultSettings, newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)), "") + be, err := newBaseExporter(defaultSettings, newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)), "") require.NoError(t, err) ocs := newObservabilityConsumerSender(be.qrSender.consumerSender) be.qrSender.consumerSender = ocs @@ -193,7 +187,7 @@ func TestQueuedRetry_MaxElapsedTime(t *testing.T) { rCfg := NewDefaultRetrySettings() rCfg.InitialInterval = time.Millisecond rCfg.MaxElapsedTime = 100 * time.Millisecond - be, err := newBaseExporter(defaultSettings, newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)), "") + be, err := newBaseExporter(defaultSettings, newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)), "") require.NoError(t, err) ocs := newObservabilityConsumerSender(be.qrSender.consumerSender) be.qrSender.consumerSender = ocs @@ -240,7 +234,7 @@ func TestQueuedRetry_ThrottleError(t *testing.T) { qCfg.NumConsumers = 1 rCfg := NewDefaultRetrySettings() rCfg.InitialInterval = 10 * time.Millisecond - be, err := newBaseExporter(defaultSettings, newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)), "") + be, err := newBaseExporter(defaultSettings, newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)), "") require.NoError(t, err) ocs := newObservabilityConsumerSender(be.qrSender.consumerSender) be.qrSender.consumerSender = ocs @@ -273,7 +267,7 @@ func TestQueuedRetry_RetryOnError(t *testing.T) { qCfg.QueueSize = 1 rCfg := NewDefaultRetrySettings() rCfg.InitialInterval = 0 - be, err := newBaseExporter(defaultSettings, newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)), "") + be, err := newBaseExporter(defaultSettings, newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)), "") require.NoError(t, err) ocs := newObservabilityConsumerSender(be.qrSender.consumerSender) be.qrSender.consumerSender = ocs @@ -300,7 +294,7 @@ func TestQueuedRetry_DropOnFull(t *testing.T) { qCfg := NewDefaultQueueSettings() qCfg.QueueSize = 0 rCfg := NewDefaultRetrySettings() - be, err := newBaseExporter(defaultSettings, newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)), "") + be, err := newBaseExporter(defaultSettings, newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)), "") require.NoError(t, err) ocs := newObservabilityConsumerSender(be.qrSender.consumerSender) be.qrSender.consumerSender = ocs @@ -321,7 +315,7 @@ func TestQueuedRetryHappyPath(t *testing.T) { qCfg := NewDefaultQueueSettings() rCfg := NewDefaultRetrySettings() set := tt.ToExporterCreateSettings() - be, err := newBaseExporter(set, newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)), "") + be, err := newBaseExporter(set, newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)), "") require.NoError(t, err) ocs := newObservabilityConsumerSender(be.qrSender.consumerSender) be.qrSender.consumerSender = ocs @@ -356,7 +350,7 @@ func TestQueuedRetry_QueueMetricsReported(t *testing.T) { qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 0 // to make every request go straight to the queue rCfg := NewDefaultRetrySettings() - be, err := newBaseExporter(defaultSettings, newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)), "") + be, err := newBaseExporter(defaultSettings, newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)), "") require.NoError(t, err) require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) @@ -398,99 +392,13 @@ func TestQueueSettings_Validate(t *testing.T) { assert.NoError(t, qCfg.Validate()) } -func TestGetRetrySettings(t *testing.T) { - getStorageClientError := errors.New("unable to create storage client") - testCases := []struct { - desc string - storage storage.Extension - numStorages int - storageIndex int - expectedError error - getClientError error - }{ - { - desc: "obtain storage extension by name", - numStorages: 2, - storageIndex: 0, - expectedError: nil, - }, - { - desc: "fail on not existing storage extension", - numStorages: 2, - storageIndex: 100, - expectedError: errNoStorageClient, - }, - { - desc: "invalid extension type", - numStorages: 2, - storageIndex: 100, - expectedError: errNoStorageClient, - }, - { - desc: "fail on error getting storage client from extension", - numStorages: 1, - storageIndex: 0, - expectedError: getStorageClientError, - getClientError: getStorageClientError, - }, - } - - for _, tC := range testCases { - t.Run(tC.desc, func(t *testing.T) { - storageID := component.NewIDWithName("file_storage", strconv.Itoa(tC.storageIndex)) - - var extensions = map[component.ID]component.Component{} - for i := 0; i < tC.numStorages; i++ { - extensions[component.NewIDWithName("file_storage", strconv.Itoa(i))] = &mockStorageExtension{GetClientError: tC.getClientError} - } - host := &mockHost{ext: extensions} - ownerID := component.NewID("foo_exporter") - - // execute - client, err := toStorageClient(context.Background(), storageID, host, ownerID, component.DataTypeTraces) - - // verify - if tC.expectedError != nil { - assert.ErrorIs(t, err, tC.expectedError) - assert.Nil(t, client) - } else { - assert.NoError(t, err) - assert.NotNil(t, client) - } - }) - } -} - -func TestInvalidStorageExtensionType(t *testing.T) { - storageID := component.NewIDWithName("extension", "extension") - - // make a test extension - factory := extensiontest.NewNopFactory() - extConfig := factory.CreateDefaultConfig() - settings := extensiontest.NewNopCreateSettings() - extension, err := factory.CreateExtension(context.Background(), settings, extConfig) - assert.NoError(t, err) - var extensions = map[component.ID]component.Component{ - storageID: extension, - } - host := &mockHost{ext: extensions} - ownerID := component.NewID("foo_exporter") - - // execute - client, err := toStorageClient(context.Background(), storageID, host, ownerID, component.DataTypeTraces) - - // we should get an error about the extension type - assert.ErrorIs(t, err, errWrongExtensionType) - assert.Nil(t, client) -} - // if requeueing is enabled, we eventually retry even if we failed at first func TestQueuedRetry_RequeuingEnabled(t *testing.T) { qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 1 rCfg := NewDefaultRetrySettings() rCfg.MaxElapsedTime = time.Nanosecond // we don't want to retry at all, but requeue instead - be, err := newBaseExporter(defaultSettings, newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)), "") + be, err := newBaseExporter(defaultSettings, newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)), "") require.NoError(t, err) ocs := newObservabilityConsumerSender(be.qrSender.consumerSender) be.qrSender.consumerSender = ocs @@ -522,7 +430,7 @@ func TestQueuedRetry_RequeuingEnabledQueueFull(t *testing.T) { qCfg.QueueSize = 0 rCfg := NewDefaultRetrySettings() rCfg.MaxElapsedTime = time.Nanosecond // we don't want to retry at all, but requeue instead - be, err := newBaseExporter(defaultSettings, newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)), "") + be, err := newBaseExporter(defaultSettings, newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)), "") require.NoError(t, err) be.qrSender.requeuingEnabled = true require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) @@ -537,6 +445,17 @@ func TestQueuedRetry_RequeuingEnabledQueueFull(t *testing.T) { mockR.checkNumRequests(t, 1) } +func TestQueueRetryWithDisabledQueue(t *testing.T) { + qs := NewDefaultQueueSettings() + qs.Enabled = false + bs := newBaseSettings(false, nil, nil, WithQueue(qs)) + require.Nil(t, bs.queue) + be, err := newBaseExporter(exportertest.NewNopCreateSettings(), bs, component.DataTypeLogs) + require.NoError(t, err) + require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) + require.NoError(t, be.Shutdown(context.Background())) +} + func TestQueuedRetryPersistenceEnabled(t *testing.T) { tt, err := obsreporttest.SetupTelemetry(defaultID) require.NoError(t, err) @@ -547,7 +466,7 @@ func TestQueuedRetryPersistenceEnabled(t *testing.T) { qCfg.StorageID = &storageID // enable persistence rCfg := NewDefaultRetrySettings() set := tt.ToExporterCreateSettings() - be, err := newBaseExporter(set, newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)), "") + be, err := newBaseExporter(set, newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)), "") require.NoError(t, err) var extensions = map[component.ID]component.Component{ @@ -571,7 +490,7 @@ func TestQueuedRetryPersistenceEnabledStorageError(t *testing.T) { qCfg.StorageID = &storageID // enable persistence rCfg := NewDefaultRetrySettings() set := tt.ToExporterCreateSettings() - bs := newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)) + bs := newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)) bs.marshaler = mockRequestMarshaler bs.unmarshaler = mockRequestUnmarshaler(&mockRequest{}) be, err := newBaseExporter(set, bs, "") @@ -598,7 +517,7 @@ func TestQueuedRetryPersistentEnabled_shutdown_dataIsRequeued(t *testing.T) { req := newMockRequest(context.Background(), 3, errors.New("some error")) - be, err := newBaseExporter(defaultSettings, newBaseSettings(false, WithRetry(rCfg), WithQueue(qCfg)), "") + be, err := newBaseExporter(defaultSettings, newBaseSettings(false, nil, nil, WithRetry(rCfg), WithQueue(qCfg)), "") require.NoError(t, err) require.NoError(t, be.Start(context.Background(), &mockHost{})) @@ -632,61 +551,11 @@ func TestQueuedRetryPersistentEnabled_shutdown_dataIsRequeued(t *testing.T) { }, time.Second, 1*time.Millisecond) } -func TestCreateSampledLogger(t *testing.T) { - testCases := []struct { - desc string - logger *zap.Logger - lCfg SampledLoggerSettings - sampledLoggedCreated bool - }{ - { - desc: "default configuration - sampledLogger enabled", - logger: zaptest.NewLogger(t, zaptest.Level(zap.WarnLevel)), - lCfg: NewDefaultSampledLoggerSettings(), - sampledLoggedCreated: true, - }, - { - desc: "sampledLogger disable", - logger: zaptest.NewLogger(t, zaptest.Level(zap.WarnLevel)), - lCfg: SampledLoggerSettings{ - Enabled: false, - }, - sampledLoggedCreated: false, - }, - { - desc: "debug logger level and sampledLogged enabled - sampledLogger not created", - logger: zaptest.NewLogger(t, zaptest.Level(zap.DebugLevel)), - lCfg: NewDefaultSampledLoggerSettings(), - sampledLoggedCreated: false, - }, - { - desc: "debug logger level and sampledLogged disabled - sampledLogger not created", - logger: zaptest.NewLogger(t, zaptest.Level(zap.DebugLevel)), - lCfg: SampledLoggerSettings{ - Enabled: false, - }, - sampledLoggedCreated: false, - }, - } - - for _, tC := range testCases { - t.Run(tC.desc, func(t *testing.T) { - newLogger := createSampledLogger(tC.logger, tC.lCfg) - require.NotNil(t, newLogger) - if tC.sampledLoggedCreated { - require.NotEqual(t, tC.logger, newLogger) - } else { - require.Equal(t, tC.logger, newLogger) - } - }) - } -} - func TestQueueRetryOptionsWithRequestExporter(t *testing.T) { - bs := newBaseSettings(true, WithRetry(NewDefaultRetrySettings())) + bs := newBaseSettings(true, nil, nil, WithRetry(NewDefaultRetrySettings())) assert.True(t, bs.requestExporter) assert.Panics(t, func() { - _ = newBaseSettings(true, WithRetry(NewDefaultRetrySettings()), WithQueue(NewDefaultQueueSettings())) + _ = newBaseSettings(true, nil, nil, WithRetry(NewDefaultRetrySettings()), WithQueue(NewDefaultQueueSettings())) }) } @@ -702,10 +571,6 @@ func (mer *mockErrorRequest) OnError(error) internal.Request { return mer } -func (mer *mockErrorRequest) Marshal() ([]byte, error) { - return nil, nil -} - func (mer *mockErrorRequest) Count() int { return 7 } @@ -737,11 +602,6 @@ func (m *mockRequest) Export(ctx context.Context) error { return ctx.Err() } -func (m *mockRequest) Marshal() ([]byte, error) { - marshaler := &ptrace.ProtoMarshaler{} - return marshaler.MarshalTraces(ptrace.NewTraces()) -} - func (m *mockRequest) OnError(error) internal.Request { return &mockRequest{ baseRequest: m.baseRequest, @@ -830,10 +690,11 @@ func checkValueForGlobalManager(t *testing.T, wantTags []tag.Tag, value int64, v func checkValueForProducer(t *testing.T, producer metricproducer.Producer, wantTags []tag.Tag, value int64, vName string) bool { for _, metric := range producer.Read() { if metric.Descriptor.Name == vName && len(metric.TimeSeries) > 0 { - lastValue := metric.TimeSeries[len(metric.TimeSeries)-1] - if tagsMatchLabelKeys(wantTags, metric.Descriptor.LabelKeys, lastValue.LabelValues) { - require.Equal(t, value, lastValue.Points[len(lastValue.Points)-1].Value.(int64)) - return true + for _, ts := range metric.TimeSeries { + if tagsMatchLabelKeys(wantTags, metric.Descriptor.LabelKeys, ts.LabelValues) { + require.Equal(t, value, ts.Points[len(ts.Points)-1].Value.(int64)) + return true + } } } } diff --git a/exporter/exporterhelper/request.go b/exporter/exporterhelper/request.go index 30f250c8ba0..407f1f27858 100644 --- a/exporter/exporterhelper/request.go +++ b/exporter/exporterhelper/request.go @@ -10,6 +10,8 @@ import ( ) // Request represents a single request that can be sent to an external endpoint. +// This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type Request interface { // Export exports the request to an external endpoint. Export(ctx context.Context) error @@ -19,6 +21,8 @@ type Request interface { // in the request. This is a recommended interface to implement for exporters. It is required for batching and queueing // based on number of items. Also, it's used for reporting number of items in collector's logs, metrics and traces. // If not implemented, collector's logs, metrics and traces will report 0 items. +// This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type RequestItemsCounter interface { // ItemsCount returns a number of basic items in the request where item is the smallest piece of data that can be // sent. For example, for OTLP exporter, this value represents the number of spans, diff --git a/exporter/exporterhelper/traces.go b/exporter/exporterhelper/traces.go index 886c0a2f197..03b0fefb95e 100644 --- a/exporter/exporterhelper/traces.go +++ b/exporter/exporterhelper/traces.go @@ -89,9 +89,7 @@ func NewTracesExporter( return nil, errNilPushTraceData } - bs := newBaseSettings(false, options...) - bs.marshaler = tracesRequestMarshaler - bs.unmarshaler = newTraceRequestUnmarshalerFunc(pusher) + bs := newBaseSettings(false, tracesRequestMarshaler, newTraceRequestUnmarshalerFunc(pusher), options...) be, err := newBaseExporter(set, bs, component.DataTypeTraces) if err != nil { return nil, err @@ -118,12 +116,17 @@ func NewTracesExporter( }, err } +// TracesConverter provides an interface for converting ptrace.Traces into a request. +// This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type TracesConverter interface { // RequestFromTraces converts ptrace.Traces into a Request. RequestFromTraces(context.Context, ptrace.Traces) (Request, error) } // NewTracesRequestExporter creates a new traces exporter based on a custom TracesConverter and RequestSender. +// This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. func NewTracesRequestExporter( _ context.Context, set exporter.CreateSettings, @@ -138,14 +141,18 @@ func NewTracesRequestExporter( return nil, errNilTracesConverter } - bs := newBaseSettings(true, options...) + bs := newBaseSettings(true, nil, nil, options...) be, err := newBaseExporter(set, bs, component.DataTypeTraces) if err != nil { return nil, err } - - // TODO: Add new observability tracing/metrics to the new exporterhelper. + be.wrapConsumerSender(func(nextSender requestSender) requestSender { + return &tracesExporterWithObservability{ + obsrep: be.obsrep, + nextSender: nextSender, + } + }) tc, err := consumer.NewTraces(func(ctx context.Context, td ptrace.Traces) error { req, cErr := converter.RequestFromTraces(ctx, td) @@ -155,10 +162,15 @@ func NewTracesRequestExporter( zap.Error(err)) return consumererror.NewPermanent(cErr) } - return be.sender.send(&request{ + r := &request{ baseRequest: baseRequest{ctx: ctx}, Request: req, - }) + } + sErr := be.sender.send(r) + if errors.Is(sErr, errSendingQueueIsFull) { + be.obsrep.recordTracesEnqueueFailure(r.Context(), int64(r.Count())) + } + return sErr }, bs.consumerOptions...) return &traceExporter{ diff --git a/exporter/exporterhelper/traces_test.go b/exporter/exporterhelper/traces_test.go index 0b314426f10..3774a6015db 100644 --- a/exporter/exporterhelper/traces_test.go +++ b/exporter/exporterhelper/traces_test.go @@ -7,6 +7,7 @@ import ( "context" "errors" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -20,7 +21,9 @@ import ( "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumererror" + "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exporterhelper/internal" "go.opentelemetry.io/collector/exporter/exportertest" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" "go.opentelemetry.io/collector/internal/testdata" @@ -146,6 +149,30 @@ func TestTracesRequestExporter_Default_ExportError(t *testing.T) { require.Equal(t, want, te.ConsumeTraces(context.Background(), td)) } +func TestTracesExporter_WithPersistentQueue(t *testing.T) { + qCfg := NewDefaultQueueSettings() + storageID := component.NewIDWithName("file_storage", "storage") + qCfg.StorageID = &storageID + rCfg := NewDefaultRetrySettings() + ts := consumertest.TracesSink{} + set := exportertest.NewNopCreateSettings() + set.ID = component.NewIDWithName("test_traces", "with_persistent_queue") + te, err := NewTracesExporter(context.Background(), set, &fakeTracesExporterConfig, ts.ConsumeTraces, WithRetry(rCfg), WithQueue(qCfg)) + require.NoError(t, err) + + host := &mockHost{ext: map[component.ID]component.Component{ + storageID: internal.NewMockStorageExtension(), + }} + require.NoError(t, te.Start(context.Background(), host)) + t.Cleanup(func() { require.NoError(t, te.Shutdown(context.Background())) }) + + traces := testdata.GenerateTraces(2) + require.NoError(t, te.ConsumeTraces(context.Background(), traces)) + require.Eventually(t, func() bool { + return len(ts.AllTraces()) == 1 && ts.SpanCount() == 2 + }, 500*time.Millisecond, 10*time.Millisecond) +} + func TestTracesExporter_WithRecordMetrics(t *testing.T) { tt, err := obsreporttest.SetupTelemetry(fakeTracesExporterName) require.NoError(t, err) @@ -158,6 +185,18 @@ func TestTracesExporter_WithRecordMetrics(t *testing.T) { checkRecordedMetricsForTracesExporter(t, tt, te, nil) } +func TestTracesRequestExporter_WithRecordMetrics(t *testing.T) { + tt, err := obsreporttest.SetupTelemetry(fakeTracesExporterName) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + te, err := NewTracesRequestExporter(context.Background(), tt.ToExporterCreateSettings(), &fakeRequestConverter{}) + require.NoError(t, err) + require.NotNil(t, te) + + checkRecordedMetricsForTracesExporter(t, tt, te, nil) +} + func TestTracesExporter_WithRecordMetrics_ReturnError(t *testing.T) { want := errors.New("my_error") tt, err := obsreporttest.SetupTelemetry(fakeTracesExporterName) @@ -171,6 +210,19 @@ func TestTracesExporter_WithRecordMetrics_ReturnError(t *testing.T) { checkRecordedMetricsForTracesExporter(t, tt, te, want) } +func TestTracesRequestExporter_WithRecordMetrics_RequestSenderError(t *testing.T) { + want := errors.New("export_error") + tt, err := obsreporttest.SetupTelemetry(fakeTracesExporterName) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + te, err := NewTracesRequestExporter(context.Background(), tt.ToExporterCreateSettings(), &fakeRequestConverter{requestError: want}) + require.NoError(t, err) + require.NotNil(t, te) + + checkRecordedMetricsForTracesExporter(t, tt, te, want) +} + func TestTracesExporter_WithRecordEnqueueFailedMetrics(t *testing.T) { tt, err := obsreporttest.SetupTelemetry(fakeTracesExporterName) require.NoError(t, err) @@ -210,6 +262,20 @@ func TestTracesExporter_WithSpan(t *testing.T) { checkWrapSpanForTracesExporter(t, sr, set.TracerProvider.Tracer("test"), te, nil, 1) } +func TestTracesRequestExporter_WithSpan(t *testing.T) { + set := exportertest.NewNopCreateSettings() + sr := new(tracetest.SpanRecorder) + set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) + otel.SetTracerProvider(set.TracerProvider) + defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + + te, err := NewTracesRequestExporter(context.Background(), set, &fakeRequestConverter{}) + require.NoError(t, err) + require.NotNil(t, te) + + checkWrapSpanForTracesExporter(t, sr, set.TracerProvider.Tracer("test"), te, nil, 1) +} + func TestTracesExporter_WithSpan_ReturnError(t *testing.T) { set := exportertest.NewNopCreateSettings() sr := new(tracetest.SpanRecorder) @@ -225,6 +291,21 @@ func TestTracesExporter_WithSpan_ReturnError(t *testing.T) { checkWrapSpanForTracesExporter(t, sr, set.TracerProvider.Tracer("test"), te, want, 1) } +func TestTracesRequestExporter_WithSpan_ExportError(t *testing.T) { + set := exportertest.NewNopCreateSettings() + sr := new(tracetest.SpanRecorder) + set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) + otel.SetTracerProvider(set.TracerProvider) + defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + + want := errors.New("export_error") + te, err := NewTracesRequestExporter(context.Background(), set, &fakeRequestConverter{requestError: want}) + require.NoError(t, err) + require.NotNil(t, te) + + checkWrapSpanForTracesExporter(t, sr, set.TracerProvider.Tracer("test"), te, want, 1) +} + func TestTracesExporter_WithShutdown(t *testing.T) { shutdownCalled := false shutdown := func(context.Context) error { shutdownCalled = true; return nil } diff --git a/exporter/go.mod b/exporter/go.mod index 3602968d3f6..e381357c7c5 100644 --- a/exporter/go.mod +++ b/exporter/go.mod @@ -6,10 +6,10 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 github.com/stretchr/testify v1.8.4 go.opencensus.io v0.24.0 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/consumer v0.83.0 - go.opentelemetry.io/collector/extension v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/consumer v0.84.0 + go.opentelemetry.io/collector/extension v0.84.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 go.opentelemetry.io/otel v1.16.0 go.opentelemetry.io/otel/sdk v1.16.0 @@ -19,7 +19,6 @@ require ( require ( contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect - github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -46,11 +45,11 @@ require ( github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect github.com/prometheus/statsd_exporter v0.22.7 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 // indirect - go.opentelemetry.io/collector/confmap v0.83.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect + go.opentelemetry.io/collector/confmap v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/processor v0.83.0 // indirect - go.opentelemetry.io/collector/receiver v0.83.0 // indirect + go.opentelemetry.io/collector/processor v0.84.0 // indirect + go.opentelemetry.io/collector/receiver v0.84.0 // indirect go.opentelemetry.io/otel/exporters/prometheus v0.39.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect go.opentelemetry.io/otel/sdk/metric v0.39.0 // indirect diff --git a/exporter/go.sum b/exporter/go.sum index b076ebbe5b1..c0ce9fc0a07 100644 --- a/exporter/go.sum +++ b/exporter/go.sum @@ -42,7 +42,6 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= diff --git a/exporter/loggingexporter/go.mod b/exporter/loggingexporter/go.mod index 1bde59bf160..7926ef01d06 100644 --- a/exporter/loggingexporter/go.mod +++ b/exporter/loggingexporter/go.mod @@ -4,12 +4,12 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 - go.opentelemetry.io/collector/confmap v0.83.0 - go.opentelemetry.io/collector/consumer v0.83.0 - go.opentelemetry.io/collector/exporter v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 + go.opentelemetry.io/collector/confmap v0.84.0 + go.opentelemetry.io/collector/consumer v0.84.0 + go.opentelemetry.io/collector/exporter v0.84.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 go.uber.org/zap v1.25.0 golang.org/x/sys v0.11.0 @@ -32,10 +32,10 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/extension v0.83.0 // indirect + go.opentelemetry.io/collector/extension v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/processor v0.83.0 // indirect - go.opentelemetry.io/collector/receiver v0.83.0 // indirect + go.opentelemetry.io/collector/processor v0.84.0 // indirect + go.opentelemetry.io/collector/receiver v0.84.0 // indirect go.opentelemetry.io/otel v1.16.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect go.opentelemetry.io/otel/trace v1.16.0 // indirect diff --git a/exporter/otlpexporter/README.md b/exporter/otlpexporter/README.md index 3886c983bdb..9dc48422026 100644 --- a/exporter/otlpexporter/README.md +++ b/exporter/otlpexporter/README.md @@ -52,7 +52,7 @@ Several helper files are leveraged to provide additional capabilities automatica - [gRPC settings](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/configgrpc/README.md) - [TLS and mTLS settings](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/configtls/README.md) -- [Queuing, retry, sampled logger and timeout settings](https://github.com/open-telemetry/opentelemetry-collector/blob/main/exporter/exporterhelper/README.md) +- [Queuing, retry and timeout settings](https://github.com/open-telemetry/opentelemetry-collector/blob/main/exporter/exporterhelper/README.md) [beta]: https://github.com/open-telemetry/opentelemetry-collector#beta [contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib diff --git a/exporter/otlpexporter/config.go b/exporter/otlpexporter/config.go index cfaa946d009..d276f6e7c87 100644 --- a/exporter/otlpexporter/config.go +++ b/exporter/otlpexporter/config.go @@ -13,10 +13,9 @@ import ( // Config defines configuration for OTLP exporter. type Config struct { - exporterhelper.TimeoutSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. - exporterhelper.QueueSettings `mapstructure:"sending_queue"` - exporterhelper.RetrySettings `mapstructure:"retry_on_failure"` - exporterhelper.SampledLoggerSettings `mapstructure:"sampled_logger"` + exporterhelper.TimeoutSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. + exporterhelper.QueueSettings `mapstructure:"sending_queue"` + exporterhelper.RetrySettings `mapstructure:"retry_on_failure"` configgrpc.GRPCClientSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. } diff --git a/exporter/otlpexporter/config_test.go b/exporter/otlpexporter/config_test.go index 8adecd7f50d..ebc1789a41e 100644 --- a/exporter/otlpexporter/config_test.go +++ b/exporter/otlpexporter/config_test.go @@ -75,8 +75,5 @@ func TestUnmarshalConfig(t *testing.T) { BalancerName: "round_robin", Auth: &configauth.Authentication{AuthenticatorID: component.NewID("nop")}, }, - SampledLoggerSettings: exporterhelper.SampledLoggerSettings{ - Enabled: false, - }, }, cfg) } diff --git a/exporter/otlpexporter/factory.go b/exporter/otlpexporter/factory.go index 923830dfee9..3980216331a 100644 --- a/exporter/otlpexporter/factory.go +++ b/exporter/otlpexporter/factory.go @@ -43,7 +43,6 @@ func createDefaultConfig() component.Config { // We almost read 0 bytes, so no need to tune ReadBufferSize. WriteBufferSize: 512 * 1024, }, - SampledLoggerSettings: exporterhelper.NewDefaultSampledLoggerSettings(), } } diff --git a/exporter/otlpexporter/factory_test.go b/exporter/otlpexporter/factory_test.go index 44c29a1eba9..4ebb0e283ba 100644 --- a/exporter/otlpexporter/factory_test.go +++ b/exporter/otlpexporter/factory_test.go @@ -50,13 +50,13 @@ func TestCreateTracesExporter(t *testing.T) { endpoint := testutil.GetAvailableLocalAddress(t) tests := []struct { name string - config Config + config *Config mustFailOnCreate bool mustFailOnStart bool }{ { name: "NoEndpoint", - config: Config{ + config: &Config{ GRPCClientSettings: configgrpc.GRPCClientSettings{ Endpoint: "", }, @@ -65,7 +65,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "UseSecure", - config: Config{ + config: &Config{ GRPCClientSettings: configgrpc.GRPCClientSettings{ Endpoint: endpoint, TLSSetting: configtls.TLSClientSetting{ @@ -76,7 +76,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "Keepalive", - config: Config{ + config: &Config{ GRPCClientSettings: configgrpc.GRPCClientSettings{ Endpoint: endpoint, Keepalive: &configgrpc.KeepaliveClientConfig{ @@ -89,7 +89,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "NoneCompression", - config: Config{ + config: &Config{ GRPCClientSettings: configgrpc.GRPCClientSettings{ Endpoint: endpoint, Compression: "none", @@ -98,7 +98,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "GzipCompression", - config: Config{ + config: &Config{ GRPCClientSettings: configgrpc.GRPCClientSettings{ Endpoint: endpoint, Compression: configcompression.Gzip, @@ -107,7 +107,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "SnappyCompression", - config: Config{ + config: &Config{ GRPCClientSettings: configgrpc.GRPCClientSettings{ Endpoint: endpoint, Compression: configcompression.Snappy, @@ -116,7 +116,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "ZstdCompression", - config: Config{ + config: &Config{ GRPCClientSettings: configgrpc.GRPCClientSettings{ Endpoint: endpoint, Compression: configcompression.Zstd, @@ -125,7 +125,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "Headers", - config: Config{ + config: &Config{ GRPCClientSettings: configgrpc.GRPCClientSettings{ Endpoint: endpoint, Headers: map[string]configopaque.String{ @@ -137,7 +137,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "NumConsumers", - config: Config{ + config: &Config{ GRPCClientSettings: configgrpc.GRPCClientSettings{ Endpoint: endpoint, }, @@ -145,7 +145,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "CaCert", - config: Config{ + config: &Config{ GRPCClientSettings: configgrpc.GRPCClientSettings{ Endpoint: endpoint, TLSSetting: configtls.TLSClientSetting{ @@ -158,7 +158,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "CertPemFileError", - config: Config{ + config: &Config{ GRPCClientSettings: configgrpc.GRPCClientSettings{ Endpoint: endpoint, TLSSetting: configtls.TLSClientSetting{ @@ -176,7 +176,7 @@ func TestCreateTracesExporter(t *testing.T) { t.Run(tt.name, func(t *testing.T) { factory := NewFactory() set := exportertest.NewNopCreateSettings() - consumer, err := factory.CreateTracesExporter(context.Background(), set, &tt.config) + consumer, err := factory.CreateTracesExporter(context.Background(), set, tt.config) if tt.mustFailOnCreate { assert.NotNil(t, err) return diff --git a/exporter/otlpexporter/go.mod b/exporter/otlpexporter/go.mod index e39b5a2984b..9e4681a0faf 100644 --- a/exporter/otlpexporter/go.mod +++ b/exporter/otlpexporter/go.mod @@ -4,16 +4,16 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/config/configauth v0.83.0 - go.opentelemetry.io/collector/config/configcompression v0.83.0 - go.opentelemetry.io/collector/config/configgrpc v0.83.0 - go.opentelemetry.io/collector/config/configopaque v0.83.0 - go.opentelemetry.io/collector/config/configtls v0.83.0 - go.opentelemetry.io/collector/confmap v0.83.0 - go.opentelemetry.io/collector/consumer v0.83.0 - go.opentelemetry.io/collector/exporter v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/config/configauth v0.84.0 + go.opentelemetry.io/collector/config/configcompression v0.84.0 + go.opentelemetry.io/collector/config/configgrpc v0.84.0 + go.opentelemetry.io/collector/config/configopaque v0.84.0 + go.opentelemetry.io/collector/config/configtls v0.84.0 + go.opentelemetry.io/collector/confmap v0.84.0 + go.opentelemetry.io/collector/consumer v0.84.0 + go.opentelemetry.io/collector/exporter v0.84.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc google.golang.org/grpc v1.57.0 @@ -43,14 +43,14 @@ require ( github.com/mostynb/go-grpc-compression v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/config/confignet v0.83.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 // indirect - go.opentelemetry.io/collector/config/internal v0.83.0 // indirect - go.opentelemetry.io/collector/extension v0.83.0 // indirect - go.opentelemetry.io/collector/extension/auth v0.83.0 // indirect + go.opentelemetry.io/collector/config/confignet v0.84.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect + go.opentelemetry.io/collector/config/internal v0.84.0 // indirect + go.opentelemetry.io/collector/extension v0.84.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/processor v0.83.0 // indirect - go.opentelemetry.io/collector/receiver v0.83.0 // indirect + go.opentelemetry.io/collector/processor v0.84.0 // indirect + go.opentelemetry.io/collector/receiver v0.84.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.1-0.20230612162650-64be7e574a17 // indirect go.opentelemetry.io/otel v1.16.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect diff --git a/exporter/otlpexporter/testdata/config.yaml b/exporter/otlpexporter/testdata/config.yaml index e2b085c8f83..7bc4bbe3f36 100644 --- a/exporter/otlpexporter/testdata/config.yaml +++ b/exporter/otlpexporter/testdata/config.yaml @@ -25,5 +25,3 @@ keepalive: timeout: 30s permit_without_stream: true balancer_name: "round_robin" -sampled_logger: - enabled: false diff --git a/exporter/otlphttpexporter/README.md b/exporter/otlphttpexporter/README.md index 687013d47f4..5dfc1b9874c 100644 --- a/exporter/otlphttpexporter/README.md +++ b/exporter/otlphttpexporter/README.md @@ -31,9 +31,6 @@ The following settings can be optionally configured: - `timeout` (default = 30s): HTTP request time limit. For details see https://golang.org/pkg/net/http/#Client - `read_buffer_size` (default = 0): ReadBufferSize for HTTP client. - `write_buffer_size` (default = 512 * 1024): WriteBufferSize for HTTP client. -- `sampled_logger`: The logger sampler configuration. It caps the CPU and I/O load of logging while keeping a representative subset of your logs. - - `enabled` (default = true). Enables/disables sampling of logging messages. - When setting `debug` log level the sampling will be disabled regardless of the value of this property. Example: diff --git a/exporter/otlphttpexporter/config.go b/exporter/otlphttpexporter/config.go index 2c2dee71cb0..692f7e0124b 100644 --- a/exporter/otlphttpexporter/config.go +++ b/exporter/otlphttpexporter/config.go @@ -13,10 +13,9 @@ import ( // Config defines configuration for OTLP/HTTP exporter. type Config struct { - confighttp.HTTPClientSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. - exporterhelper.QueueSettings `mapstructure:"sending_queue"` - exporterhelper.RetrySettings `mapstructure:"retry_on_failure"` - exporterhelper.SampledLoggerSettings `mapstructure:"sampled_logger"` + confighttp.HTTPClientSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. + exporterhelper.QueueSettings `mapstructure:"sending_queue"` + exporterhelper.RetrySettings `mapstructure:"retry_on_failure"` // The URL to send traces to. If omitted the Endpoint + "/v1/traces" will be used. TracesEndpoint string `mapstructure:"traces_endpoint"` diff --git a/exporter/otlphttpexporter/config_test.go b/exporter/otlphttpexporter/config_test.go index c45838a744c..35b2d15a160 100644 --- a/exporter/otlphttpexporter/config_test.go +++ b/exporter/otlphttpexporter/config_test.go @@ -70,8 +70,5 @@ func TestUnmarshalConfig(t *testing.T) { Timeout: time.Second * 10, Compression: "gzip", }, - SampledLoggerSettings: exporterhelper.SampledLoggerSettings{ - Enabled: false, - }, }, cfg) } diff --git a/exporter/otlphttpexporter/factory.go b/exporter/otlphttpexporter/factory.go index 6f499e83bcf..4bdbcdf40fd 100644 --- a/exporter/otlphttpexporter/factory.go +++ b/exporter/otlphttpexporter/factory.go @@ -48,7 +48,6 @@ func createDefaultConfig() component.Config { // We almost read 0 bytes, so no need to tune ReadBufferSize. WriteBufferSize: 512 * 1024, }, - SampledLoggerSettings: exporterhelper.NewDefaultSampledLoggerSettings(), } } diff --git a/exporter/otlphttpexporter/factory_test.go b/exporter/otlphttpexporter/factory_test.go index 03762abf89c..ba6d4d1c835 100644 --- a/exporter/otlphttpexporter/factory_test.go +++ b/exporter/otlphttpexporter/factory_test.go @@ -54,13 +54,13 @@ func TestCreateTracesExporter(t *testing.T) { tests := []struct { name string - config Config + config *Config mustFailOnCreate bool mustFailOnStart bool }{ { name: "NoEndpoint", - config: Config{ + config: &Config{ HTTPClientSettings: confighttp.HTTPClientSettings{ Endpoint: "", }, @@ -69,7 +69,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "UseSecure", - config: Config{ + config: &Config{ HTTPClientSettings: confighttp.HTTPClientSettings{ Endpoint: endpoint, TLSSetting: configtls.TLSClientSetting{ @@ -80,7 +80,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "Headers", - config: Config{ + config: &Config{ HTTPClientSettings: confighttp.HTTPClientSettings{ Endpoint: endpoint, Headers: map[string]configopaque.String{ @@ -92,7 +92,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "CaCert", - config: Config{ + config: &Config{ HTTPClientSettings: confighttp.HTTPClientSettings{ Endpoint: endpoint, TLSSetting: configtls.TLSClientSetting{ @@ -105,7 +105,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "CertPemFileError", - config: Config{ + config: &Config{ HTTPClientSettings: confighttp.HTTPClientSettings{ Endpoint: endpoint, TLSSetting: configtls.TLSClientSetting{ @@ -120,7 +120,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "NoneCompression", - config: Config{ + config: &Config{ HTTPClientSettings: confighttp.HTTPClientSettings{ Endpoint: endpoint, Compression: "none", @@ -129,7 +129,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "GzipCompression", - config: Config{ + config: &Config{ HTTPClientSettings: confighttp.HTTPClientSettings{ Endpoint: endpoint, Compression: configcompression.Gzip, @@ -138,7 +138,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "SnappyCompression", - config: Config{ + config: &Config{ HTTPClientSettings: confighttp.HTTPClientSettings{ Endpoint: endpoint, Compression: configcompression.Snappy, @@ -147,7 +147,7 @@ func TestCreateTracesExporter(t *testing.T) { }, { name: "ZstdCompression", - config: Config{ + config: &Config{ HTTPClientSettings: confighttp.HTTPClientSettings{ Endpoint: endpoint, Compression: configcompression.Zstd, @@ -160,7 +160,7 @@ func TestCreateTracesExporter(t *testing.T) { t.Run(tt.name, func(t *testing.T) { factory := NewFactory() set := exportertest.NewNopCreateSettings() - consumer, err := factory.CreateTracesExporter(context.Background(), set, &tt.config) + consumer, err := factory.CreateTracesExporter(context.Background(), set, tt.config) if tt.mustFailOnCreate { assert.Error(t, err) diff --git a/exporter/otlphttpexporter/go.mod b/exporter/otlphttpexporter/go.mod index b7f45c496ed..7eab1223782 100644 --- a/exporter/otlphttpexporter/go.mod +++ b/exporter/otlphttpexporter/go.mod @@ -4,18 +4,18 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/config/configcompression v0.83.0 - go.opentelemetry.io/collector/config/confighttp v0.83.0 - go.opentelemetry.io/collector/config/configopaque v0.83.0 - go.opentelemetry.io/collector/config/configtls v0.83.0 - go.opentelemetry.io/collector/confmap v0.83.0 - go.opentelemetry.io/collector/consumer v0.83.0 - go.opentelemetry.io/collector/exporter v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/config/configcompression v0.84.0 + go.opentelemetry.io/collector/config/confighttp v0.84.0 + go.opentelemetry.io/collector/config/configopaque v0.84.0 + go.opentelemetry.io/collector/config/configtls v0.84.0 + go.opentelemetry.io/collector/confmap v0.84.0 + go.opentelemetry.io/collector/consumer v0.84.0 + go.opentelemetry.io/collector/exporter v0.84.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/collector/receiver v0.83.0 - go.opentelemetry.io/collector/receiver/otlpreceiver v0.83.0 + go.opentelemetry.io/collector/receiver v0.84.0 + go.opentelemetry.io/collector/receiver/otlpreceiver v0.84.0 go.uber.org/zap v1.25.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc google.golang.org/grpc v1.57.0 @@ -46,15 +46,15 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rs/cors v1.9.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/config/configauth v0.83.0 // indirect - go.opentelemetry.io/collector/config/configgrpc v0.83.0 // indirect - go.opentelemetry.io/collector/config/confignet v0.83.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 // indirect - go.opentelemetry.io/collector/config/internal v0.83.0 // indirect - go.opentelemetry.io/collector/extension v0.83.0 // indirect - go.opentelemetry.io/collector/extension/auth v0.83.0 // indirect + go.opentelemetry.io/collector/config/configauth v0.84.0 // indirect + go.opentelemetry.io/collector/config/configgrpc v0.84.0 // indirect + go.opentelemetry.io/collector/config/confignet v0.84.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect + go.opentelemetry.io/collector/config/internal v0.84.0 // indirect + go.opentelemetry.io/collector/extension v0.84.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/processor v0.83.0 // indirect + go.opentelemetry.io/collector/processor v0.84.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.1-0.20230612162650-64be7e574a17 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 // indirect go.opentelemetry.io/otel v1.16.0 // indirect diff --git a/exporter/otlphttpexporter/go.sum b/exporter/otlphttpexporter/go.sum index afd95da1786..61cc9fbcd14 100644 --- a/exporter/otlphttpexporter/go.sum +++ b/exporter/otlphttpexporter/go.sum @@ -130,7 +130,7 @@ cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvj cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= -cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= +cloud.google.com/go/compute v1.20.0 h1:cUOcywWuowO9It2i1KX1lIb0HH7gLv6nENKuZGnlcSo= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= diff --git a/exporter/otlphttpexporter/otlp.go b/exporter/otlphttpexporter/otlp.go index 9e2e92a34d5..b118b72f2a3 100644 --- a/exporter/otlphttpexporter/otlp.go +++ b/exporter/otlphttpexporter/otlp.go @@ -47,6 +47,8 @@ type baseExporter struct { const ( headerRetryAfter = "Retry-After" maxHTTPResponseReadBytes = 64 * 1024 + + protobufContentType = "application/x-protobuf" ) // Create new exporter. @@ -118,7 +120,7 @@ func (e *baseExporter) export(ctx context.Context, url string, request []byte, p if err != nil { return consumererror.NewPermanent(err) } - req.Header.Set("Content-Type", "application/x-protobuf") + req.Header.Set("Content-Type", protobufContentType) req.Header.Set("User-Agent", e.userAgent) resp, err := e.client.Do(req) @@ -252,16 +254,19 @@ func handlePartialSuccessResponse(resp *http.Response, partialSuccessHandler par return err } - return partialSuccessHandler(bodyBytes) + return partialSuccessHandler(bodyBytes, resp.Header.Get("Content-Type")) } -type partialSuccessHandler func(protoBytes []byte) error +type partialSuccessHandler func(bytes []byte, contentType string) error -func tracesPartialSuccessHandler(protoBytes []byte) error { +func tracesPartialSuccessHandler(protoBytes []byte, contentType string) error { + if contentType != protobufContentType { + return nil + } exportResponse := ptraceotlp.NewExportResponse() err := exportResponse.UnmarshalProto(protoBytes) if err != nil { - return err + return fmt.Errorf("error parsing protobuf response: %w", err) } partialSuccess := exportResponse.PartialSuccess() if !(partialSuccess.ErrorMessage() == "" && partialSuccess.RejectedSpans() == 0) { @@ -270,11 +275,14 @@ func tracesPartialSuccessHandler(protoBytes []byte) error { return nil } -func metricsPartialSuccessHandler(protoBytes []byte) error { +func metricsPartialSuccessHandler(protoBytes []byte, contentType string) error { + if contentType != protobufContentType { + return nil + } exportResponse := pmetricotlp.NewExportResponse() err := exportResponse.UnmarshalProto(protoBytes) if err != nil { - return err + return fmt.Errorf("error parsing protobuf response: %w", err) } partialSuccess := exportResponse.PartialSuccess() if !(partialSuccess.ErrorMessage() == "" && partialSuccess.RejectedDataPoints() == 0) { @@ -283,11 +291,14 @@ func metricsPartialSuccessHandler(protoBytes []byte) error { return nil } -func logsPartialSuccessHandler(protoBytes []byte) error { +func logsPartialSuccessHandler(protoBytes []byte, contentType string) error { + if contentType != protobufContentType { + return nil + } exportResponse := plogotlp.NewExportResponse() err := exportResponse.UnmarshalProto(protoBytes) if err != nil { - return err + return fmt.Errorf("error parsing protobuf response: %w", err) } partialSuccess := exportResponse.PartialSuccess() if !(partialSuccess.ErrorMessage() == "" && partialSuccess.RejectedLogRecords() == 0) { diff --git a/exporter/otlphttpexporter/otlp_test.go b/exporter/otlphttpexporter/otlp_test.go index 64d9223e3f5..daa54d4b7ea 100644 --- a/exporter/otlphttpexporter/otlp_test.go +++ b/exporter/otlphttpexporter/otlp_test.go @@ -687,6 +687,7 @@ func TestPartialSuccess_traces(t *testing.T) { partial.SetRejectedSpans(1) bytes, err := response.MarshalProto() require.NoError(t, err) + writer.Header().Set("Content-Type", "application/x-protobuf") _, err = writer.Write(bytes) require.NoError(t, err) }) @@ -720,6 +721,7 @@ func TestPartialSuccess_metrics(t *testing.T) { partial.SetRejectedDataPoints(1) bytes, err := response.MarshalProto() require.NoError(t, err) + writer.Header().Set("Content-Type", "application/x-protobuf") _, err = writer.Write(bytes) require.NoError(t, err) }) @@ -751,9 +753,10 @@ func TestPartialSuccess_logs(t *testing.T) { partial := response.PartialSuccess() partial.SetErrorMessage("hello") partial.SetRejectedLogRecords(1) - bytes, err := response.MarshalProto() + b, err := response.MarshalProto() require.NoError(t, err) - _, err = writer.Write(bytes) + writer.Header().Set("Content-Type", "application/x-protobuf") + _, err = writer.Write(b) require.NoError(t, err) }) defer srv.Close() @@ -789,6 +792,9 @@ func TestPartialResponse_missingHeaderButHasBody(t *testing.T) { // `-1` indicates a missing Content-Length header in the Go http standard library ContentLength: -1, Body: io.NopCloser(bytes.NewReader(data)), + Header: map[string][]string{ + "Content-Type": {"application/x-protobuf"}, + }, } err = handlePartialSuccessResponse(resp, tracesPartialSuccessHandler) assert.True(t, consumererror.IsPermanent(err)) @@ -799,6 +805,9 @@ func TestPartialResponse_missingHeaderAndBody(t *testing.T) { // `-1` indicates a missing Content-Length header in the Go http standard library ContentLength: -1, Body: io.NopCloser(bytes.NewReader([]byte{})), + Header: map[string][]string{ + "Content-Type": {"application/x-protobuf"}, + }, } err := handlePartialSuccessResponse(resp, tracesPartialSuccessHandler) assert.Nil(t, err) @@ -824,6 +833,9 @@ func TestPartialSuccess_shortContentLengthHeader(t *testing.T) { resp := &http.Response{ ContentLength: 3, Body: io.NopCloser(bytes.NewReader(data)), + Header: map[string][]string{ + "Content-Type": {"application/x-protobuf"}, + }, } err = handlePartialSuccessResponse(resp, tracesPartialSuccessHandler) assert.Error(t, err) @@ -839,6 +851,9 @@ func TestPartialSuccess_longContentLengthHeader(t *testing.T) { resp := &http.Response{ ContentLength: 4096, Body: io.NopCloser(bytes.NewReader(data)), + Header: map[string][]string{ + "Content-Type": {"application/x-protobuf"}, + }, } err = handlePartialSuccessResponse(resp, tracesPartialSuccessHandler) assert.Error(t, err) @@ -848,6 +863,9 @@ func TestPartialSuccessInvalidResponseBody(t *testing.T) { resp := &http.Response{ Body: io.NopCloser(badReader{}), ContentLength: 100, + Header: map[string][]string{ + "Content-Type": {protobufContentType}, + }, } err := handlePartialSuccessResponse(resp, tracesPartialSuccessHandler) assert.Error(t, err) @@ -873,12 +891,52 @@ func TestPartialSuccessInvalidBody(t *testing.T) { } for _, tt := range invalidBodyCases { t.Run("Invalid response body_"+tt.telemetryType, func(t *testing.T) { - err := tt.handler([]byte{1}) - assert.Error(t, err) + err := tt.handler([]byte{1}, "application/x-protobuf") + assert.ErrorContains(t, err, "error parsing protobuf response:") }) } } +func TestPartialSuccessUnsupportedContentType(t *testing.T) { + unsupportedContentTypeCases := []struct { + contentType string + }{ + { + contentType: "application/json", + }, + { + contentType: "text/plain", + }, + { + contentType: "application/octet-stream", + }, + } + for _, telemetryType := range []string{"logs", "metrics", "traces"} { + for _, tt := range unsupportedContentTypeCases { + t.Run("Unsupported content type "+tt.contentType+" "+telemetryType, func(t *testing.T) { + var handler func(b []byte, contentType string) error + switch telemetryType { + case "logs": + handler = logsPartialSuccessHandler + case "metrics": + handler = metricsPartialSuccessHandler + case "traces": + handler = tracesPartialSuccessHandler + default: + panic(telemetryType) + } + exportResponse := ptraceotlp.NewExportResponse() + exportResponse.PartialSuccess().SetErrorMessage("foo") + exportResponse.PartialSuccess().SetRejectedSpans(42) + b, err := exportResponse.MarshalProto() + require.NoError(t, err) + err = handler(b, tt.contentType) + assert.NoError(t, err) + }) + } + } +} + func createBackend(endpoint string, handler func(writer http.ResponseWriter, request *http.Request)) *httptest.Server { mux := http.NewServeMux() mux.HandleFunc(endpoint, handler) diff --git a/exporter/otlphttpexporter/testdata/config.yaml b/exporter/otlphttpexporter/testdata/config.yaml index 4dbd41941cb..a600a7bc9d6 100644 --- a/exporter/otlphttpexporter/testdata/config.yaml +++ b/exporter/otlphttpexporter/testdata/config.yaml @@ -23,5 +23,3 @@ headers: header1: 234 another: "somevalue" compression: gzip -sampled_logger: - enabled: false diff --git a/extension/auth/go.mod b/extension/auth/go.mod index 8745cd0d642..cb201cd6218 100644 --- a/extension/auth/go.mod +++ b/extension/auth/go.mod @@ -4,8 +4,8 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/extension v0.83.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/extension v0.84.0 google.golang.org/grpc v1.57.0 ) @@ -20,8 +20,8 @@ require ( github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 // indirect - go.opentelemetry.io/collector/confmap v0.83.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect + go.opentelemetry.io/collector/confmap v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect go.opentelemetry.io/otel v1.16.0 // indirect diff --git a/extension/ballastextension/go.mod b/extension/ballastextension/go.mod index b1ee2796d7f..3c85af15cbf 100644 --- a/extension/ballastextension/go.mod +++ b/extension/ballastextension/go.mod @@ -4,10 +4,10 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/confmap v0.83.0 - go.opentelemetry.io/collector/extension v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/confmap v0.84.0 + go.opentelemetry.io/collector/extension v0.84.0 go.uber.org/zap v1.25.0 ) @@ -29,7 +29,7 @@ require ( github.com/tklauser/go-sysconf v0.3.11 // indirect github.com/tklauser/numcpus v0.6.0 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect go.opentelemetry.io/otel v1.16.0 // indirect diff --git a/extension/go.mod b/extension/go.mod index 1818ede6b25..22bf75c3008 100644 --- a/extension/go.mod +++ b/extension/go.mod @@ -4,8 +4,8 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/confmap v0.83.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/confmap v0.84.0 ) require ( @@ -19,7 +19,7 @@ require ( github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect go.opentelemetry.io/otel v1.16.0 // indirect diff --git a/extension/zpagesextension/go.mod b/extension/zpagesextension/go.mod index 66f317e3bf6..65983f2bdf7 100644 --- a/extension/zpagesextension/go.mod +++ b/extension/zpagesextension/go.mod @@ -4,11 +4,11 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/config/confignet v0.83.0 - go.opentelemetry.io/collector/confmap v0.83.0 - go.opentelemetry.io/collector/extension v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/config/confignet v0.84.0 + go.opentelemetry.io/collector/confmap v0.84.0 + go.opentelemetry.io/collector/extension v0.84.0 go.opentelemetry.io/contrib/zpages v0.42.0 go.opentelemetry.io/otel/sdk v1.16.0 go.opentelemetry.io/otel/trace v1.16.0 @@ -29,7 +29,7 @@ require ( github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect go.opentelemetry.io/otel v1.16.0 // indirect diff --git a/go.mod b/go.mod index 415fef8e57e..2f66cd81ba0 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( contrib.go.opencensus.io/exporter/prometheus v0.4.2 - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.3.1 github.com/prometheus/client_golang v1.16.0 github.com/prometheus/client_model v0.4.0 github.com/prometheus/common v0.44.0 @@ -12,25 +12,27 @@ require ( github.com/spf13/cobra v1.7.0 github.com/stretchr/testify v1.8.4 go.opencensus.io v0.24.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/config/confignet v0.83.0 - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 - go.opentelemetry.io/collector/confmap v0.83.0 - go.opentelemetry.io/collector/connector v0.83.0 - go.opentelemetry.io/collector/consumer v0.83.0 - go.opentelemetry.io/collector/exporter v0.83.0 - go.opentelemetry.io/collector/extension v0.83.0 - go.opentelemetry.io/collector/extension/zpagesextension v0.83.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/config/confignet v0.84.0 + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 + go.opentelemetry.io/collector/confmap v0.84.0 + go.opentelemetry.io/collector/connector v0.84.0 + go.opentelemetry.io/collector/consumer v0.84.0 + go.opentelemetry.io/collector/exporter v0.84.0 + go.opentelemetry.io/collector/extension v0.84.0 + go.opentelemetry.io/collector/extension/zpagesextension v0.84.0 go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/collector/processor v0.83.0 - go.opentelemetry.io/collector/receiver v0.83.0 - go.opentelemetry.io/collector/semconv v0.83.0 + go.opentelemetry.io/collector/processor v0.84.0 + go.opentelemetry.io/collector/receiver v0.84.0 + go.opentelemetry.io/collector/semconv v0.84.0 go.opentelemetry.io/contrib/propagators/b3 v1.17.0 go.opentelemetry.io/otel v1.16.0 go.opentelemetry.io/otel/bridge/opencensus v0.39.0 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.39.0 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.39.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0 go.opentelemetry.io/otel/exporters/prometheus v0.39.0 go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.39.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0 @@ -41,7 +43,7 @@ require ( go.uber.org/multierr v1.11.0 go.uber.org/zap v1.25.0 golang.org/x/sys v0.11.0 - gonum.org/v1/gonum v0.13.0 + gonum.org/v1/gonum v0.14.0 google.golang.org/grpc v1.57.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -84,6 +86,7 @@ require ( go.opentelemetry.io/contrib/zpages v0.42.0 // indirect go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.39.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // indirect go.opentelemetry.io/proto/otlp v0.19.0 // indirect golang.org/x/exp v0.0.0-20230711023510-fffb14384f22 // indirect golang.org/x/net v0.14.0 // indirect diff --git a/go.sum b/go.sum index ba55da66376..b0fffcc03da 100644 --- a/go.sum +++ b/go.sum @@ -165,8 +165,8 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -332,6 +332,12 @@ go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.39.0 h1:rm+ go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.39.0/go.mod h1:sWFbI3jJ+6JdjOVepA5blpv/TJ20Hw+26561iMbWcwU= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.39.0 h1:IZXpCEtI7BbX01DRQEWTGDkvjMB6hEhiEZXS+eg2YqY= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.39.0/go.mod h1:xY111jIZtWb+pUUgT4UiiSonAaY2cD2Ts5zvuKLki3o= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 h1:cbsD4cUcviQGXdw8+bo5x2wazq10SKz8hEbtCRPcU78= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0/go.mod h1:JgXSGah17croqhJfhByOLVY719k1emAXC8MVhCIJlRs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 h1:TVQp/bboR4mhZSav+MdgXB8FaRho1RC8UwVn3T0vjVc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0/go.mod h1:I33vtIe0sR96wfrUcilIzLoA3mLHhRmz9S9Te0S3gDo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0 h1:iqjq9LAB8aK++sKVcELezzn655JnBNdsDhghU4G/So8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0/go.mod h1:hGXzO5bhhSHZnKvrDaXB82Y9DRFour0Nz/KrBh7reWw= go.opentelemetry.io/otel/exporters/prometheus v0.39.0 h1:whAaiHxOatgtKd+w0dOi//1KUxj3KoPINZdtDaDj3IA= go.opentelemetry.io/otel/exporters/prometheus v0.39.0/go.mod h1:4jo5Q4CROlCpSPsXLhymi+LYrDXd2ObU5wbKayfZs7Y= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.39.0 h1:fl2WmyenEf6LYYlfHAtCUEDyGcpwJNqD4dHGO7PVm4w= @@ -349,7 +355,7 @@ go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLk go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= @@ -557,8 +563,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.13.0 h1:a0T3bh+7fhRyqeNbiC3qVHYmkiQgit3wnNan/2c0HMM= -gonum.org/v1/gonum v0.13.0/go.mod h1:/WPYRckkfWrhWefxyYTfrTtQR0KH4iyHNuzxqXAKyAU= +gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= +gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= diff --git a/internal/tools/go.mod b/internal/tools/go.mod index c2fb07a6f2b..905d51d8958 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -6,7 +6,7 @@ require ( github.com/a8m/envsubst v1.4.2 github.com/atombender/go-jsonschema v0.12.1 github.com/client9/misspell v0.3.4 - github.com/golangci/golangci-lint v1.54.1 + github.com/golangci/golangci-lint v1.54.2 github.com/google/addlicense v1.1.1 github.com/jcchavezs/porto v0.4.0 github.com/mikefarah/yq/v4 v4.35.1 @@ -17,8 +17,8 @@ require ( go.opentelemetry.io/build-tools/multimod v0.11.0 go.opentelemetry.io/build-tools/semconvgen v0.11.0 golang.org/x/exp v0.0.0-20230711023510-fffb14384f22 - golang.org/x/tools v0.12.0 - golang.org/x/vuln v1.0.0 + golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 + golang.org/x/vuln v1.0.1 ) require ( @@ -27,8 +27,8 @@ require ( dario.cat/mergo v1.0.0 // indirect github.com/4meepo/tagalign v1.3.2 // indirect github.com/Abirdcfly/dupword v0.0.12 // indirect - github.com/Antonboom/errname v0.1.10 // indirect - github.com/Antonboom/nilnil v0.1.5 // indirect + github.com/Antonboom/errname v0.1.12 // indirect + github.com/Antonboom/nilnil v0.1.7 // indirect github.com/BurntSushi/toml v1.3.2 // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0 // indirect @@ -52,6 +52,7 @@ require ( github.com/breml/errchkjson v0.3.1 // indirect github.com/butuzov/ireturn v0.2.0 // indirect github.com/butuzov/mirror v1.1.0 // indirect + github.com/ccojocar/zxcvbn-go v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/charithe/durationcheck v0.0.10 // indirect github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 // indirect @@ -141,16 +142,15 @@ require ( github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/moricho/tparallel v0.3.1 // indirect github.com/nakabonne/nestif v0.3.1 // indirect - github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect github.com/nishanths/exhaustive v0.11.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.13.3 // indirect + github.com/nunnatsa/ginkgolinter v0.13.5 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml/v2 v2.0.9 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polyfloyd/go-errorlint v1.4.3 // indirect + github.com/polyfloyd/go-errorlint v1.4.4 // indirect github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect @@ -164,8 +164,8 @@ require ( github.com/sanity-io/litter v1.5.5 // indirect github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.23.0 // indirect - github.com/securego/gosec/v2 v2.16.0 // indirect + github.com/sashamelentyev/usestdlibvars v1.24.0 // indirect + github.com/securego/gosec/v2 v2.17.0 // indirect github.com/sergi/go-diff v1.1.0 // indirect github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect github.com/sirupsen/logrus v1.9.3 // indirect @@ -188,7 +188,7 @@ require ( github.com/subosito/gotenv v1.4.2 // indirect github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect github.com/tdakkota/asciicheck v0.2.0 // indirect - github.com/tetafro/godot v1.4.11 // indirect + github.com/tetafro/godot v1.4.14 // indirect github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 // indirect github.com/timonwong/loggercheck v0.9.4 // indirect github.com/tomarrell/wrapcheck/v2 v2.8.1 // indirect @@ -203,7 +203,7 @@ require ( github.com/ykadowak/zerologlint v0.1.3 // indirect gitlab.com/bosi/decorder v0.4.0 // indirect go.opentelemetry.io/build-tools v0.11.0 // indirect - go.tmz.dev/musttag v0.7.1 // indirect + go.tmz.dev/musttag v0.7.2 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.25.0 // indirect golang.org/x/crypto v0.12.0 // indirect @@ -220,7 +220,7 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/tools v0.4.3 // indirect + honnef.co/go/tools v0.4.5 // indirect mvdan.cc/gofumpt v0.5.0 // indirect mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect diff --git a/internal/tools/go.sum b/internal/tools/go.sum index 1396f6a0cf0..78cdfd8b5e6 100644 --- a/internal/tools/go.sum +++ b/internal/tools/go.sum @@ -46,10 +46,10 @@ github.com/4meepo/tagalign v1.3.2 h1:1idD3yxlRGV18VjqtDbqYvQ5pXqQS0wO2dn6M3XstvI github.com/4meepo/tagalign v1.3.2/go.mod h1:Q9c1rYMZJc9dPRkbQPpcBNCLEmY2njbAsXhQOZFE2dE= github.com/Abirdcfly/dupword v0.0.12 h1:56NnOyrXzChj07BDFjeRA+IUzSz01jmzEq+G4kEgFhc= github.com/Abirdcfly/dupword v0.0.12/go.mod h1:+us/TGct/nI9Ndcbcp3rgNcQzctTj68pq7TcgNpLfdI= -github.com/Antonboom/errname v0.1.10 h1:RZ7cYo/GuZqjr1nuJLNe8ZH+a+Jd9DaZzttWzak9Bls= -github.com/Antonboom/errname v0.1.10/go.mod h1:xLeiCIrvVNpUtsN0wxAh05bNIZpqE22/qDMnTBTttiA= -github.com/Antonboom/nilnil v0.1.5 h1:X2JAdEVcbPaOom2TUa1FxZ3uyuUlex0XMLGYMemu6l0= -github.com/Antonboom/nilnil v0.1.5/go.mod h1:I24toVuBKhfP5teihGWctrRiPbRKHwZIFOvc6v3HZXk= +github.com/Antonboom/errname v0.1.12 h1:oh9ak2zUtsLp5oaEd/erjB4GPu9w19NyoIskZClDcQY= +github.com/Antonboom/errname v0.1.12/go.mod h1:bK7todrzvlaZoQagP1orKzWXv59X/x0W0Io2XT1Ssro= +github.com/Antonboom/nilnil v0.1.7 h1:ofgL+BA7vlA1K2wNQOsHzLJ2Pw5B5DpWRLdDAVvvTow= +github.com/Antonboom/nilnil v0.1.7/go.mod h1:TP+ScQWVEq0eSIxqU8CbdT5DFWoHp0MbP+KMUO1BKYQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -116,6 +116,8 @@ github.com/butuzov/ireturn v0.2.0/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacM github.com/butuzov/mirror v1.1.0 h1:ZqX54gBVMXu78QLoiqdwpl2mgmoOJTk7s4p4o+0avZI= github.com/butuzov/mirror v1.1.0/go.mod h1:8Q0BdQU6rC6WILDiBM60DBfvV78OLJmMmixe7GF45AE= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/ccojocar/zxcvbn-go v1.0.1 h1:+sxrANSCj6CdadkcMnvde/GWU1vZiiXRbqYSCalV4/4= +github.com/ccojocar/zxcvbn-go v1.0.1/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -267,8 +269,8 @@ github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6 github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= -github.com/golangci/golangci-lint v1.54.1 h1:0qMrH1gkeIBqCZaaAm5Fwq4xys9rO/lJofHfZURIFFk= -github.com/golangci/golangci-lint v1.54.1/go.mod h1:JK47+qksV/t2mAz9YvndwT0ZLW4A1rvDljOs3g9jblo= +github.com/golangci/golangci-lint v1.54.2 h1:oR9zxfWYxt7hFqk6+fw6Enr+E7F0SN2nqHhJYyIb0yo= +github.com/golangci/golangci-lint v1.54.2/go.mod h1:vnsaCTPKCI2wreL9tv7RkHDwUrz3htLjed6+6UsvcwU= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= @@ -450,19 +452,17 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= -github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= -github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nishanths/exhaustive v0.11.0 h1:T3I8nUGhl/Cwu5Z2hfc92l0e04D2GEW6e0l8pzda2l0= github.com/nishanths/exhaustive v0.11.0/go.mod h1:RqwDsZ1xY0dNdqHho2z6X+bgzizwbLYOWnZbbl2wLB4= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.13.3 h1:wEvjrzSMfDdnoWkctignX9QTf4rT9f4GkQ3uVoXBmiU= -github.com/nunnatsa/ginkgolinter v0.13.3/go.mod h1:aTKXo8WddENYxNEFT+4ZxEgWXqlD9uMD3w9Bfw/ABEc= +github.com/nunnatsa/ginkgolinter v0.13.5 h1:fOsPB4CEZOPkyMqF4B9hoqOpooFWU7vWSVkCSscVpgU= +github.com/nunnatsa/ginkgolinter v0.13.5/go.mod h1:OBHy4536xtuX3102NM63XRtOyxqZOO02chsaeDWXVO8= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo/v2 v2.9.4 h1:xR7vG4IXt5RWx6FfIjyAtsoMAtnc3C/rFXBBd2AjZwE= -github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.12.0 h1:cLMgSQnXBs1eehF0Wy/FAGsgDTDmAqFR7rQylBb1nDY= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -484,8 +484,8 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polyfloyd/go-errorlint v1.4.3 h1:P6NALOLV8BrWhm6PsqOraUK05E5h8IZnpXYJ+CIg+0U= -github.com/polyfloyd/go-errorlint v1.4.3/go.mod h1:VPlWPh6hB/wruVG803SuNpLuTGNjLHYlvcdSy4RhdPA= +github.com/polyfloyd/go-errorlint v1.4.4 h1:A9gytp+p6TYqeALTYRoxJESYP8wJRETRX2xzGWFsEBU= +github.com/polyfloyd/go-errorlint v1.4.4/go.mod h1:ry5NqF7l9Q77V+XqAfUg1zfryrEtyac3G5+WVpIK0xU= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -533,10 +533,10 @@ github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/ github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.23.0 h1:01h+/2Kd+NblNItNeux0veSL5cBF1jbEOPrEhDzGYq0= -github.com/sashamelentyev/usestdlibvars v1.23.0/go.mod h1:YPwr/Y1LATzHI93CqoPUN/2BzGQ/6N/cl/KwgR0B/aU= -github.com/securego/gosec/v2 v2.16.0 h1:Pi0JKoasQQ3NnoRao/ww/N/XdynIB9NRYYZT5CyOs5U= -github.com/securego/gosec/v2 v2.16.0/go.mod h1:xvLcVZqUfo4aAQu56TNv7/Ltz6emAOQAEsrZrt7uGlI= +github.com/sashamelentyev/usestdlibvars v1.24.0 h1:MKNzmXtGh5N0y74Z/CIaJh4GlB364l0K1RUT08WSWAc= +github.com/sashamelentyev/usestdlibvars v1.24.0/go.mod h1:9cYkq+gYJ+a5W2RPdhfaSCnTVUC1OQP/bSiiBhq3OZE= +github.com/securego/gosec/v2 v2.17.0 h1:ZpAStTDKY39insEG9OH6kV3IkhQZPTq9a9eGOLOjcdI= +github.com/securego/gosec/v2 v2.17.0/go.mod h1:lt+mgC91VSmriVoJLentrMkRCYs+HLTBnUFUBuhV2hc= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= @@ -583,7 +583,6 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -605,8 +604,8 @@ github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= -github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= +github.com/tetafro/godot v1.4.14 h1:ScO641OHpf9UpHPk8fCknSuXNMpi4iFlwuWoBs3L+1s= +github.com/tetafro/godot v1.4.14/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 h1:quvGphlmUVU+nhpFa4gg4yJyTRJ13reZMDHrKwYw53M= github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= github.com/timonwong/loggercheck v0.9.4 h1:HKKhqrjcVj8sxL7K77beXh0adEm6DLjV/QOGeMXEVi4= @@ -640,7 +639,7 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= gitlab.com/bosi/decorder v0.4.0 h1:HWuxAhSxIvsITcXeP+iIRg9d1cVfvVkmlF7M68GaoDY= gitlab.com/bosi/decorder v0.4.0/go.mod h1:xarnteyUoJiOTEldDysquWKTVDCKo2TOIOIibSuWqOg= -go-simpler.org/assert v0.5.0 h1:+5L/lajuQtzmbtEfh69sr5cRf2/xZzyJhFjoOz/PPqs= +go-simpler.org/assert v0.6.0 h1:QxSrXa4oRuo/1eHMXSBFHKvJIpWABayzKldqZyugG7E= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -659,8 +658,8 @@ go.opentelemetry.io/build-tools/multimod v0.11.0 h1:QMo2Y4BlsTsWUR0LXV4gmiv5yEiX go.opentelemetry.io/build-tools/multimod v0.11.0/go.mod h1:EID7sjEGyk1FWzRdsV6rlWp43IIn8iHXGE5pM4TytyQ= go.opentelemetry.io/build-tools/semconvgen v0.11.0 h1:gQsNzy49l9JjNozybaRUl+vy0EMxYasV8w6aK+IWquc= go.opentelemetry.io/build-tools/semconvgen v0.11.0/go.mod h1:Zy04Bw3w3lT7mORe23V2BwjfJYpoza6Xz1XSMIrLTCg= -go.tmz.dev/musttag v0.7.1 h1:9lFmeSFnFfPuMq4IksHGomItE6NgKMNW2Nt2FPOhCfU= -go.tmz.dev/musttag v0.7.1/go.mod h1:oJLkpR56EsIryktZJk/B0IroSMi37YWver47fibGh5U= +go.tmz.dev/musttag v0.7.2 h1:1J6S9ipDbalBSODNT5jCep8dhZyMr4ttnjQagmGYR5s= +go.tmz.dev/musttag v0.7.2/go.mod h1:m6q5NiiSKMnQYokefa2xGoyoXnrswCbJ0AWYzf4Zs28= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -955,10 +954,10 @@ golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= -golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= -golang.org/x/vuln v1.0.0 h1:tYLAU3jD9LQr98Y+3el06lWyGMCnvzw06PIWP3LIy7g= -golang.org/x/vuln v1.0.0/go.mod h1:V0eyhHwaAaHrt42J9bgrN6rd12f6GU4T0Lu0ex2wDg4= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/vuln v1.0.1 h1:KUas02EjQK5LTuIx1OylBQdKKZ9jeugs+HiqO5HormU= +golang.org/x/vuln v1.0.1/go.mod h1:bb2hMwln/tqxg32BNY4CcxHWtHXuYa3SbIBmtsyjxtM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1087,8 +1086,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.4.3 h1:o/n5/K5gXqk8Gozvs2cnL0F2S1/g1vcGCAx2vETjITw= -honnef.co/go/tools v0.4.3/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= +honnef.co/go/tools v0.4.5 h1:YGD4H+SuIOOqsyoLOpZDWcieM28W47/zRO7f+9V3nvo= +honnef.co/go/tools v0.4.5/go.mod h1:GUV+uIBCLpdf0/v6UhHHG/yzI/z6qPskBeQCjcNB96k= mvdan.cc/gofumpt v0.5.0 h1:0EQ+Z56k8tXjj/6TQD25BFNKQXpCvT0rnansIc7Ug5E= mvdan.cc/gofumpt v0.5.0/go.mod h1:HBeVDtMKRZpXyxFciAirzdKklDlGu8aAy1wEbH5Y9js= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= diff --git a/otelcol/command_components.go b/otelcol/command_components.go index f33beb27dc3..f63fce8e55f 100644 --- a/otelcol/command_components.go +++ b/otelcol/command_components.go @@ -12,13 +12,18 @@ import ( "go.opentelemetry.io/collector/component" ) +type componentWithStability struct { + Name component.Type + Stability map[string]string +} + type componentsOutput struct { BuildInfo component.BuildInfo - Receivers []component.Type - Processors []component.Type - Exporters []component.Type - Connectors []component.Type - Extensions []component.Type + Receivers []componentWithStability + Processors []componentWithStability + Exporters []componentWithStability + Connectors []componentWithStability + Extensions []componentWithStability } // newComponentsCommand constructs a new components command using the given CollectorSettings. @@ -26,24 +31,66 @@ func newComponentsCommand(set CollectorSettings) *cobra.Command { return &cobra.Command{ Use: "components", Short: "Outputs available components in this collector distribution", + Long: "Outputs available components in this collector distribution including their stability levels. The output format is not stable and can change between releases.", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { components := componentsOutput{} for con := range set.Factories.Connectors { - components.Connectors = append(components.Connectors, con) + components.Connectors = append(components.Connectors, componentWithStability{ + Name: con, + Stability: map[string]string{ + "logs-to-logs": set.Factories.Connectors[con].LogsToLogsStability().String(), + "logs-to-metrics": set.Factories.Connectors[con].LogsToMetricsStability().String(), + "logs-to-traces": set.Factories.Connectors[con].LogsToTracesStability().String(), + + "metrics-to-logs": set.Factories.Connectors[con].MetricsToLogsStability().String(), + "metrics-to-metrics": set.Factories.Connectors[con].MetricsToMetricsStability().String(), + "metrics-to-traces": set.Factories.Connectors[con].MetricsToTracesStability().String(), + + "traces-to-logs": set.Factories.Connectors[con].TracesToLogsStability().String(), + "traces-to-metrics": set.Factories.Connectors[con].TracesToMetricsStability().String(), + "traces-to-traces": set.Factories.Connectors[con].TracesToTracesStability().String(), + }, + }) } for ext := range set.Factories.Extensions { - components.Extensions = append(components.Extensions, ext) + components.Extensions = append(components.Extensions, componentWithStability{ + Name: ext, + Stability: map[string]string{ + "extension": set.Factories.Extensions[ext].ExtensionStability().String(), + }, + }) } for prs := range set.Factories.Processors { - components.Processors = append(components.Processors, prs) + components.Processors = append(components.Processors, componentWithStability{ + Name: prs, + Stability: map[string]string{ + "logs": set.Factories.Processors[prs].LogsProcessorStability().String(), + "metrics": set.Factories.Processors[prs].MetricsProcessorStability().String(), + "traces": set.Factories.Processors[prs].TracesProcessorStability().String(), + }, + }) } for rcv := range set.Factories.Receivers { - components.Receivers = append(components.Receivers, rcv) + components.Receivers = append(components.Receivers, componentWithStability{ + Name: rcv, + Stability: map[string]string{ + "logs": set.Factories.Receivers[rcv].LogsReceiverStability().String(), + "metrics": set.Factories.Receivers[rcv].MetricsReceiverStability().String(), + "traces": set.Factories.Receivers[rcv].TracesReceiverStability().String(), + }, + }) } for exp := range set.Factories.Exporters { - components.Exporters = append(components.Exporters, exp) + components.Exporters = append(components.Exporters, componentWithStability{ + Name: exp, + Stability: map[string]string{ + "logs": set.Factories.Exporters[exp].LogsExporterStability().String(), + "metrics": set.Factories.Exporters[exp].MetricsExporterStability().String(), + "traces": set.Factories.Exporters[exp].TracesExporterStability().String(), + }, + }) } components.BuildInfo = set.BuildInfo yamlData, err := yaml.Marshal(components) diff --git a/otelcol/command_components_test.go b/otelcol/command_components_test.go index 37e923276f5..b143023eb5c 100644 --- a/otelcol/command_components_test.go +++ b/otelcol/command_components_test.go @@ -32,12 +32,53 @@ func TestNewBuildSubCommand(t *testing.T) { cmd.SetArgs([]string{"components"}) ExpectedYamlStruct := componentsOutput{ - BuildInfo: component.NewDefaultBuildInfo(), - Receivers: []component.Type{"nop"}, - Processors: []component.Type{"nop"}, - Exporters: []component.Type{"nop"}, - Connectors: []component.Type{"nop"}, - Extensions: []component.Type{"nop"}, + BuildInfo: component.NewDefaultBuildInfo(), + Receivers: []componentWithStability{{ + Name: component.Type("nop"), + Stability: map[string]string{ + "logs": "Stable", + "metrics": "Stable", + "traces": "Stable", + }, + }}, + Processors: []componentWithStability{{ + Name: component.Type("nop"), + Stability: map[string]string{ + "logs": "Stable", + "metrics": "Stable", + "traces": "Stable", + }, + }}, + Exporters: []componentWithStability{{ + Name: component.Type("nop"), + Stability: map[string]string{ + "logs": "Stable", + "metrics": "Stable", + "traces": "Stable", + }, + }}, + Connectors: []componentWithStability{{ + Name: component.Type("nop"), + Stability: map[string]string{ + "logs-to-logs": "Development", + "logs-to-metrics": "Development", + "logs-to-traces": "Development", + + "metrics-to-logs": "Development", + "metrics-to-metrics": "Development", + "metrics-to-traces": "Development", + + "traces-to-logs": "Development", + "traces-to-metrics": "Development", + "traces-to-traces": "Development", + }, + }}, + Extensions: []componentWithStability{{ + Name: component.Type("nop"), + Stability: map[string]string{ + "extension": "Stable", + }, + }}, } ExpectedOutput, err := yaml.Marshal(ExpectedYamlStruct) require.NoError(t, err) diff --git a/processor/batchprocessor/go.mod b/processor/batchprocessor/go.mod index d5305f5d305..6ccae15d497 100644 --- a/processor/batchprocessor/go.mod +++ b/processor/batchprocessor/go.mod @@ -9,13 +9,13 @@ require ( github.com/prometheus/common v0.44.0 github.com/stretchr/testify v1.8.4 go.opencensus.io v0.24.0 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 - go.opentelemetry.io/collector/confmap v0.83.0 - go.opentelemetry.io/collector/consumer v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 + go.opentelemetry.io/collector/confmap v0.84.0 + go.opentelemetry.io/collector/consumer v0.84.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/collector/processor v0.83.0 + go.opentelemetry.io/collector/processor v0.84.0 go.opentelemetry.io/otel v1.16.0 go.opentelemetry.io/otel/exporters/prometheus v0.39.0 go.opentelemetry.io/otel/metric v1.16.0 @@ -48,9 +48,9 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect github.com/prometheus/statsd_exporter v0.22.7 // indirect - go.opentelemetry.io/collector/exporter v0.83.0 // indirect + go.opentelemetry.io/collector/exporter v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/receiver v0.83.0 // indirect + go.opentelemetry.io/collector/receiver v0.84.0 // indirect go.opentelemetry.io/otel/trace v1.16.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.14.0 // indirect diff --git a/processor/go.mod b/processor/go.mod index b14c3140f9b..d86256c9b34 100644 --- a/processor/go.mod +++ b/processor/go.mod @@ -4,9 +4,9 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/consumer v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/consumer v0.84.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 go.opentelemetry.io/otel v1.16.0 go.opentelemetry.io/otel/trace v1.16.0 @@ -28,8 +28,8 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 // indirect - go.opentelemetry.io/collector/confmap v0.83.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect + go.opentelemetry.io/collector/confmap v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect go.uber.org/multierr v1.11.0 // indirect diff --git a/processor/memorylimiterprocessor/go.mod b/processor/memorylimiterprocessor/go.mod index c011079a8cb..53b7c649366 100644 --- a/processor/memorylimiterprocessor/go.mod +++ b/processor/memorylimiterprocessor/go.mod @@ -4,13 +4,13 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 - go.opentelemetry.io/collector/confmap v0.83.0 - go.opentelemetry.io/collector/consumer v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 + go.opentelemetry.io/collector/confmap v0.84.0 + go.opentelemetry.io/collector/consumer v0.84.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/collector/processor v0.83.0 + go.opentelemetry.io/collector/processor v0.84.0 go.uber.org/zap v1.25.0 ) @@ -36,9 +36,9 @@ require ( github.com/tklauser/numcpus v0.6.0 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/exporter v0.83.0 // indirect + go.opentelemetry.io/collector/exporter v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/receiver v0.83.0 // indirect + go.opentelemetry.io/collector/receiver v0.84.0 // indirect go.opentelemetry.io/otel v1.16.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect go.opentelemetry.io/otel/trace v1.16.0 // indirect diff --git a/receiver/go.mod b/receiver/go.mod index 488ab6b32b0..509ae7806bd 100644 --- a/receiver/go.mod +++ b/receiver/go.mod @@ -4,9 +4,9 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/consumer v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/consumer v0.84.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 go.opentelemetry.io/otel v1.16.0 go.opentelemetry.io/otel/sdk v1.16.0 @@ -43,11 +43,11 @@ require ( github.com/prometheus/procfs v0.10.1 // indirect github.com/prometheus/statsd_exporter v0.22.7 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 // indirect - go.opentelemetry.io/collector/confmap v0.83.0 // indirect - go.opentelemetry.io/collector/exporter v0.83.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 // indirect + go.opentelemetry.io/collector/confmap v0.84.0 // indirect + go.opentelemetry.io/collector/exporter v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/processor v0.83.0 // indirect + go.opentelemetry.io/collector/processor v0.84.0 // indirect go.opentelemetry.io/otel/exporters/prometheus v0.39.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect go.opentelemetry.io/otel/sdk/metric v0.39.0 // indirect diff --git a/receiver/otlpreceiver/README.md b/receiver/otlpreceiver/README.md index 54cb9f81efd..603e320def3 100644 --- a/receiver/otlpreceiver/README.md +++ b/receiver/otlpreceiver/README.md @@ -37,7 +37,9 @@ The following settings are configurable: Several helper files are leveraged to provide additional capabilities automatically: - [gRPC settings](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/configgrpc/README.md) including CORS +- [HTTP settings](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/confighttp/README.md) - [TLS and mTLS settings](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/configtls/README.md) +- [Auth settings](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/configauth/README.md) ## Writing with HTTP/JSON diff --git a/receiver/otlpreceiver/go.mod b/receiver/otlpreceiver/go.mod index 1b96ae510a1..ea72397faa1 100644 --- a/receiver/otlpreceiver/go.mod +++ b/receiver/otlpreceiver/go.mod @@ -6,18 +6,18 @@ require ( github.com/gogo/protobuf v1.3.2 github.com/klauspost/compress v1.16.7 github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.83.0 - go.opentelemetry.io/collector/component v0.83.0 - go.opentelemetry.io/collector/config/configgrpc v0.83.0 - go.opentelemetry.io/collector/config/confighttp v0.83.0 - go.opentelemetry.io/collector/config/confignet v0.83.0 - go.opentelemetry.io/collector/config/configtelemetry v0.83.0 - go.opentelemetry.io/collector/config/configtls v0.83.0 - go.opentelemetry.io/collector/confmap v0.83.0 - go.opentelemetry.io/collector/consumer v0.83.0 + go.opentelemetry.io/collector v0.84.0 + go.opentelemetry.io/collector/component v0.84.0 + go.opentelemetry.io/collector/config/configgrpc v0.84.0 + go.opentelemetry.io/collector/config/confighttp v0.84.0 + go.opentelemetry.io/collector/config/confignet v0.84.0 + go.opentelemetry.io/collector/config/configtelemetry v0.84.0 + go.opentelemetry.io/collector/config/configtls v0.84.0 + go.opentelemetry.io/collector/confmap v0.84.0 + go.opentelemetry.io/collector/consumer v0.84.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/collector/receiver v0.83.0 - go.opentelemetry.io/collector/semconv v0.83.0 + go.opentelemetry.io/collector/receiver v0.84.0 + go.opentelemetry.io/collector/semconv v0.84.0 go.uber.org/zap v1.25.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc google.golang.org/grpc v1.57.0 @@ -58,15 +58,15 @@ require ( github.com/prometheus/statsd_exporter v0.22.7 // indirect github.com/rs/cors v1.9.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/config/configauth v0.83.0 // indirect - go.opentelemetry.io/collector/config/configcompression v0.83.0 // indirect - go.opentelemetry.io/collector/config/configopaque v0.83.0 // indirect - go.opentelemetry.io/collector/config/internal v0.83.0 // indirect - go.opentelemetry.io/collector/exporter v0.83.0 // indirect - go.opentelemetry.io/collector/extension v0.83.0 // indirect - go.opentelemetry.io/collector/extension/auth v0.83.0 // indirect + go.opentelemetry.io/collector/config/configauth v0.84.0 // indirect + go.opentelemetry.io/collector/config/configcompression v0.84.0 // indirect + go.opentelemetry.io/collector/config/configopaque v0.84.0 // indirect + go.opentelemetry.io/collector/config/internal v0.84.0 // indirect + go.opentelemetry.io/collector/exporter v0.84.0 // indirect + go.opentelemetry.io/collector/extension v0.84.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.84.0 // indirect go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/processor v0.83.0 // indirect + go.opentelemetry.io/collector/processor v0.84.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.1-0.20230612162650-64be7e574a17 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 // indirect go.opentelemetry.io/otel v1.16.0 // indirect diff --git a/service/internal/proctelemetry/config.go b/service/internal/proctelemetry/config.go index ee20660e296..67d3122f980 100644 --- a/service/internal/proctelemetry/config.go +++ b/service/internal/proctelemetry/config.go @@ -20,6 +20,8 @@ import ( "go.opentelemetry.io/otel/bridge/opencensus" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" otelprom "go.opentelemetry.io/otel/exporters/prometheus" "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" @@ -83,7 +85,7 @@ func InitMetricReader(ctx context.Context, reader telemetry.MetricReader, asyncE return nil, nil, fmt.Errorf("unsupported metric reader type %v", reader) } -func InitSpanProcessor(_ context.Context, processor telemetry.SpanProcessor) (sdktrace.SpanProcessor, error) { +func InitSpanProcessor(ctx context.Context, processor telemetry.SpanProcessor) (sdktrace.SpanProcessor, error) { if processor.Batch != nil { if processor.Batch.Exporter.Console != nil { exp, err := stdouttrace.New( @@ -92,32 +94,23 @@ func InitSpanProcessor(_ context.Context, processor telemetry.SpanProcessor) (sd if err != nil { return nil, err } - opts := []sdktrace.BatchSpanProcessorOption{} - if processor.Batch.ExportTimeout != nil { - if *processor.Batch.ExportTimeout < 0 { - return nil, fmt.Errorf("invalid export timeout %d", *processor.Batch.ExportTimeout) - } - opts = append(opts, sdktrace.WithExportTimeout(time.Millisecond*time.Duration(*processor.Batch.ExportTimeout))) - } - if processor.Batch.MaxExportBatchSize != nil { - if *processor.Batch.MaxExportBatchSize < 0 { - return nil, fmt.Errorf("invalid batch size %d", *processor.Batch.MaxExportBatchSize) - } - opts = append(opts, sdktrace.WithMaxExportBatchSize(*processor.Batch.MaxExportBatchSize)) - } - if processor.Batch.MaxQueueSize != nil { - if *processor.Batch.MaxQueueSize < 0 { - return nil, fmt.Errorf("invalid queue size %d", *processor.Batch.MaxQueueSize) - } - opts = append(opts, sdktrace.WithMaxQueueSize(*processor.Batch.MaxQueueSize)) + return initBatchSpanProcessor(processor.Batch, exp) + } + if processor.Batch.Exporter.Otlp != nil { + var err error + var exp sdktrace.SpanExporter + switch processor.Batch.Exporter.Otlp.Protocol { + case protocolProtobufHTTP: + exp, err = initOTLPHTTPSpanExporter(ctx, processor.Batch.Exporter.Otlp) + case protocolProtobufGRPC: + exp, err = initOTLPgRPCSpanExporter(ctx, processor.Batch.Exporter.Otlp) + default: + return nil, fmt.Errorf("unsupported protocol %q", processor.Batch.Exporter.Otlp.Protocol) } - if processor.Batch.ScheduleDelay != nil { - if *processor.Batch.ScheduleDelay < 0 { - return nil, fmt.Errorf("invalid schedule delay %d", *processor.Batch.ScheduleDelay) - } - opts = append(opts, sdktrace.WithBatchTimeout(time.Millisecond*time.Duration(*processor.Batch.ScheduleDelay))) + if err != nil { + return nil, err } - return sdktrace.NewBatchSpanProcessor(exp, opts...), nil + return initBatchSpanProcessor(processor.Batch, exp) } return nil, errNoValidSpanExporter } @@ -287,7 +280,14 @@ func initOTLPgRPCExporter(ctx context.Context, otlpConfig *telemetry.OtlpMetric) } if otlpConfig.Compression != nil { - opts = append(opts, otlpmetricgrpc.WithCompressor(*otlpConfig.Compression)) + switch *otlpConfig.Compression { + case "gzip": + opts = append(opts, otlpmetricgrpc.WithCompressor(*otlpConfig.Compression)) + case "none": + break + default: + return nil, fmt.Errorf("unsupported compression %q", *otlpConfig.Compression) + } } if otlpConfig.Timeout != nil { opts = append(opts, otlpmetricgrpc.WithTimeout(time.Millisecond*time.Duration(*otlpConfig.Timeout))) @@ -335,3 +335,104 @@ func initOTLPHTTPExporter(ctx context.Context, otlpConfig *telemetry.OtlpMetric) return otlpmetrichttp.New(ctx, opts...) } + +func initOTLPgRPCSpanExporter(ctx context.Context, otlpConfig *telemetry.Otlp) (sdktrace.SpanExporter, error) { + opts := []otlptracegrpc.Option{} + + if len(otlpConfig.Endpoint) > 0 { + u, err := url.ParseRequestURI(normalizeEndpoint(otlpConfig.Endpoint)) + if err != nil { + return nil, err + } + opts = append(opts, otlptracegrpc.WithEndpoint(u.Host)) + if u.Scheme == "http" { + opts = append(opts, otlptracegrpc.WithInsecure()) + } + } + + if otlpConfig.Compression != nil { + switch *otlpConfig.Compression { + case "gzip": + opts = append(opts, otlptracegrpc.WithCompressor(*otlpConfig.Compression)) + case "none": + break + default: + return nil, fmt.Errorf("unsupported compression %q", *otlpConfig.Compression) + } + } + if otlpConfig.Timeout != nil && *otlpConfig.Timeout > 0 { + opts = append(opts, otlptracegrpc.WithTimeout(time.Millisecond*time.Duration(*otlpConfig.Timeout))) + } + if len(otlpConfig.Headers) > 0 { + opts = append(opts, otlptracegrpc.WithHeaders(otlpConfig.Headers)) + } + + return otlptracegrpc.New(ctx, opts...) +} + +func initOTLPHTTPSpanExporter(ctx context.Context, otlpConfig *telemetry.Otlp) (sdktrace.SpanExporter, error) { + opts := []otlptracehttp.Option{} + + if len(otlpConfig.Endpoint) > 0 { + u, err := url.ParseRequestURI(normalizeEndpoint(otlpConfig.Endpoint)) + if err != nil { + return nil, err + } + opts = append(opts, otlptracehttp.WithEndpoint(u.Host)) + + if u.Scheme == "http" { + opts = append(opts, otlptracehttp.WithInsecure()) + } + if len(u.Path) > 0 { + opts = append(opts, otlptracehttp.WithURLPath(u.Path)) + } + } + if otlpConfig.Compression != nil { + switch *otlpConfig.Compression { + case "gzip": + opts = append(opts, otlptracehttp.WithCompression(otlptracehttp.GzipCompression)) + case "none": + opts = append(opts, otlptracehttp.WithCompression(otlptracehttp.NoCompression)) + default: + return nil, fmt.Errorf("unsupported compression %q", *otlpConfig.Compression) + } + } + if otlpConfig.Timeout != nil && *otlpConfig.Timeout > 0 { + opts = append(opts, otlptracehttp.WithTimeout(time.Millisecond*time.Duration(*otlpConfig.Timeout))) + } + if len(otlpConfig.Headers) > 0 { + opts = append(opts, otlptracehttp.WithHeaders(otlpConfig.Headers)) + } + + return otlptracehttp.New(ctx, opts...) +} + +func initBatchSpanProcessor(bsp *telemetry.BatchSpanProcessor, exp sdktrace.SpanExporter) (sdktrace.SpanProcessor, error) { + opts := []sdktrace.BatchSpanProcessorOption{} + if bsp.ExportTimeout != nil { + if *bsp.ExportTimeout < 0 { + return nil, fmt.Errorf("invalid export timeout %d", *bsp.ExportTimeout) + } + opts = append(opts, sdktrace.WithExportTimeout(time.Millisecond*time.Duration(*bsp.ExportTimeout))) + } + if bsp.MaxExportBatchSize != nil { + if *bsp.MaxExportBatchSize < 0 { + return nil, fmt.Errorf("invalid batch size %d", *bsp.MaxExportBatchSize) + } + opts = append(opts, sdktrace.WithMaxExportBatchSize(*bsp.MaxExportBatchSize)) + } + if bsp.MaxQueueSize != nil { + if *bsp.MaxQueueSize < 0 { + return nil, fmt.Errorf("invalid queue size %d", *bsp.MaxQueueSize) + } + opts = append(opts, sdktrace.WithMaxQueueSize(*bsp.MaxQueueSize)) + } + if bsp.ScheduleDelay != nil { + if *bsp.ScheduleDelay < 0 { + return nil, fmt.Errorf("invalid schedule delay %d", *bsp.ScheduleDelay) + } + opts = append(opts, sdktrace.WithBatchTimeout(time.Millisecond*time.Duration(*bsp.ScheduleDelay))) + } + return sdktrace.NewBatchSpanProcessor(exp, opts...), nil + +} diff --git a/service/internal/proctelemetry/config_test.go b/service/internal/proctelemetry/config_test.go index 1a1fec4e4b6..cb09754e52c 100644 --- a/service/internal/proctelemetry/config_test.go +++ b/service/internal/proctelemetry/config_test.go @@ -162,7 +162,7 @@ func TestMetricReader(t *testing.T) { Otlp: &telemetry.OtlpMetric{ Protocol: "grpc/protobuf", Endpoint: "http://localhost:4317", - Compression: strPtr("gzip"), + Compression: strPtr("none"), Timeout: intPtr(1000), Headers: map[string]string{ "test": "test1", @@ -226,6 +226,7 @@ func TestMetricReader(t *testing.T) { }, }, }, + err: errors.New("unsupported compression \"invalid\""), }, { name: "periodic/otlp-http-exporter", @@ -427,6 +428,267 @@ func TestSpanProcessor(t *testing.T) { }, }, }, + { + name: "batch/otlp-exporter-invalid-protocol", + processor: telemetry.SpanProcessor{ + Batch: &telemetry.BatchSpanProcessor{ + MaxExportBatchSize: intPtr(0), + ExportTimeout: intPtr(0), + MaxQueueSize: intPtr(0), + ScheduleDelay: intPtr(0), + Exporter: telemetry.SpanExporter{ + Otlp: &telemetry.Otlp{ + Protocol: *strPtr("http/invalid"), + }, + }, + }, + }, + err: errors.New("unsupported protocol \"http/invalid\""), + }, + { + name: "batch/otlp-grpc-exporter-no-endpoint", + processor: telemetry.SpanProcessor{ + Batch: &telemetry.BatchSpanProcessor{ + MaxExportBatchSize: intPtr(0), + ExportTimeout: intPtr(0), + MaxQueueSize: intPtr(0), + ScheduleDelay: intPtr(0), + Exporter: telemetry.SpanExporter{ + Otlp: &telemetry.Otlp{ + Protocol: "grpc/protobuf", + Compression: strPtr("gzip"), + Timeout: intPtr(1000), + Headers: map[string]string{ + "test": "test1", + }, + }, + }, + }, + }, + }, + { + name: "batch/otlp-grpc-exporter", + processor: telemetry.SpanProcessor{ + Batch: &telemetry.BatchSpanProcessor{ + MaxExportBatchSize: intPtr(0), + ExportTimeout: intPtr(0), + MaxQueueSize: intPtr(0), + ScheduleDelay: intPtr(0), + Exporter: telemetry.SpanExporter{ + Otlp: &telemetry.Otlp{ + Protocol: "grpc/protobuf", + Endpoint: "http://localhost:4317", + Compression: strPtr("gzip"), + Timeout: intPtr(1000), + Headers: map[string]string{ + "test": "test1", + }, + }, + }, + }, + }, + }, + { + name: "batch/otlp-grpc-exporter-no-scheme", + processor: telemetry.SpanProcessor{ + Batch: &telemetry.BatchSpanProcessor{ + MaxExportBatchSize: intPtr(0), + ExportTimeout: intPtr(0), + MaxQueueSize: intPtr(0), + ScheduleDelay: intPtr(0), + Exporter: telemetry.SpanExporter{ + Otlp: &telemetry.Otlp{ + Protocol: "grpc/protobuf", + Endpoint: "localhost:4317", + Compression: strPtr("gzip"), + Timeout: intPtr(1000), + Headers: map[string]string{ + "test": "test1", + }, + }, + }, + }, + }, + }, + { + name: "batch/otlp-grpc-invalid-endpoint", + processor: telemetry.SpanProcessor{ + Batch: &telemetry.BatchSpanProcessor{ + MaxExportBatchSize: intPtr(0), + ExportTimeout: intPtr(0), + MaxQueueSize: intPtr(0), + ScheduleDelay: intPtr(0), + Exporter: telemetry.SpanExporter{ + Otlp: &telemetry.Otlp{ + Protocol: "grpc/protobuf", + Endpoint: " ", + Compression: strPtr("gzip"), + Timeout: intPtr(1000), + Headers: map[string]string{ + "test": "test1", + }, + }, + }, + }, + }, + err: &url.Error{Op: "parse", URL: "http:// ", Err: url.InvalidHostError(" ")}, + }, + { + name: "batch/otlp-grpc-invalid-compression", + processor: telemetry.SpanProcessor{ + Batch: &telemetry.BatchSpanProcessor{ + MaxExportBatchSize: intPtr(0), + ExportTimeout: intPtr(0), + MaxQueueSize: intPtr(0), + ScheduleDelay: intPtr(0), + Exporter: telemetry.SpanExporter{ + Otlp: &telemetry.Otlp{ + Protocol: "grpc/protobuf", + Endpoint: "localhost:4317", + Compression: strPtr("invalid"), + Timeout: intPtr(1000), + Headers: map[string]string{ + "test": "test1", + }, + }, + }, + }, + }, + err: errors.New("unsupported compression \"invalid\""), + }, + { + name: "batch/otlp-http-exporter", + processor: telemetry.SpanProcessor{ + Batch: &telemetry.BatchSpanProcessor{ + MaxExportBatchSize: intPtr(0), + ExportTimeout: intPtr(0), + MaxQueueSize: intPtr(0), + ScheduleDelay: intPtr(0), + Exporter: telemetry.SpanExporter{ + Otlp: &telemetry.Otlp{ + Protocol: "http/protobuf", + Endpoint: "http://localhost:4318", + Compression: strPtr("gzip"), + Timeout: intPtr(1000), + Headers: map[string]string{ + "test": "test1", + }, + }, + }, + }, + }, + }, + { + name: "batch/otlp-http-exporter-with-path", + processor: telemetry.SpanProcessor{ + Batch: &telemetry.BatchSpanProcessor{ + MaxExportBatchSize: intPtr(0), + ExportTimeout: intPtr(0), + MaxQueueSize: intPtr(0), + ScheduleDelay: intPtr(0), + Exporter: telemetry.SpanExporter{ + Otlp: &telemetry.Otlp{ + Protocol: "http/protobuf", + Endpoint: "http://localhost:4318/path/123", + Compression: strPtr("none"), + Timeout: intPtr(1000), + Headers: map[string]string{ + "test": "test1", + }, + }, + }, + }, + }, + }, + { + name: "batch/otlp-http-exporter-no-endpoint", + processor: telemetry.SpanProcessor{ + Batch: &telemetry.BatchSpanProcessor{ + MaxExportBatchSize: intPtr(0), + ExportTimeout: intPtr(0), + MaxQueueSize: intPtr(0), + ScheduleDelay: intPtr(0), + Exporter: telemetry.SpanExporter{ + Otlp: &telemetry.Otlp{ + Protocol: "http/protobuf", + Compression: strPtr("gzip"), + Timeout: intPtr(1000), + Headers: map[string]string{ + "test": "test1", + }, + }, + }, + }, + }, + }, + { + name: "batch/otlp-http-exporter-no-scheme", + processor: telemetry.SpanProcessor{ + Batch: &telemetry.BatchSpanProcessor{ + MaxExportBatchSize: intPtr(0), + ExportTimeout: intPtr(0), + MaxQueueSize: intPtr(0), + ScheduleDelay: intPtr(0), + Exporter: telemetry.SpanExporter{ + Otlp: &telemetry.Otlp{ + Protocol: "http/protobuf", + Endpoint: "localhost:4318", + Compression: strPtr("gzip"), + Timeout: intPtr(1000), + Headers: map[string]string{ + "test": "test1", + }, + }, + }, + }, + }, + }, + { + name: "batch/otlp-http-invalid-endpoint", + processor: telemetry.SpanProcessor{ + Batch: &telemetry.BatchSpanProcessor{ + MaxExportBatchSize: intPtr(0), + ExportTimeout: intPtr(0), + MaxQueueSize: intPtr(0), + ScheduleDelay: intPtr(0), + Exporter: telemetry.SpanExporter{ + Otlp: &telemetry.Otlp{ + Protocol: "http/protobuf", + Endpoint: " ", + Compression: strPtr("gzip"), + Timeout: intPtr(1000), + Headers: map[string]string{ + "test": "test1", + }, + }, + }, + }, + }, + err: &url.Error{Op: "parse", URL: "http:// ", Err: url.InvalidHostError(" ")}, + }, + { + name: "batch/otlp-http-invalid-compression", + processor: telemetry.SpanProcessor{ + Batch: &telemetry.BatchSpanProcessor{ + MaxExportBatchSize: intPtr(0), + ExportTimeout: intPtr(0), + MaxQueueSize: intPtr(0), + ScheduleDelay: intPtr(0), + Exporter: telemetry.SpanExporter{ + Otlp: &telemetry.Otlp{ + Protocol: "http/protobuf", + Endpoint: "localhost:4318", + Compression: strPtr("invalid"), + Timeout: intPtr(1000), + Headers: map[string]string{ + "test": "test1", + }, + }, + }, + }, + }, + err: errors.New("unsupported compression \"invalid\""), + }, } for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { diff --git a/service/service_test.go b/service/service_test.go index 555a0d5a863..2a3ec346d65 100644 --- a/service/service_test.go +++ b/service/service_test.go @@ -56,7 +56,7 @@ type ownMetricsTestCase struct { expectedLabels map[string]labelValue } -var testResourceAttrValue = "resource_attr_test_value" +var testResourceAttrValue = "resource_attr_test_value" // #nosec G101: Potential hardcoded credentials var testInstanceID = "test_instance_id" var testServiceVersion = "2022-05-20" var testServiceName = "test name" diff --git a/service/telemetry/config.go b/service/telemetry/config.go index ac91a6494b0..514ae03278a 100644 --- a/service/telemetry/config.go +++ b/service/telemetry/config.go @@ -150,14 +150,19 @@ func (sp *SpanProcessor) Unmarshal(conf *confmap.Conf) error { } if sp.Batch != nil { - if sp.Batch.Exporter.Console == nil { - return fmt.Errorf("invalid exporter configuration") - } - return nil + return sp.Batch.Exporter.Validate() } return fmt.Errorf("unsupported span processor type %s", conf.AllKeys()) } +// Validate checks for valid exporters to be configured for the SpanExporter +func (se *SpanExporter) Validate() error { + if se.Console == nil && se.Otlp == nil { + return fmt.Errorf("invalid exporter configuration") + } + return nil +} + func (mr *MetricReader) Unmarshal(conf *confmap.Conf) error { if !obsreportconfig.UseOtelWithSDKConfigurationForInternalTelemetryFeatureGate.IsEnabled() { // only unmarshal if feature gate is enabled @@ -173,17 +178,27 @@ func (mr *MetricReader) Unmarshal(conf *confmap.Conf) error { } if mr.Pull != nil { - if mr.Pull.Exporter.Prometheus == nil { - return fmt.Errorf("invalid exporter configuration") - } - return nil + return mr.Pull.Validate() } if mr.Periodic != nil { - if mr.Periodic.Exporter.Otlp == nil && mr.Periodic.Exporter.Console == nil { - return fmt.Errorf("invalid exporter configuration") - } - return nil + return mr.Periodic.Validate() } return fmt.Errorf("unsupported metric reader type %s", conf.AllKeys()) } + +// Validate checks for valid exporters to be configured for the PullMetricReader +func (pmr *PullMetricReader) Validate() error { + if pmr.Exporter.Prometheus == nil { + return fmt.Errorf("invalid exporter configuration") + } + return nil +} + +// Validate checks for valid exporters to be configured for the PeriodicMetricReader +func (pmr *PeriodicMetricReader) Validate() error { + if pmr.Exporter.Otlp == nil && pmr.Exporter.Console == nil { + return fmt.Errorf("invalid exporter configuration") + } + return nil +} diff --git a/service/telemetry/config_test.go b/service/telemetry/config_test.go index a2412a5d17b..8af1616fb92 100644 --- a/service/telemetry/config_test.go +++ b/service/telemetry/config_test.go @@ -220,6 +220,14 @@ func TestUnmarshalSpanProcessor(t *testing.T) { }, }}), }, + { + name: "valid batch processor type, valid otlp exporter", + cfg: confmap.NewFromStringMap(map[string]any{"batch": BatchSpanProcessor{ + Exporter: SpanExporter{ + Otlp: &Otlp{}, + }, + }}), + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/versions.yaml b/versions.yaml index 4ff8096671e..e5c97e2f0b3 100644 --- a/versions.yaml +++ b/versions.yaml @@ -8,7 +8,7 @@ module-sets: - go.opentelemetry.io/collector/featuregate - go.opentelemetry.io/collector/pdata beta: - version: v0.83.0 + version: v0.84.0 modules: - go.opentelemetry.io/collector - go.opentelemetry.io/collector/cmd/builder