diff --git a/.chloggen/add-curve-preferences-tls.yaml b/.chloggen/add-curve-preferences-tls.yaml new file mode 100644 index 000000000000..82aeb1496f7e --- /dev/null +++ b/.chloggen/add-curve-preferences-tls.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: configtls + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Allow users to mention their preferred curve types for ECDHE handshake + +# One or more tracking issues or pull requests related to the change +issues: [12174] + +# (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: + +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [] diff --git a/.chloggen/add-get-metrics.yaml b/.chloggen/add-get-metrics.yaml new file mode 100644 index 000000000000..85693f53a747 --- /dev/null +++ b/.chloggen/add-get-metrics.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: componenttest + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add helper to get a metric for componentest.Telemetry + +# One or more tracking issues or pull requests related to the change +issues: [12215] + +# (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: + +# 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: [api] diff --git a/.chloggen/all-optional-async.yaml b/.chloggen/all-optional-async.yaml new file mode 100644 index 000000000000..1ed218b90388 --- /dev/null +++ b/.chloggen/all-optional-async.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: bug_fix + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: mdatagen + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: All register callbacks to async instruments can now be unregistered by calling `metadata.TelemetryBuilder.Shutdown()` + +# One or more tracking issues or pull requests related to the change +issues: [12204] + +# (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: + +# 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: [api] diff --git a/.chloggen/clenup-initialization.yaml b/.chloggen/clenup-initialization.yaml new file mode 100644 index 000000000000..e7ffeed1e73e --- /dev/null +++ b/.chloggen/clenup-initialization.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: bug_fix + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: exporterhelper + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Fix bug that the exporter with new batcher may have been marked as non mutation. + +# One or more tracking issues or pull requests related to the change +issues: [12239] + +# (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: Only affects users that manually turned on `exporter.UsePullingBasedExporterQueueBatcher` featuregate. + +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [] diff --git a/.chloggen/codeboten_update-config-dependency.yaml b/.chloggen/codeboten_update-config-dependency.yaml new file mode 100644 index 000000000000..96c42b8d6cd6 --- /dev/null +++ b/.chloggen/codeboten_update-config-dependency.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: service + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: remove custom code and instead use config package to instantiate meter provider. + +# One or more tracking issues or pull requests related to the change +issues: [11611] + +# (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: + +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [] diff --git a/.chloggen/consumer-queue.yaml b/.chloggen/consumer-queue.yaml new file mode 100644 index 000000000000..cdf1c224b522 --- /dev/null +++ b/.chloggen/consumer-queue.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: breaking + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: exporterhelper + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Change queue to embed the async consumers. + +# One or more tracking issues or pull requests related to the change +issues: [12242] + +# (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: + +# 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: [api] diff --git a/.chloggen/dep-mdatagen.yaml b/.chloggen/dep-mdatagen.yaml new file mode 100644 index 000000000000..52103bb9478c --- /dev/null +++ b/.chloggen/dep-mdatagen.yaml @@ -0,0 +1,29 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: deprecation + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: metadatatest + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Deprecate metadatatest.Telemetry in favor of componenttest.Telemetry + +# One or more tracking issues or pull requests related to the change +issues: [12218] + +# (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: | + metadatatest.Telemetry -> componenttest.Telemetry | + metadatatest.SetupTelemetry -> componenttest.NewTelemetry | + metadatatest.Telemetry.NewSettings -> metadatatest.NewSettings | + metadatatest.Telemetry.AssertMetrics -> metadatatest.AssertEqual* | + +# 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: [api] diff --git a/.chloggen/deprecate-checkexporterenqueue-functions.yaml b/.chloggen/deprecate-checkexporterenqueue-functions.yaml new file mode 100644 index 000000000000..d8ee95edbc57 --- /dev/null +++ b/.chloggen/deprecate-checkexporterenqueue-functions.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: deprecation + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: component/componenttest + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Deprecate `CheckExporterEnqueue*` functions in componenenttest + +# One or more tracking issues or pull requests related to the change +issues: [12185] + +# (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: Use the `metadatatest.AssertEqualMetric` series of functions instead of `obsreporttest.CheckExporterEnqueue*` functions. + +# 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: [api] diff --git a/.chloggen/deprecate-checkexporterlogs.yaml b/.chloggen/deprecate-checkexporterlogs.yaml new file mode 100644 index 000000000000..5ae6ef2a9b71 --- /dev/null +++ b/.chloggen/deprecate-checkexporterlogs.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: deprecation + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: component/componenttest + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Deprecate CheckExporterLogs in componenenttest + +# One or more tracking issues or pull requests related to the change +issues: [12185] + +# (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: Use the `metadatatest.AssertEqualMetric` series of functions instead of `obsreporttest.CheckExporterLogs` + +# 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: [api] diff --git a/.chloggen/deprecate-checkexportermetricgauge.yaml b/.chloggen/deprecate-checkexportermetricgauge.yaml new file mode 100644 index 000000000000..11334828a65b --- /dev/null +++ b/.chloggen/deprecate-checkexportermetricgauge.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: deprecation + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: component/componenttest + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Deprecate CheckExporterMetricGauge in componenenttest + +# One or more tracking issues or pull requests related to the change +issues: [12185] + +# (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: Use the `metadatatest.AssertEqualMetric` series of functions instead of `obsreporttest.CheckReceiverMetricGauge` + +# 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: [api] diff --git a/.chloggen/deprecate-checkexportermetrics.yaml b/.chloggen/deprecate-checkexportermetrics.yaml new file mode 100644 index 000000000000..f3081d1d9ecc --- /dev/null +++ b/.chloggen/deprecate-checkexportermetrics.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: deprecation + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: component/componenttest + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Deprecate CheckExporterMetrics in componenenttest + +# One or more tracking issues or pull requests related to the change +issues: [12185] + +# (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: Use the `metadatatest.AssertEqualMetric` series of functions instead of `obsreporttest.CheckExporterMetrics` + +# 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: [api] diff --git a/.chloggen/deprecate-checkexporttraces.yaml b/.chloggen/deprecate-checkexporttraces.yaml new file mode 100644 index 000000000000..0c5b47592850 --- /dev/null +++ b/.chloggen/deprecate-checkexporttraces.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: deprecation + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: component/componenttest + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Deprecate CheckExporterTraces in componenenttest + +# One or more tracking issues or pull requests related to the change +issues: [12185] + +# (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: Use the `metadatatest.AssertEqualMetric` series of functions instead of `obsreporttest.CheckExporterTraces` + +# 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: [api] diff --git a/.chloggen/deprecate-checkreceiverlogs.yaml b/.chloggen/deprecate-checkreceiverlogs.yaml new file mode 100644 index 000000000000..e19859eeced5 --- /dev/null +++ b/.chloggen/deprecate-checkreceiverlogs.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: deprecation + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: component/componenttest + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Deprecate CheckReceiverLogs in componenenttest + +# One or more tracking issues or pull requests related to the change +issues: [12185] + +# (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: Use the `metadatatest.AssertEqualMetric` series of functions instead of `obsreporttest.CheckReceiverLogs` + +# 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: [api] diff --git a/.chloggen/deprecate-optional-async.yaml b/.chloggen/deprecate-optional-async.yaml new file mode 100644 index 000000000000..d340cc562802 --- /dev/null +++ b/.chloggen/deprecate-optional-async.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: deprecation + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: mdatagen + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Make registration of callback for async metric always optional. + +# One or more tracking issues or pull requests related to the change +issues: [12204] + +# (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: Deprecate `metadata.TelemetryBuilder.Init*` and `metadata.With*Callback` in favor of `metadata.TelemetryBuilder.Register*Callback` + +# 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: [api] diff --git a/.chloggen/set-new-queue-batching-to-beta.yaml b/.chloggen/disabled-batcher-context.yaml similarity index 89% rename from .chloggen/set-new-queue-batching-to-beta.yaml rename to .chloggen/disabled-batcher-context.yaml index f36a2ebd1ab8..79a6af801751 100644 --- a/.chloggen/set-new-queue-batching-to-beta.yaml +++ b/.chloggen/disabled-batcher-context.yaml @@ -1,16 +1,16 @@ # Use this changelog template to create an entry for release notes. # One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' -change_type: enhancement +change_type: bug_fix # The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) component: exporterhelper # A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: Set the feature gate UsePullingBasedExporterQueueBatcher to beta +note: Fix context propagation for DisabledBatcher # One or more tracking issues or pull requests related to the change -issues: [8122] +issues: [12231] # (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. diff --git a/.chloggen/done-callback.yaml b/.chloggen/done-callback.yaml new file mode 100644 index 000000000000..7a82eb2be772 --- /dev/null +++ b/.chloggen/done-callback.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: breaking + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: exporterqueue + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Change Queue interface to return a callback instead of an index + +# One or more tracking issues or pull requests related to the change +issues: [8122] + +# (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: + +# 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: [api] diff --git a/.chloggen/generate-metric-assert-funcs.yaml b/.chloggen/generate-metric-assert-funcs.yaml new file mode 100644 index 000000000000..1554bf58a40d --- /dev/null +++ b/.chloggen/generate-metric-assert-funcs.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: mdatagen + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Generate assert function for each metric in mdatagen + +# One or more tracking issues or pull requests related to the change +issues: [12179] + +# (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: + +# 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: [api] diff --git a/.chloggen/mx-psi_component-kind-structify.yaml b/.chloggen/mx-psi_component-kind-structify.yaml new file mode 100644 index 000000000000..55dfeeb7c677 --- /dev/null +++ b/.chloggen/mx-psi_component-kind-structify.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: breaking + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: component + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Change underlying type for `component.Kind` to be a struct. + +# One or more tracking issues or pull requests related to the change +issues: [12214] + +# (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: + +# 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: [api] diff --git a/.chloggen/mx-psi_extension-interface.yaml b/.chloggen/mx-psi_extension-interface.yaml new file mode 100644 index 000000000000..04cb17765c99 --- /dev/null +++ b/.chloggen/mx-psi_extension-interface.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: breaking + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: extension + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Change `extension.Extension` to be an interface that embeds `component.Component` instead of an alias + +# One or more tracking issues or pull requests related to the change +issues: [11443] + +# (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: + +# 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: [api] diff --git a/.chloggen/mx-psi_metricslevel-detailed.yaml b/.chloggen/mx-psi_metricslevel-detailed.yaml new file mode 100644 index 000000000000..a7dfd1931da3 --- /dev/null +++ b/.chloggen/mx-psi_metricslevel-detailed.yaml @@ -0,0 +1,26 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: deprecation + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: component + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Deprecate `component.TelemetrySettings.MetricsLevel` in favor of using views and 'Enabled' method. + +# One or more tracking issues or pull requests related to the change +issues: [12159] + +# (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: | + - Components will temporarily need the service to support using views. + +# 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: [api] diff --git a/.chloggen/newsettings.yaml b/.chloggen/newsettings.yaml new file mode 100644 index 000000000000..8680880df96e --- /dev/null +++ b/.chloggen/newsettings.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: metadatatest + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Generate NewSettings that accepts componenttest.Telemetry + +# One or more tracking issues or pull requests related to the change +issues: [12216] + +# (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: + +# 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: [api] diff --git a/.chloggen/pprofile-build-attributes.yaml b/.chloggen/pprofile-build-attributes.yaml new file mode 100644 index 000000000000..d65add9670de --- /dev/null +++ b/.chloggen/pprofile-build-attributes.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: pdata/pprofile + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add new helper method `FromAttributeIndices` to build a `pcommon.Map` out of `AttributeIndices`. + +# One or more tracking issues or pull requests related to the change +issues: [12176] + +# (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: + +# 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: [api] diff --git a/.chloggen/remove-deprecated-checkscrapermetrics.yaml b/.chloggen/remove-deprecated-checkscrapermetrics.yaml new file mode 100644 index 000000000000..ee42142fc6e1 --- /dev/null +++ b/.chloggen/remove-deprecated-checkscrapermetrics.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: breaking + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: component/componenttest + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Remove deprecated `CheckScraperMetrics` functions + +# One or more tracking issues or pull requests related to the change +issues: [12183] + +# (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: + +# 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: [api] diff --git a/.chloggen/service-config-validate.yaml b/.chloggen/service-config-validate.yaml new file mode 100644 index 000000000000..03abd62cb717 --- /dev/null +++ b/.chloggen/service-config-validate.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: bug_fix + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: service + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Include validation errors from telemetry.Config when validating the service config + +# One or more tracking issues or pull requests related to the change +issues: [12100] + +# (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: Previously validation errors were only printed to the console + +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [] diff --git a/.chloggen/strings-cut.yaml b/.chloggen/strings-cut.yaml new file mode 100644 index 000000000000..bcd6a24fa25d --- /dev/null +++ b/.chloggen/strings-cut.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: general + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: "Reduce memory allocations when loading configuration and parsing component names" + +# One or more tracking issues or pull requests related to the change +issues: [11964] + +# (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: + +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [] diff --git a/.chloggen/telemetry-async-err-ch.yaml b/.chloggen/telemetry-async-err-ch.yaml new file mode 100644 index 000000000000..005ff6dac5a8 --- /dev/null +++ b/.chloggen/telemetry-async-err-ch.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: bug_fix + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: service-telemetry + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: pass the missing async error channel into service telemetry settings + +# One or more tracking issues or pull requests related to the change +issues: [11417] + +# (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: + +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [] diff --git a/.chloggen/validateconfig-print-path.yaml b/.chloggen/validateconfig-print-path.yaml new file mode 100644 index 000000000000..230c5377f3e1 --- /dev/null +++ b/.chloggen/validateconfig-print-path.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: component + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Show path to invalid config in errors returned from `component.ValidateConfig` + +# One or more tracking issues or pull requests related to the change +issues: [12108] + +# (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: + +# 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: [api] diff --git a/.github/workflows/api-compatibility.yml b/.github/workflows/api-compatibility.yml index f4d270a60abb..73045db529af 100644 --- a/.github/workflows/api-compatibility.yml +++ b/.github/workflows/api-compatibility.yml @@ -33,7 +33,7 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 # Generate apidiff states of Main - name: Generate-States diff --git a/.github/workflows/build-and-test-arm.yml b/.github/workflows/build-and-test-arm.yml index 37768874fe73..0d4593f55bff 100644 --- a/.github/workflows/build-and-test-arm.yml +++ b/.github/workflows/build-and-test-arm.yml @@ -31,7 +31,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: "~1.22.8" + go-version: "~1.22.11" cache: false - name: Cache Go id: go-cache diff --git a/.github/workflows/build-and-test-windows.yaml b/.github/workflows/build-and-test-windows.yaml index 65e8672df4db..50414d757320 100644 --- a/.github/workflows/build-and-test-windows.yaml +++ b/.github/workflows/build-and-test-windows.yaml @@ -27,7 +27,7 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 cache: false - name: Cache Go uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 @@ -56,7 +56,7 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 cache: false - name: Cache Go uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 1f30626f15da..bc5caedb2727 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -23,7 +23,7 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 cache: false - name: Cache Go id: go-cache @@ -46,7 +46,7 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 cache: false - name: Cache Go id: go-cache @@ -70,7 +70,7 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 cache: false - name: Cache Go id: go-cache @@ -95,7 +95,7 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 cache: false - name: Cache Go id: go-cache @@ -200,7 +200,7 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 cache: false - name: Cache Go id: go-cache @@ -218,7 +218,7 @@ jobs: - name: Run Unit Tests With Coverage run: make gotest-with-cover - name: Upload coverage report - uses: codecov/codecov-action@1e68e06f1dbfde0e4cefc87efeba9e4643565303 # 5.1.2 + uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # 5.3.1 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} @@ -262,7 +262,7 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 cache: false - name: Cache Go id: go-cache diff --git a/.github/workflows/builder-integration-test.yaml b/.github/workflows/builder-integration-test.yaml index ce743bb722b4..c034e2793339 100644 --- a/.github/workflows/builder-integration-test.yaml +++ b/.github/workflows/builder-integration-test.yaml @@ -35,6 +35,6 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 - name: Test run: make builder-integration-test diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index ebee440f69dd..65d61fce8aba 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -33,7 +33,7 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 - name: Cache Go id: go-cache uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 9a9e5d4f0978..3d73c4e22e40 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -25,16 +25,16 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3.28.2 + uses: github/codeql-action/init@17a820bf2e43b47be2c72b39cc905417bc1ab6d0 # v3.28.6 with: languages: go - name: Autobuild - uses: github/codeql-action/autobuild@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3.28.2 + uses: github/codeql-action/autobuild@17a820bf2e43b47be2c72b39cc905417bc1ab6d0 # v3.28.6 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3.28.2 + uses: github/codeql-action/analyze@17a820bf2e43b47be2c72b39cc905417bc1ab6d0 # v3.28.6 diff --git a/.github/workflows/contrib-tests.yml b/.github/workflows/contrib-tests.yml index fc0184cebf9c..a17952b8b1c4 100644 --- a/.github/workflows/contrib-tests.yml +++ b/.github/workflows/contrib-tests.yml @@ -44,7 +44,7 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 cache: false - name: Run Contrib Tests run: | diff --git a/.github/workflows/perf.yml b/.github/workflows/perf.yml index 8bdef7ce1b25..7dc73e000a34 100644 --- a/.github/workflows/perf.yml +++ b/.github/workflows/perf.yml @@ -15,7 +15,7 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 - name: Run benchmark run: make gobenchmark diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 1310def1c0e8..58b147c68e58 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -130,7 +130,7 @@ jobs: - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 # Prepare Core for release. # - Update CHANGELOG.md file, this is done via chloggen # - Run make prepare-release PREVIOUS_VERSION=1.0.0 RELEASE_CANDIDATE=1.1.0 MODSET=stable diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 888e5a27a224..2974e26d63d1 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -64,6 +64,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3.28.2 + uses: github/codeql-action/upload-sarif@17a820bf2e43b47be2c72b39cc905417bc1ab6d0 # v3.28.6 with: sarif_file: results.sarif diff --git a/.github/workflows/tidy-dependencies.yml b/.github/workflows/tidy-dependencies.yml index a0590aafb12a..3f4f731efff4 100644 --- a/.github/workflows/tidy-dependencies.yml +++ b/.github/workflows/tidy-dependencies.yml @@ -20,7 +20,7 @@ jobs: ref: ${{ github.head_ref }} - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: ~1.22.9 + go-version: ~1.22.11 cache: false - name: Cache Go id: go-cache diff --git a/VERSIONING.md b/VERSIONING.md index 0cd399b16f79..d60a519b91e9 100644 --- a/VERSIONING.md +++ b/VERSIONING.md @@ -81,7 +81,11 @@ may become valid after a change to the validation rules. The following are explicitly considered to be breaking changes: * **Modifying struct tags related to serialization**. Struct tags used to configure serialization mechanisms (`yaml:`, `mapstructure:`, etc) are part of the structure definition and must maintain compatibility to the same extent as the -structure. +structure. However, changes are allowed when tag modifications produce a +functionally-equivalent result when serializing or deserializing the structure. +For example, adding a tag to a field so it will not be emitted during serialization +if it has a default value would not alter its value if the serialized representation +were again deserialized, so such a change would be permitted. * **Making validation rules more strict**. A valid configuration struct as defined by its `Validate` method return value must continue to be valid after a change to the validation rules, except when the configuration struct would cause an error on its intended usage (e.g. when calling a method or when passed to any method or function in any module under opentelemetry-collector). diff --git a/client/go.mod b/client/go.mod index f40a85cf911a..73c9f4930cc9 100644 --- a/client/go.mod +++ b/client/go.mod @@ -20,9 +20,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/client/go.sum b/client/go.sum index a325492a9929..edc81fe738b9 100644 --- a/client/go.sum +++ b/client/go.sum @@ -37,16 +37,16 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -82,12 +82,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/cmd/builder/README.md b/cmd/builder/README.md index 555348dca845..89e985200d58 100644 --- a/cmd/builder/README.md +++ b/cmd/builder/README.md @@ -96,6 +96,8 @@ go install go.opentelemetry.io/collector/cmd/builder@latest If installing through this method the binary will be called `builder`. +Please note that the `go.mod` file generated uses `go 1.22` as the version. Versions 1.22.3, 1.21.10, and prior of Go [do not recognize this as a valid go version](https://github.com/golang/go/commit/27ed85d4d1702e868730ab6ea2ad6326988c615c). In order to successfully generate and build a collector using ocb, you must use Go version 1.22.4+, or any version of Go 1.23 and beyond. + ## Running A build configuration file must be provided with the `--config` flag. diff --git a/cmd/mdatagen/go.mod b/cmd/mdatagen/go.mod index 45e78ee7d897..0298c657469d 100644 --- a/cmd/mdatagen/go.mod +++ b/cmd/mdatagen/go.mod @@ -62,9 +62,9 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/cmd/mdatagen/go.sum b/cmd/mdatagen/go.sum index 7fdfceddb5cf..6a856c78f65b 100644 --- a/cmd/mdatagen/go.sum +++ b/cmd/mdatagen/go.sum @@ -107,12 +107,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/cmd/mdatagen/internal/command_test.go b/cmd/mdatagen/internal/command_test.go index 15c16e241da4..058b7bff9cdc 100644 --- a/cmd/mdatagen/internal/command_test.go +++ b/cmd/mdatagen/internal/command_test.go @@ -601,10 +601,10 @@ package metadata import ( "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/embedded" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/config/configtelemetry" ) func Meter(settings component.TelemetrySettings) metric.Meter { @@ -634,10 +634,10 @@ package metadata import ( "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/embedded" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/config/configtelemetry" ) func Meter(settings component.TelemetrySettings) metric.Meter { diff --git a/cmd/mdatagen/internal/loader_test.go b/cmd/mdatagen/internal/loader_test.go index bcacf107208e..aee0293c8771 100644 --- a/cmd/mdatagen/internal/loader_test.go +++ b/cmd/mdatagen/internal/loader_test.go @@ -277,6 +277,7 @@ func TestLoadMetadata(t *testing.T) { }, "queue_length": { Enabled: true, + Stability: Stability{Level: "alpha"}, Description: "This metric is optional and therefore not initialized in NewTelemetryBuilder.", ExtendedDocumentation: "For example this metric only exists if feature A is enabled.", Unit: strPtr("{items}"), diff --git a/cmd/mdatagen/internal/samplereceiver/documentation.md b/cmd/mdatagen/internal/samplereceiver/documentation.md index 077f1bf8250a..b47d8a8ff47f 100644 --- a/cmd/mdatagen/internal/samplereceiver/documentation.md +++ b/cmd/mdatagen/internal/samplereceiver/documentation.md @@ -144,7 +144,7 @@ Queue capacity - sync gauge example. ### otelcol_queue_length -This metric is optional and therefore not initialized in NewTelemetryBuilder. +This metric is optional and therefore not initialized in NewTelemetryBuilder. [alpha] For example this metric only exists if feature A is enabled. diff --git a/cmd/mdatagen/internal/samplereceiver/factory.go b/cmd/mdatagen/internal/samplereceiver/factory.go index e7445f9cb299..df625767eff0 100644 --- a/cmd/mdatagen/internal/samplereceiver/factory.go +++ b/cmd/mdatagen/internal/samplereceiver/factory.go @@ -6,6 +6,8 @@ package samplereceiver // import "go.opentelemetry.io/collector/cmd/mdatagen/int import ( "context" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplereceiver/internal/metadata" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/consumer" @@ -27,10 +29,18 @@ func createTraces(context.Context, receiver.Settings, component.Config, consumer } func createMetrics(ctx context.Context, set receiver.Settings, _ component.Config, _ consumer.Metrics) (receiver.Metrics, error) { - telemetryBuilder, err := metadata.NewTelemetryBuilder(set.TelemetrySettings, metadata.WithProcessRuntimeTotalAllocBytesCallback(func() int64 { return 2 })) + telemetryBuilder, err := metadata.NewTelemetryBuilder(set.TelemetrySettings) + if err != nil { + return nil, err + } + err = telemetryBuilder.RegisterProcessRuntimeTotalAllocBytesCallback(func(_ context.Context, observer metric.Int64Observer) error { + observer.Observe(2) + return nil + }) if err != nil { return nil, err } + telemetryBuilder.BatchSizeTriggerSend.Add(ctx, 1) return nopReceiver{telemetryBuilder: telemetryBuilder}, nil } @@ -43,10 +53,20 @@ var nopInstance = &nopReceiver{} type nopReceiver struct { component.StartFunc - component.ShutdownFunc telemetryBuilder *metadata.TelemetryBuilder } func (r nopReceiver) initOptionalMetric() { - _, _ = r.telemetryBuilder.InitQueueLength(func() int64 { return 1 }) + _ = r.telemetryBuilder.RegisterQueueLengthCallback(func(_ context.Context, observer metric.Int64Observer) error { + observer.Observe(3) + return nil + }) +} + +// Shutdown shuts down the component. +func (r nopReceiver) Shutdown(context.Context) error { + if r.telemetryBuilder != nil { + r.telemetryBuilder.Shutdown() + } + return nil } diff --git a/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry.go b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry.go index 39e92802fd99..3e29542e5d37 100644 --- a/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry.go +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry.go @@ -5,8 +5,10 @@ package metadata import ( "context" "errors" + "sync" "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/embedded" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" @@ -23,9 +25,12 @@ func Tracer(settings component.TelemetrySettings) trace.Tracer { // TelemetryBuilder provides an interface for components to report telemetry // as defined in metadata and user config. type TelemetryBuilder struct { - meter metric.Meter - BatchSizeTriggerSend metric.Int64Counter - ProcessRuntimeTotalAllocBytes metric.Int64ObservableCounter + meter metric.Meter + mu sync.Mutex + registrations []metric.Registration + BatchSizeTriggerSend metric.Int64Counter + ProcessRuntimeTotalAllocBytes metric.Int64ObservableCounter + // TODO: Remove in v0.119.0 when remove deprecated funcs. observeProcessRuntimeTotalAllocBytes func(context.Context, metric.Observer) error QueueCapacity metric.Int64Gauge QueueLength metric.Int64ObservableGauge @@ -43,7 +48,7 @@ func (tbof telemetryBuilderOptionFunc) apply(mb *TelemetryBuilder) { tbof(mb) } -// WithProcessRuntimeTotalAllocBytesCallback sets callback for observable ProcessRuntimeTotalAllocBytes metric. +// Deprecated: [v0.119.0] use RegisterProcessRuntimeTotalAllocBytesCallback. func WithProcessRuntimeTotalAllocBytesCallback(cb func() int64, opts ...metric.ObserveOption) TelemetryBuilderOption { return telemetryBuilderOptionFunc(func(builder *TelemetryBuilder) { builder.observeProcessRuntimeTotalAllocBytes = func(_ context.Context, o metric.Observer) error { @@ -53,17 +58,23 @@ func WithProcessRuntimeTotalAllocBytesCallback(cb func() int64, opts ...metric.O }) } -// InitQueueLength configures the QueueLength metric. -func (builder *TelemetryBuilder) InitQueueLength(cb func() int64, opts ...metric.ObserveOption) (metric.Registration, error) { - var err error - builder.QueueLength, err = builder.meter.Int64ObservableGauge( - "otelcol_queue_length", - metric.WithDescription("This metric is optional and therefore not initialized in NewTelemetryBuilder."), - metric.WithUnit("{items}"), - ) +// RegisterProcessRuntimeTotalAllocBytesCallback sets callback for observable ProcessRuntimeTotalAllocBytes metric. +func (builder *TelemetryBuilder) RegisterProcessRuntimeTotalAllocBytesCallback(cb metric.Int64Callback) error { + reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { + cb(ctx, &observerInt64{inst: builder.ProcessRuntimeTotalAllocBytes, obs: o}) + return nil + }, builder.ProcessRuntimeTotalAllocBytes) if err != nil { - return nil, err + return err } + builder.mu.Lock() + defer builder.mu.Unlock() + builder.registrations = append(builder.registrations, reg) + return nil +} + +// Deprecated: [v0.119.0] use RegisterQueueLengthCallback. +func (builder *TelemetryBuilder) InitQueueLength(cb func() int64, opts ...metric.ObserveOption) (metric.Registration, error) { reg, err := builder.meter.RegisterCallback(func(_ context.Context, o metric.Observer) error { o.ObserveInt64(builder.QueueLength, cb(), opts...) return nil @@ -71,6 +82,40 @@ func (builder *TelemetryBuilder) InitQueueLength(cb func() int64, opts ...metric return reg, err } +// RegisterQueueLengthCallback sets callback for observable QueueLength metric. +func (builder *TelemetryBuilder) RegisterQueueLengthCallback(cb metric.Int64Callback) error { + reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { + cb(ctx, &observerInt64{inst: builder.QueueLength, obs: o}) + return nil + }, builder.QueueLength) + if err != nil { + return err + } + builder.mu.Lock() + defer builder.mu.Unlock() + builder.registrations = append(builder.registrations, reg) + return nil +} + +type observerInt64 struct { + embedded.Int64Observer + inst metric.Int64Observable + obs metric.Observer +} + +func (oi *observerInt64) Observe(value int64, opts ...metric.ObserveOption) { + oi.obs.ObserveInt64(oi.inst, value, opts...) +} + +// Shutdown unregister all registered callbacks for async instruments. +func (builder *TelemetryBuilder) Shutdown() { + builder.mu.Lock() + defer builder.mu.Unlock() + for _, reg := range builder.registrations { + reg.Unregister() + } +} + // NewTelemetryBuilder provides a struct with methods to update all internal telemetry // for a component func NewTelemetryBuilder(settings component.TelemetrySettings, options ...TelemetryBuilderOption) (*TelemetryBuilder, error) { @@ -92,14 +137,25 @@ func NewTelemetryBuilder(settings component.TelemetrySettings, options ...Teleme metric.WithUnit("By"), ) errs = errors.Join(errs, err) - _, err = builder.meter.RegisterCallback(builder.observeProcessRuntimeTotalAllocBytes, builder.ProcessRuntimeTotalAllocBytes) - errs = errors.Join(errs, err) + if builder.observeProcessRuntimeTotalAllocBytes != nil { + reg, err := builder.meter.RegisterCallback(builder.observeProcessRuntimeTotalAllocBytes, builder.ProcessRuntimeTotalAllocBytes) + errs = errors.Join(errs, err) + if err == nil { + builder.registrations = append(builder.registrations, reg) + } + } builder.QueueCapacity, err = builder.meter.Int64Gauge( "otelcol_queue_capacity", metric.WithDescription("Queue capacity - sync gauge example."), metric.WithUnit("{items}"), ) errs = errors.Join(errs, err) + builder.QueueLength, err = builder.meter.Int64ObservableGauge( + "otelcol_queue_length", + metric.WithDescription("This metric is optional and therefore not initialized in NewTelemetryBuilder. [alpha]"), + metric.WithUnit("{items}"), + ) + errs = errors.Join(errs, err) builder.RequestDuration, err = builder.meter.Float64Histogram( "otelcol_request_duration", metric.WithDescription("Duration of request [alpha]"), diff --git a/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest.go b/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest.go index 194def3a39db..f5e2b59abff0 100644 --- a/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest.go +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest.go @@ -16,26 +16,35 @@ import ( "go.opentelemetry.io/collector/receiver/receivertest" ) +// Deprecated: [v0.119.0] Use componenttest.Telemetry type Telemetry struct { - componenttest.Telemetry + *componenttest.Telemetry } +// Deprecated: [v0.119.0] Use componenttest.NewTelemetry func SetupTelemetry(opts ...componenttest.TelemetryOption) Telemetry { return Telemetry{Telemetry: componenttest.NewTelemetry(opts...)} } + +// Deprecated: [v0.119.0] Use metadatatest.NewSettings func (tt *Telemetry) NewSettings() receiver.Settings { + return NewSettings(tt.Telemetry) +} + +func NewSettings(tt *componenttest.Telemetry) receiver.Settings { set := receivertest.NewNopSettings() set.ID = component.NewID(component.MustNewType("sample")) set.TelemetrySettings = tt.NewTelemetrySettings() return set } +// Deprecated: [v0.119.0] Use metadatatest.AssertEqual* func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { var md metricdata.ResourceMetrics require.NoError(t, tt.Reader.Collect(context.Background(), &md)) // ensure all required metrics are present for _, want := range expected { - got := getMetric(want.Name, md) + got := getMetricFromResource(want.Name, md) metricdatatest.AssertEqual(t, want, got, opts...) } @@ -43,7 +52,82 @@ func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, require.Equal(t, len(expected), lenMetrics(md)) } -func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { +func AssertEqualBatchSizeTriggerSend(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_batch_size_trigger_send", + Description: "Number of times the batch was sent due to a size trigger [deprecated since v0.110.0]", + Unit: "{times}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_batch_size_trigger_send") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessRuntimeTotalAllocBytes(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_process_runtime_total_alloc_bytes", + Description: "Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc')", + Unit: "By", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_process_runtime_total_alloc_bytes") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualQueueCapacity(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_queue_capacity", + Description: "Queue capacity - sync gauge example.", + Unit: "{items}", + Data: metricdata.Gauge[int64]{ + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_queue_capacity") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualQueueLength(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_queue_length", + Description: "This metric is optional and therefore not initialized in NewTelemetryBuilder. [alpha]", + Unit: "{items}", + Data: metricdata.Gauge[int64]{ + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_queue_length") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualRequestDuration(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.HistogramDataPoint[float64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_request_duration", + Description: "Duration of request [alpha]", + Unit: "s", + Data: metricdata.Histogram[float64]{ + Temporality: metricdata.CumulativeTemporality, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_request_duration") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func getMetricFromResource(name string, got metricdata.ResourceMetrics) metricdata.Metrics { for _, sm := range got.ScopeMetrics { for _, m := range sm.Metrics { if m.Name == name { diff --git a/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest_test.go b/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest_test.go index ccd897ac3cc7..573627394cc5 100644 --- a/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest_test.go +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/sdk/metric/metricdata" "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" @@ -15,12 +16,17 @@ import ( func TestSetupTelemetry(t *testing.T) { testTel := SetupTelemetry() - tb, err := metadata.NewTelemetryBuilder( - testTel.NewTelemetrySettings(), - metadata.WithProcessRuntimeTotalAllocBytesCallback(func() int64 { return 1 }), - ) + tb, err := metadata.NewTelemetryBuilder(testTel.NewTelemetrySettings()) require.NoError(t, err) - require.NotNil(t, tb) + defer tb.Shutdown() + require.NoError(t, tb.RegisterProcessRuntimeTotalAllocBytesCallback(func(_ context.Context, observer metric.Int64Observer) error { + observer.Observe(1) + return nil + })) + require.NoError(t, tb.RegisterQueueLengthCallback(func(_ context.Context, observer metric.Int64Observer) error { + observer.Observe(1) + return nil + })) tb.BatchSizeTriggerSend.Add(context.Background(), 1) tb.QueueCapacity.Record(context.Background(), 1) tb.RequestDuration.Record(context.Background(), 1) @@ -60,6 +66,16 @@ func TestSetupTelemetry(t *testing.T) { }, }, }, + { + Name: "otelcol_queue_length", + Description: "This metric is optional and therefore not initialized in NewTelemetryBuilder. [alpha]", + Unit: "{items}", + Data: metricdata.Gauge[int64]{ + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, { Name: "otelcol_request_duration", Description: "Duration of request [alpha]", @@ -72,5 +88,21 @@ func TestSetupTelemetry(t *testing.T) { }, }, }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + AssertEqualBatchSizeTriggerSend(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessRuntimeTotalAllocBytes(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualQueueCapacity(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualQueueLength(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualRequestDuration(t, testTel.Telemetry, + []metricdata.HistogramDataPoint[float64]{{}}, metricdatatest.IgnoreValue(), + metricdatatest.IgnoreTimestamp()) + require.NoError(t, testTel.Shutdown(context.Background())) } diff --git a/cmd/mdatagen/internal/samplereceiver/metadata.yaml b/cmd/mdatagen/internal/samplereceiver/metadata.yaml index 8014e3e5849a..45eab3b045a6 100644 --- a/cmd/mdatagen/internal/samplereceiver/metadata.yaml +++ b/cmd/mdatagen/internal/samplereceiver/metadata.yaml @@ -190,6 +190,8 @@ telemetry: monotonic: true queue_length: enabled: true + stability: + level: alpha description: This metric is optional and therefore not initialized in NewTelemetryBuilder. extended_documentation: For example this metric only exists if feature A is enabled. unit: "{items}" diff --git a/cmd/mdatagen/internal/samplereceiver/metrics_test.go b/cmd/mdatagen/internal/samplereceiver/metrics_test.go index 95e620f8c771..a675639ab5fd 100644 --- a/cmd/mdatagen/internal/samplereceiver/metrics_test.go +++ b/cmd/mdatagen/internal/samplereceiver/metrics_test.go @@ -26,84 +26,30 @@ func TestGeneratedMetrics(t *testing.T) { } func TestComponentTelemetry(t *testing.T) { - tt := metadatatest.SetupTelemetry() + tt := componenttest.NewTelemetry() factory := NewFactory() - receiver, err := factory.CreateMetrics(context.Background(), tt.NewSettings(), componenttest.NewNopHost(), new(consumertest.MetricsSink)) + receiver, err := factory.CreateMetrics(context.Background(), metadatatest.NewSettings(tt), componenttest.NewNopHost(), new(consumertest.MetricsSink)) require.NoError(t, err) - tt.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_batch_size_trigger_send", - Description: "Number of times the batch was sent due to a size trigger [deprecated since v0.110.0]", - Unit: "{times}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 1, - }, - }, + metadatatest.AssertEqualBatchSizeTriggerSend(t, tt, + []metricdata.DataPoint[int64]{ + { + Value: 1, }, - }, - { - Name: "otelcol_process_runtime_total_alloc_bytes", - Description: "Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc')", - Unit: "By", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 2, - }, - }, + }, metricdatatest.IgnoreTimestamp()) + metadatatest.AssertEqualProcessRuntimeTotalAllocBytes(t, tt, + []metricdata.DataPoint[int64]{ + { + Value: 2, }, - }, - }, metricdatatest.IgnoreTimestamp()) + }, metricdatatest.IgnoreTimestamp()) rcv, ok := receiver.(nopReceiver) require.True(t, ok) rcv.initOptionalMetric() - tt.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_batch_size_trigger_send", - Description: "Number of times the batch was sent due to a size trigger [deprecated since v0.110.0]", - Unit: "{times}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 1, - }, - }, + metadatatest.AssertEqualQueueLength(t, tt, + []metricdata.DataPoint[int64]{ + { + Value: 3, }, - }, - { - Name: "otelcol_process_runtime_total_alloc_bytes", - Description: "Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc')", - Unit: "By", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 2, - }, - }, - }, - }, - { - Name: "otelcol_queue_length", - Description: "This metric is optional and therefore not initialized in NewTelemetryBuilder.", - Unit: "{items}", - Data: metricdata.Gauge[int64]{ - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 1, - }, - }, - }, - }, - }, metricdatatest.IgnoreTimestamp()) + }, metricdatatest.IgnoreTimestamp()) require.NoError(t, tt.Shutdown(context.Background())) } diff --git a/cmd/mdatagen/internal/templates/telemetry.go.tmpl b/cmd/mdatagen/internal/templates/telemetry.go.tmpl index bb54518232ae..e95e63081167 100644 --- a/cmd/mdatagen/internal/templates/telemetry.go.tmpl +++ b/cmd/mdatagen/internal/templates/telemetry.go.tmpl @@ -7,20 +7,19 @@ import ( {{- range $_, $metric := .Telemetry.Metrics }} {{- if $metric.Data.Async }} "context" - {{- break}} + "sync" + +{{- break}} {{- end }} {{- end }} "errors" {{- end }} "go.opentelemetry.io/otel/metric" - {{- if .Telemetry.Metrics }} - noopmetric "go.opentelemetry.io/otel/metric/noop" - {{- end }} + "go.opentelemetry.io/otel/metric/embedded" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/config/configtelemetry" ) func Meter(settings component.TelemetrySettings) metric.Meter { @@ -32,13 +31,16 @@ func Tracer(settings component.TelemetrySettings) trace.Tracer { } {{- if .Telemetry.Metrics }} -// TelemetryBuilder provides an interface for components to report telemetry +// TelemetryBuilder provides an interface for components to report telemetry // as defined in metadata and user config. type TelemetryBuilder struct { meter metric.Meter + mu sync.Mutex + registrations []metric.Registration {{- range $name, $metric := .Telemetry.Metrics }} {{ $name.Render }} metric.{{ $metric.Data.Instrument }} {{- if and ($metric.Data.Async) (not $metric.Optional) }} + // TODO: Remove in v0.119.0 when remove deprecated funcs. observe{{ $name.Render }} func(context.Context, metric.Observer) error {{- end }} {{- end }} @@ -55,35 +57,19 @@ func (tbof telemetryBuilderOptionFunc) apply(mb *TelemetryBuilder) { tbof(mb) } - {{- range $name, $metric := .Telemetry.Metrics }} -{{- if $metric.Optional }} -// Init{{ $name.Render }} configures the {{ $name.Render }} metric. -func (builder *TelemetryBuilder) Init{{ $name.Render }}({{ if $metric.Data.Async -}}cb func() {{ $metric.Data.BasicType }}{{- end }}, opts ...metric.ObserveOption) (metric.Registration, error) { - var err error - builder.{{ $name.Render }}, err = builder.meter.{{ $metric.Data.Instrument }}( - "otelcol_{{ $name }}", - metric.WithDescription("{{ $metric.Description }}"), - metric.WithUnit("{{ $metric.Unit }}"), - {{- if eq $metric.Data.Type "Histogram" -}} - {{ if $metric.Data.Boundaries -}}metric.WithExplicitBucketBoundaries([]float64{ {{- range $metric.Data.Boundaries }} {{.}}, {{- end }} }...),{{- end }} - {{- end }} - ) - {{- if $metric.Data.Async }} - if err != nil { - return nil, err - } + {{- if $metric.Optional }} +// Deprecated: [v0.119.0] use Register{{ $name.Render }}Callback. +func (builder *TelemetryBuilder) Init{{ $name.Render }}({{ if $metric.Data.Async -}}cb func() {{ $metric.Data.BasicType }}, {{- end }}opts ...metric.ObserveOption) (metric.Registration, error) { reg, err := builder.meter.RegisterCallback(func(_ context.Context, o metric.Observer) error { o.Observe{{ casesTitle $metric.Data.BasicType }}(builder.{{ $name.Render }}, cb(), opts...) return nil }, builder.{{ $name.Render }}) - {{- end }} return reg, err } - {{- else }} - {{ if $metric.Data.Async -}} -// With{{ $name.Render }}Callback sets callback for observable {{ $name.Render }} metric. + {{ if $metric.Data.Async -}} +// Deprecated: [v0.119.0] use Register{{ $name.Render }}Callback. func With{{ $name.Render }}Callback(cb func() {{ $metric.Data.BasicType }}, opts ...metric.ObserveOption) TelemetryBuilderOption { return telemetryBuilderOptionFunc(func(builder *TelemetryBuilder) { builder.observe{{ $name.Render }} = func(_ context.Context, o metric.Observer) error { @@ -92,10 +78,70 @@ func With{{ $name.Render }}Callback(cb func() {{ $metric.Data.BasicType }}, opts } }) } + {{- end }} {{- end }} + + {{ if $metric.Data.Async -}} +// Register{{ $name.Render }}Callback sets callback for observable {{ $name.Render }} metric. +func (builder *TelemetryBuilder) Register{{ $name.Render }}Callback(cb metric.{{ casesTitle $metric.Data.BasicType }}Callback) error { + reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { + cb(ctx, &observer{{ casesTitle $metric.Data.BasicType }}{inst : builder.{{ $name.Render }}, obs: o}) + return nil + }, builder.{{ $name.Render }}) + if err != nil { + return err + } + builder.mu.Lock() + defer builder.mu.Unlock() + builder.registrations = append(builder.registrations, reg) + return nil +} + {{- end }} + +{{- end }} + +{{- range $name, $metric := .Telemetry.Metrics }} +{{- if $metric.Data.Async }} + {{ if eq $metric.Data.BasicType "int64" -}} +type observerInt64 struct { + embedded.Int64Observer + inst metric.Int64Observable + obs metric.Observer +} + +func (oi *observerInt64) Observe(value int64, opts ...metric.ObserveOption) { + oi.obs.ObserveInt64(oi.inst, value, opts...) +} + {{ break }} {{- end }} {{- end }} +{{- end }} + +{{- range $name, $metric := .Telemetry.Metrics }} +{{- if $metric.Data.Async }} +{{ if eq $metric.Data.BasicType "float64" -}} +type observerFloat64 struct { + embedded.Float64Observer + inst metric.Float64Observable + obs metric.Observer +} + +func (oi *observerFloat64) Observe(value float64, opts ...metric.ObserveOption) { + oi.obs.ObserveFloat64(oi.inst, value, opts...) +} +{{ break }} +{{- end }} +{{- end }} +{{- end }} +// Shutdown unregister all registered callbacks for async instruments. +func (builder *TelemetryBuilder) Shutdown() { + builder.mu.Lock() + defer builder.mu.Unlock() + for _, reg := range builder.registrations { + reg.Unregister() + } +} // NewTelemetryBuilder provides a struct with methods to update all internal telemetry // for a component @@ -108,7 +154,6 @@ func NewTelemetryBuilder(settings component.TelemetrySettings, options ...Teleme var err, errs error {{- range $name, $metric := .Telemetry.Metrics }} - {{- if not $metric.Optional }} builder.{{ $name.Render }}, err = builder.meter.{{ $metric.Data.Instrument }}( "otelcol_{{ $name }}", metric.WithDescription("{{ $metric.Description }}{{ $metric.Stability }}"), @@ -118,10 +163,14 @@ func NewTelemetryBuilder(settings component.TelemetrySettings, options ...Teleme {{- end }} ) errs = errors.Join(errs, err) - {{- if $metric.Data.Async }} - _, err = builder.meter.RegisterCallback(builder.observe{{ $name.Render }}, builder.{{ $name.Render }}) - errs = errors.Join(errs, err) - {{- end }} + {{- if and ($metric.Data.Async) (not $metric.Optional) }} + if builder.observe{{ $name.Render }} != nil { + reg, err := builder.meter.RegisterCallback(builder.observe{{ $name.Render }}, builder.{{ $name.Render }}) + errs = errors.Join(errs, err) + if err == nil { + builder.registrations = append(builder.registrations, reg) + } + } {{- end }} {{- end }} return &builder, errs diff --git a/cmd/mdatagen/internal/templates/telemetrytest.go.tmpl b/cmd/mdatagen/internal/templates/telemetrytest.go.tmpl index 5aede0b5c5c2..a5c538af41b1 100644 --- a/cmd/mdatagen/internal/templates/telemetrytest.go.tmpl +++ b/cmd/mdatagen/internal/templates/telemetrytest.go.tmpl @@ -20,29 +20,37 @@ import ( {{- end }} ) +// Deprecated: [v0.119.0] Use componenttest.Telemetry type Telemetry struct { - componenttest.Telemetry + *componenttest.Telemetry } +// Deprecated: [v0.119.0] Use componenttest.NewTelemetry func SetupTelemetry(opts ...componenttest.TelemetryOption) Telemetry { return Telemetry{ Telemetry: componenttest.NewTelemetry(opts...) } } -{{- if or isConnector isExporter isExtension isProcessor isReceiver isScraper }} +{{ if or isConnector isExporter isExtension isProcessor isReceiver isScraper }} +// Deprecated: [v0.119.0] Use {{ .Package }}test.NewSettings func (tt *Telemetry) NewSettings() {{ .Status.Class }}.Settings { - set := {{ .Status.Class }}test.NewNopSettings() - set.ID = component.NewID(component.MustNewType("{{ .Type }}")) - set.TelemetrySettings = tt.NewTelemetrySettings() - return set + return NewSettings(tt.Telemetry) +} + +func NewSettings(tt *componenttest.Telemetry) {{ .Status.Class }}.Settings { +set := {{ .Status.Class }}test.NewNopSettings() +set.ID = component.NewID(component.MustNewType("{{ .Type }}")) +set.TelemetrySettings = tt.NewTelemetrySettings() +return set } {{- end }} +// Deprecated: [v0.119.0] Use {{ .Package }}test.AssertEqual* func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { var md metricdata.ResourceMetrics require.NoError(t, tt.Reader.Collect(context.Background(), &md)) // ensure all required metrics are present for _, want := range expected { - got := getMetric(want.Name, md) + got := getMetricFromResource(want.Name, md) metricdatatest.AssertEqual(t, want, got, opts...) } @@ -50,7 +58,31 @@ func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, require.Equal(t, len(expected), lenMetrics(md)) } -func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { +{{ range $name, $metric := .Telemetry.Metrics }} + +func AssertEqual{{ $name.Render }}(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.{{- if eq $metric.Data.Type "Histogram" }} {{$metric.Data.Type}} {{- end }}DataPoint[{{ $metric.Data.BasicType }}], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_{{ $name }}", + Description: "{{ $metric.Description }}{{ $metric.Stability }}", + Unit: "{{ $metric.Unit }}", + Data: metricdata.{{ $metric.Data.Type }}[{{ $metric.Data.BasicType }}]{ + {{- if $metric.Data.HasAggregated }} + Temporality: metricdata.CumulativeTemporality, + {{- end }} + {{- if $metric.Data.HasMonotonic }} + IsMonotonic: {{ $metric.Data.Monotonic }}, + {{- end }} + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_{{ $name }}") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +{{- end }} + +func getMetricFromResource(name string, got metricdata.ResourceMetrics) metricdata.Metrics { for _, sm := range got.ScopeMetrics { for _, m := range sm.Metrics { if m.Name == name { @@ -70,4 +102,3 @@ func lenMetrics(got metricdata.ResourceMetrics) int { return metricsCount } - diff --git a/cmd/mdatagen/internal/templates/telemetrytest_test.go.tmpl b/cmd/mdatagen/internal/templates/telemetrytest_test.go.tmpl index 2d4e44fca24b..8463ddb48098 100644 --- a/cmd/mdatagen/internal/templates/telemetrytest_test.go.tmpl +++ b/cmd/mdatagen/internal/templates/telemetrytest_test.go.tmpl @@ -13,19 +13,21 @@ import ( func TestSetupTelemetry(t *testing.T) { testTel := SetupTelemetry() - tb, err := {{ .Package }}.NewTelemetryBuilder( - testTel.NewTelemetrySettings(), - {{- $package := .Package -}} - {{- range $name, $metric := .Telemetry.Metrics }} - {{- if (and (not $metric.Optional) $metric.Data.Async) }} - {{ $package }}.With{{ $name.Render }}Callback(func() {{ $metric.Data.BasicType }} { return 1 }), - {{- end }} - {{- end }} - ) - require.NoError(t, err) - require.NotNil(t, tb) + tb, err := {{ .Package }}.NewTelemetryBuilder(testTel.NewTelemetrySettings()) + require.NoError(t, err) + defer tb.Shutdown() + + {{- range $name, $metric := .Telemetry.Metrics }} + {{- if $metric.Data.Async }} + require.NoError(t, tb.Register{{ $name.Render }}Callback(func(_ context.Context, observer metric.{{ casesTitle $metric.Data.BasicType }}Observer) error { + observer.Observe(1) + return nil + })) + {{- end }} + {{- end }} + {{- range $name, $metric := .Telemetry.Metrics }} - {{- if (and (not $metric.Optional) (not $metric.Data.Async)) }} + {{- if not $metric.Data.Async }} {{- if eq $metric.Data.Type "Sum" }} tb.{{ $name.Render }}.Add(context.Background(), 1) {{- else }} @@ -36,7 +38,6 @@ func TestSetupTelemetry(t *testing.T) { testTel.AssertMetrics(t, []metricdata.Metrics{ {{- range $name, $metric := .Telemetry.Metrics }} - {{- if not $metric.Optional }} { Name: "otelcol_{{ $name }}", Description: "{{ $metric.Description }}{{ $metric.Stability }}", @@ -64,9 +65,20 @@ func TestSetupTelemetry(t *testing.T) { }, {{- end }} }, - {{- end }} {{- end }} }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + + {{- range $name, $metric := .Telemetry.Metrics }} + AssertEqual{{ $name.Render }}(t, testTel.Telemetry, + {{ if eq $metric.Data.Type "Gauge" -}} + []metricdata.DataPoint[{{ $metric.Gauge.MetricValueType.BasicType }}]{{"{{Value: 1}}"}}, + {{- else if eq $metric.Data.Type "Sum" -}} + []metricdata.DataPoint[{{ $metric.Sum.MetricValueType.BasicType }}]{{"{{Value: 1}}"}}, + {{- else if eq $metric.Data.Type "Histogram" -}} + []metricdata.HistogramDataPoint[{{ $metric.Histogram.MetricValueType.BasicType }}]{{"{{}}"}}, metricdatatest.IgnoreValue(), + {{- end }} + metricdatatest.IgnoreTimestamp()) + {{- end }} + require.NoError(t, testTel.Shutdown(context.Background())) } - diff --git a/cmd/otelcorecol/go.mod b/cmd/otelcorecol/go.mod index 4e10af53d99e..a2aaba730993 100644 --- a/cmd/otelcorecol/go.mod +++ b/cmd/otelcorecol/go.mod @@ -4,7 +4,7 @@ module go.opentelemetry.io/collector/cmd/otelcorecol go 1.22.0 -toolchain go1.22.10 +toolchain go1.22.11 require ( go.opentelemetry.io/collector/component v0.118.0 @@ -123,26 +123,27 @@ require ( go.opentelemetry.io/collector/semconv v0.118.0 // indirect go.opentelemetry.io/collector/service v0.118.0 // indirect go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 // indirect - go.opentelemetry.io/contrib/config v0.10.0 // indirect + go.opentelemetry.io/contrib/config v0.14.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.34.0 // indirect go.opentelemetry.io/contrib/zpages v0.59.0 // indirect go.opentelemetry.io/otel v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect go.opentelemetry.io/otel/exporters/prometheus v0.56.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 // indirect go.opentelemetry.io/otel/log v0.10.0 // indirect go.opentelemetry.io/otel/metric v1.34.0 // indirect go.opentelemetry.io/otel/sdk v1.34.0 // indirect - go.opentelemetry.io/otel/sdk/log v0.7.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.10.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect go.opentelemetry.io/otel/trace v1.34.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect @@ -154,8 +155,8 @@ require ( gonum.org/v1/gonum v0.15.1 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/cmd/otelcorecol/go.sum b/cmd/otelcorecol/go.sum index 0f31aefddd34..c8c8a463b629 100644 --- a/cmd/otelcorecol/go.sum +++ b/cmd/otelcorecol/go.sum @@ -115,8 +115,8 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 h1:f+xpAfhQTjR8beiSMe1bnT/25PkeyWmOcI+SjXWguNw= go.opentelemetry.io/contrib/bridges/otelzap v0.9.0/go.mod h1:T1Z1jyS5FttgQoF6UcGhnM+gF9wU32B4lHO69nXw4FE= -go.opentelemetry.io/contrib/config v0.10.0 h1:2JknAzMaYjxrHkTnZh3eOme/Y2P5eHE2SWfhfV6Xd6c= -go.opentelemetry.io/contrib/config v0.10.0/go.mod h1:aND2M6/KfNkntI5cyvHriR/zvZgPf8j9yETdSmvpfmc= +go.opentelemetry.io/contrib/config v0.14.0 h1:QAG8uHNp5ZiCkpT7XggSmg5AyW1sA0LgypMoXgBB1+4= +go.opentelemetry.io/contrib/config v0.14.0/go.mod h1:77rDmFPqBae5jtQ2C78RuDTHz4P27C8LzoN0MZyumYQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= @@ -127,34 +127,36 @@ go.opentelemetry.io/contrib/zpages v0.59.0 h1:t0H5zUy8fifIhRuVwm2FrA/D70Kk10SSpA go.opentelemetry.io/contrib/zpages v0.59.0/go.mod h1:9wo+yUPvHnBQEzoHJ8R3nA/Q5rkef7HjtLlSFI0Tgrc= go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 h1:mMOmtYie9Fx6TSVzw4W+NTpvoaS1JWWga37oI1a/4qQ= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0/go.mod h1:yy7nDsMMBUkD+jeekJ36ur5f3jJIrmCwUrY67VFhNpA= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 h1:5dTKu4I5Dn4P2hxyW3l3jTaZx9ACgg0ECos1eAVrheY= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0/go.mod h1:P5HcUI8obLrCCmM3sbVBohZFH34iszk/+CPWuakZWL8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 h1:q/heq5Zh8xV1+7GoMGJpTxM2Lhq5+bFxB29tshuRuw0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0/go.mod h1:leO2CSTg0Y+LyvmR7Wm4pUxE8KAmaM2GCVx7O+RATLA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 h1:ajl4QczuJVA2TU9W9AGw++86Xga/RKt//16z/yxPgdk= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0/go.mod h1:Vn3/rlOJ3ntf/Q3zAI0V5lDnTbHGaUsNUeF6nZmm7pA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 h1:opwv08VbCZ8iecIWs+McMdHRcAXzjAeda3uG2kI/hcA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0/go.mod h1:oOP3ABpW7vFHulLpE8aYtNBodrHhMTrvfxUXGvqm7Ac= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4= go.opentelemetry.io/otel/exporters/prometheus v0.56.0 h1:GnCIi0QyG0yy2MrJLzVrIM7laaJstj//flf1zEJCG+E= go.opentelemetry.io/otel/exporters/prometheus v0.56.0/go.mod h1:JQcVZtbIIPM+7SWBB+T6FK+xunlyidwLp++fN0sUaOk= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0 h1:TwmL3O3fRR80m8EshBrd8YydEZMcUCsZXzOUlnFohwM= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0/go.mod h1:tH98dDv5KPmPThswbXA0fr0Lwfs+OhK8HgaCo7PjRrk= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 h1:GKCEAZLEpEf78cUvudQdTg0aET2ObOZRB2HtXA0qPAI= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0/go.mod h1:9/zqSWLCmHT/9Jo6fYeUDRRogOLL60ABLsHWS99lF8s= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 h1:czJDQwFrMbOr9Kk+BPo1y8WZIIFIK58SA1kykuVeiOU= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0/go.mod h1:lT7bmsxOe58Tq+JIOkTQMCGXdu47oA+VJKLZHbaBKbs= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 h1:UGZ1QwZWY67Z6BmckTU+9Rxn04m2bD3gD6Mk0OIOCPk= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0/go.mod h1:fcwWuDuaObkkChiDlhEpSq9+X1C0omv+s5mBtToAQ64= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 h1:jBpDk4HAUsrnVO1FsfCfCOTEc/MkInJmvfCHYLFiT80= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0/go.mod h1:H9LUIM1daaeZaz91vZcfeM0fejXPmgCYE8ZhzqfJuiU= go.opentelemetry.io/otel/log v0.10.0 h1:1CXmspaRITvFcjA4kyVszuG4HjA61fPDxMb7q3BuyF0= go.opentelemetry.io/otel/log v0.10.0/go.mod h1:PbVdm9bXKku/gL0oFfUF4wwsQsOPlpo4VEqjvxih+FM= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/sdk/log v0.7.0 h1:dXkeI2S0MLc5g0/AwxTZv6EUEjctiH8aG14Am56NTmQ= -go.opentelemetry.io/otel/sdk/log v0.7.0/go.mod h1:oIRXpW+WD6M8BuGj5rtS0aRu/86cbDV/dAfNaZBIjYM= +go.opentelemetry.io/otel/sdk/log v0.10.0 h1:lR4teQGWfeDVGoute6l0Ou+RpFqQ9vaPdrNJlST0bvw= +go.opentelemetry.io/otel/sdk/log v0.10.0/go.mod h1:A+V1UTWREhWAittaQEG4bYm4gAZa6xnvVu+xKrIRkzo= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= @@ -210,10 +212,10 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1: google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/component/component.go b/component/component.go index 0a0c160fc599..5a32c5041d7c 100644 --- a/component/component.go +++ b/component/component.go @@ -78,31 +78,20 @@ func (f ShutdownFunc) Shutdown(ctx context.Context) error { } // Kind represents component kinds. -type Kind int +type Kind struct { + name string +} -const ( - _ Kind = iota // skip 0, start types from 1. - KindReceiver - KindProcessor - KindExporter - KindExtension - KindConnector +var ( + KindReceiver = Kind{name: "Receiver"} + KindProcessor = Kind{name: "Processor"} + KindExporter = Kind{name: "Exporter"} + KindExtension = Kind{name: "Extension"} + KindConnector = Kind{name: "Connector"} ) func (k Kind) String() string { - switch k { - case KindReceiver: - return "Receiver" - case KindProcessor: - return "Processor" - case KindExporter: - return "Exporter" - case KindExtension: - return "Extension" - case KindConnector: - return "Connector" - } - return "" + return k.name } // StabilityLevel represents the stability level of the component created by the factory. diff --git a/component/component_test.go b/component/component_test.go index 1cedc41af5d8..830d608ef0a5 100644 --- a/component/component_test.go +++ b/component/component_test.go @@ -10,13 +10,12 @@ import ( ) func TestKindString(t *testing.T) { - assert.Equal(t, "", Kind(0).String()) + assert.Equal(t, "", Kind{}.String()) assert.Equal(t, "Receiver", KindReceiver.String()) assert.Equal(t, "Processor", KindProcessor.String()) assert.Equal(t, "Exporter", KindExporter.String()) assert.Equal(t, "Extension", KindExtension.String()) assert.Equal(t, "Connector", KindConnector.String()) - assert.Equal(t, "", Kind(100).String()) } func TestStabilityLevelUnmarshal(t *testing.T) { diff --git a/component/componentstatus/go.mod b/component/componentstatus/go.mod index 7618dc65f8be..88c2d71d5d27 100644 --- a/component/componentstatus/go.mod +++ b/component/componentstatus/go.mod @@ -22,9 +22,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/component/componentstatus/go.sum b/component/componentstatus/go.sum index a7bf2c27469f..68c5d74f9162 100644 --- a/component/componentstatus/go.sum +++ b/component/componentstatus/go.sum @@ -32,10 +32,10 @@ go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -75,12 +75,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/component/componenttest/configtest.go b/component/componenttest/configtest.go index 8d1f1d157da2..6023f2ff0b6f 100644 --- a/component/componenttest/configtest.go +++ b/component/componenttest/configtest.go @@ -122,6 +122,9 @@ func checkStructFieldTags(f reflect.StructField) error { default: fieldTag := tagParts[0] if !configFieldTagRegExp.MatchString(fieldTag) { + if f.Name == "AdditionalProperties" { + return nil + } return fmt.Errorf( "field %q has config tag %q which doesn't satisfy %q", f.Name, diff --git a/component/componenttest/go.mod b/component/componenttest/go.mod index dd916d754599..bbeb2cbc9a11 100644 --- a/component/componenttest/go.mod +++ b/component/componenttest/go.mod @@ -28,9 +28,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/component/componenttest/go.sum b/component/componenttest/go.sum index ab41a28dad03..889137715630 100644 --- a/component/componenttest/go.sum +++ b/component/componenttest/go.sum @@ -76,12 +76,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/component/componenttest/nop_telemetry_test.go b/component/componenttest/nop_telemetry_test.go index 5f9d2d3aa93c..8850ba5e70d4 100644 --- a/component/componenttest/nop_telemetry_test.go +++ b/component/componenttest/nop_telemetry_test.go @@ -22,6 +22,6 @@ func TestNewNopTelemetrySettings(t *testing.T) { assert.NotPanics(t, func() { nts.MeterProvider.Meter("test") }) - assert.Equal(t, configtelemetry.LevelNone, nts.MetricsLevel) + assert.Equal(t, configtelemetry.LevelNone, nts.MetricsLevel) //nolint:staticcheck assert.Equal(t, 0, nts.Resource.Attributes().Len()) } diff --git a/component/componenttest/obsreporttest.go b/component/componenttest/obsreporttest.go index 3e673454442b..07d69cad00da 100644 --- a/component/componenttest/obsreporttest.go +++ b/component/componenttest/obsreporttest.go @@ -26,61 +26,63 @@ const ( ) type TestTelemetry struct { - Telemetry + *Telemetry id component.ID } +// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead. // CheckExporterTraces checks that for the current exported values for trace exporter metrics match given values. func (tts *TestTelemetry) CheckExporterTraces(sentSpans, sendFailedSpans int64) error { - return checkExporterTraces(tts.Reader, tts.id, sentSpans, sendFailedSpans) + return checkExporter(tts.Telemetry, tts.id, "spans", sentSpans, sendFailedSpans) } +// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead. // CheckExporterMetrics checks that for the current exported values for metrics exporter metrics match given values. func (tts *TestTelemetry) CheckExporterMetrics(sentMetricsPoints, sendFailedMetricsPoints int64) error { - return checkExporterMetrics(tts.Reader, tts.id, sentMetricsPoints, sendFailedMetricsPoints) + return checkExporter(tts.Telemetry, tts.id, "metric_points", sentMetricsPoints, sendFailedMetricsPoints) } +// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead. func (tts *TestTelemetry) CheckExporterEnqueueFailedMetrics(enqueueFailed int64) error { - return checkExporterEnqueueFailed(tts.Reader, tts.id, "metric_points", enqueueFailed) + return checkExporterEnqueueFailed(tts.Telemetry, tts.id, "metric_points", enqueueFailed) } +// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead. func (tts *TestTelemetry) CheckExporterEnqueueFailedTraces(enqueueFailed int64) error { - return checkExporterEnqueueFailed(tts.Reader, tts.id, "spans", enqueueFailed) + return checkExporterEnqueueFailed(tts.Telemetry, tts.id, "spans", enqueueFailed) } +// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead. func (tts *TestTelemetry) CheckExporterEnqueueFailedLogs(enqueueFailed int64) error { - return checkExporterEnqueueFailed(tts.Reader, tts.id, "log_records", enqueueFailed) + return checkExporterEnqueueFailed(tts.Telemetry, tts.id, "log_records", enqueueFailed) } +// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead. // CheckExporterLogs checks that for the current exported values for logs exporter metrics match given values. func (tts *TestTelemetry) CheckExporterLogs(sentLogRecords, sendFailedLogRecords int64) error { - return checkExporterLogs(tts.Reader, tts.id, sentLogRecords, sendFailedLogRecords) + return checkExporter(tts.Telemetry, tts.id, "log_records", sentLogRecords, sendFailedLogRecords) } +// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead. func (tts *TestTelemetry) CheckExporterMetricGauge(metric string, val int64, extraAttrs ...attribute.KeyValue) error { attrs := attributesForExporterMetrics(tts.id, extraAttrs...) - return checkIntGauge(tts.Reader, metric, val, attrs) + return checkIntGauge(tts.Telemetry, metric, val, attrs) } // CheckReceiverTraces checks that for the current exported values for trace receiver metrics match given values. func (tts *TestTelemetry) CheckReceiverTraces(protocol string, acceptedSpans, droppedSpans int64) error { - return checkReceiverTraces(tts.Reader, tts.id, protocol, acceptedSpans, droppedSpans) + return checkReceiver(tts.Telemetry, tts.id, "spans", protocol, acceptedSpans, droppedSpans) } +// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead. // CheckReceiverLogs checks that for the current exported values for logs receiver metrics match given values. func (tts *TestTelemetry) CheckReceiverLogs(protocol string, acceptedLogRecords, droppedLogRecords int64) error { - return checkReceiverLogs(tts.Reader, tts.id, protocol, acceptedLogRecords, droppedLogRecords) + return checkReceiver(tts.Telemetry, tts.id, "log_records", protocol, acceptedLogRecords, droppedLogRecords) } // CheckReceiverMetrics checks that for the current exported values for metrics receiver metrics match given values. func (tts *TestTelemetry) CheckReceiverMetrics(protocol string, acceptedMetricPoints, droppedMetricPoints int64) error { - return checkReceiverMetrics(tts.Reader, tts.id, protocol, acceptedMetricPoints, droppedMetricPoints) -} - -// Deprecated: [v0.118.0] use metadatatest.AssertMetrics instead. -// CheckScraperMetrics checks that for the current exported values for metrics scraper metrics match given values. -func (tts *TestTelemetry) CheckScraperMetrics(receiver component.ID, scraper component.ID, scrapedMetricPoints, erroredMetricPoints int64) error { - return checkScraperMetrics(tts.Reader, receiver, scraper, scrapedMetricPoints, erroredMetricPoints) + return checkReceiver(tts.Telemetry, tts.id, "metric_points", protocol, acceptedMetricPoints, droppedMetricPoints) } // TelemetrySettings returns the TestTelemetry's TelemetrySettings diff --git a/component/componenttest/otelchecker.go b/component/componenttest/otelchecker.go index c3196f7d66ed..eaa8aad724c7 100644 --- a/component/componenttest/otelchecker.go +++ b/component/componenttest/otelchecker.go @@ -4,75 +4,42 @@ package componenttest // import "go.opentelemetry.io/collector/component/componenttest" import ( - "context" "fmt" "go.opentelemetry.io/otel/attribute" - sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/metric/metricdata" "go.uber.org/multierr" "go.opentelemetry.io/collector/component" ) -func checkScraperMetrics(reader *sdkmetric.ManualReader, receiver component.ID, scraper component.ID, scrapedMetricPoints, erroredMetricPoints int64) error { - scraperAttrs := attributesForScraperMetrics(receiver, scraper) - return multierr.Combine( - checkIntSum(reader, "otelcol_scraper_scraped_metric_points", scrapedMetricPoints, scraperAttrs), - checkIntSum(reader, "otelcol_scraper_errored_metric_points", erroredMetricPoints, scraperAttrs)) -} - -func checkReceiverTraces(reader *sdkmetric.ManualReader, receiver component.ID, protocol string, accepted, dropped int64) error { - return checkReceiver(reader, receiver, "spans", protocol, accepted, dropped) -} - -func checkReceiverLogs(reader *sdkmetric.ManualReader, receiver component.ID, protocol string, accepted, dropped int64) error { - return checkReceiver(reader, receiver, "log_records", protocol, accepted, dropped) -} - -func checkReceiverMetrics(reader *sdkmetric.ManualReader, receiver component.ID, protocol string, accepted, dropped int64) error { - return checkReceiver(reader, receiver, "metric_points", protocol, accepted, dropped) -} - -func checkReceiver(reader *sdkmetric.ManualReader, receiver component.ID, datatype, protocol string, acceptedMetricPoints, droppedMetricPoints int64) error { +func checkReceiver(tel *Telemetry, receiver component.ID, datatype, protocol string, acceptedMetricPoints, droppedMetricPoints int64) error { receiverAttrs := attributesForReceiverMetrics(receiver, protocol) return multierr.Combine( - checkIntSum(reader, "otelcol_receiver_accepted_"+datatype, acceptedMetricPoints, receiverAttrs), - checkIntSum(reader, "otelcol_receiver_refused_"+datatype, droppedMetricPoints, receiverAttrs)) -} - -func checkExporterTraces(reader *sdkmetric.ManualReader, exporter component.ID, sent, sendFailed int64) error { - return checkExporter(reader, exporter, "spans", sent, sendFailed) -} - -func checkExporterLogs(reader *sdkmetric.ManualReader, exporter component.ID, sent, sendFailed int64) error { - return checkExporter(reader, exporter, "log_records", sent, sendFailed) + checkIntSum(tel, "otelcol_receiver_accepted_"+datatype, acceptedMetricPoints, receiverAttrs), + checkIntSum(tel, "otelcol_receiver_refused_"+datatype, droppedMetricPoints, receiverAttrs)) } -func checkExporterMetrics(reader *sdkmetric.ManualReader, exporter component.ID, sent, sendFailed int64) error { - return checkExporter(reader, exporter, "metric_points", sent, sendFailed) -} - -func checkExporter(reader *sdkmetric.ManualReader, exporter component.ID, datatype string, sent, sendFailed int64) error { +func checkExporter(tel *Telemetry, exporter component.ID, datatype string, sent, sendFailed int64) error { exporterAttrs := attributesForExporterMetrics(exporter) - errs := checkIntSum(reader, "otelcol_exporter_sent_"+datatype, sent, exporterAttrs) + errs := checkIntSum(tel, "otelcol_exporter_sent_"+datatype, sent, exporterAttrs) if sendFailed > 0 { errs = multierr.Append(errs, - checkIntSum(reader, "otelcol_exporter_send_failed_"+datatype, sendFailed, exporterAttrs)) + checkIntSum(tel, "otelcol_exporter_send_failed_"+datatype, sendFailed, exporterAttrs)) } return errs } -func checkExporterEnqueueFailed(reader *sdkmetric.ManualReader, exporter component.ID, datatype string, enqueueFailed int64) error { +func checkExporterEnqueueFailed(tel *Telemetry, exporter component.ID, datatype string, enqueueFailed int64) error { if enqueueFailed == 0 { return nil } exporterAttrs := attributesForExporterMetrics(exporter) - return checkIntSum(reader, "otelcol_exporter_enqueue_failed_"+datatype, enqueueFailed, exporterAttrs) + return checkIntSum(tel, "otelcol_exporter_enqueue_failed_"+datatype, enqueueFailed, exporterAttrs) } -func checkIntGauge(reader *sdkmetric.ManualReader, metric string, expected int64, expectedAttrs attribute.Set) error { - dp, err := getGaugeDataPoint[int64](reader, metric, expectedAttrs) +func checkIntGauge(tel *Telemetry, metric string, expected int64, expectedAttrs attribute.Set) error { + dp, err := getGaugeDataPoint[int64](tel, metric, expectedAttrs) if err != nil { return err } @@ -84,8 +51,8 @@ func checkIntGauge(reader *sdkmetric.ManualReader, metric string, expected int64 return nil } -func checkIntSum(reader *sdkmetric.ManualReader, expectedMetric string, expected int64, expectedAttrs attribute.Set) error { - dp, err := getSumDataPoint[int64](reader, expectedMetric, expectedAttrs) +func checkIntSum(tel *Telemetry, expectedMetric string, expected int64, expectedAttrs attribute.Set) error { + dp, err := getSumDataPoint[int64](tel, expectedMetric, expectedAttrs) if err != nil { return err } @@ -97,8 +64,8 @@ func checkIntSum(reader *sdkmetric.ManualReader, expectedMetric string, expected return nil } -func getSumDataPoint[N int64 | float64](reader *sdkmetric.ManualReader, expectedName string, expectedAttrs attribute.Set) (metricdata.DataPoint[N], error) { - m, err := getMetric(reader, expectedName) +func getSumDataPoint[N int64 | float64](tel *Telemetry, expectedName string, expectedAttrs attribute.Set) (metricdata.DataPoint[N], error) { + m, err := tel.GetMetric(expectedName) if err != nil { return metricdata.DataPoint[N]{}, err } @@ -111,8 +78,8 @@ func getSumDataPoint[N int64 | float64](reader *sdkmetric.ManualReader, expected } } -func getGaugeDataPoint[N int64 | float64](reader *sdkmetric.ManualReader, expectedName string, expectedAttrs attribute.Set) (metricdata.DataPoint[N], error) { - m, err := getMetric(reader, expectedName) +func getGaugeDataPoint[N int64 | float64](tel *Telemetry, expectedName string, expectedAttrs attribute.Set) (metricdata.DataPoint[N], error) { + m, err := tel.GetMetric(expectedName) if err != nil { return metricdata.DataPoint[N]{}, err } @@ -134,29 +101,6 @@ func getDataPoint[N int64 | float64](dps []metricdata.DataPoint[N], expectedName return metricdata.DataPoint[N]{}, fmt.Errorf("metric '%s' doesn't have a data point with the given attributes: %s", expectedName, expectedAttrs.Encoded(attribute.DefaultEncoder())) } -func getMetric(reader *sdkmetric.ManualReader, expectedName string) (metricdata.Metrics, error) { - var rm metricdata.ResourceMetrics - if err := reader.Collect(context.Background(), &rm); err != nil { - return metricdata.Metrics{}, err - } - - for _, sm := range rm.ScopeMetrics { - for _, m := range sm.Metrics { - if m.Name == expectedName { - return m, nil - } - } - } - return metricdata.Metrics{}, fmt.Errorf("metric '%s' not found", expectedName) -} - -func attributesForScraperMetrics(receiver component.ID, scraper component.ID) attribute.Set { - return attribute.NewSet( - attribute.String(receiverTag, receiver.String()), - attribute.String(scraperTag, scraper.String()), - ) -} - // attributesForReceiverMetrics returns the attributes that are needed for the receiver metrics. func attributesForReceiverMetrics(receiver component.ID, transport string) attribute.Set { return attribute.NewSet( diff --git a/component/componenttest/telemetry.go b/component/componenttest/telemetry.go index 990f5cd36c50..7f14b1d435fc 100644 --- a/component/componenttest/telemetry.go +++ b/component/componenttest/telemetry.go @@ -6,8 +6,10 @@ package componenttest // import "go.opentelemetry.io/collector/component/compone import ( "context" "errors" + "fmt" sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/sdk/trace/tracetest" @@ -47,7 +49,7 @@ type Telemetry struct { traceProvider *sdktrace.TracerProvider } -func NewTelemetry(opts ...TelemetryOption) Telemetry { +func NewTelemetry(opts ...TelemetryOption) *Telemetry { reader := sdkmetric.NewManualReader() spanRecorder := new(tracetest.SpanRecorder) tOpts := telemetryOption{ @@ -57,7 +59,7 @@ func NewTelemetry(opts ...TelemetryOption) Telemetry { for _, opt := range opts { opt.apply(&tOpts) } - return Telemetry{ + return &Telemetry{ Reader: reader, SpanRecorder: spanRecorder, meterProvider: sdkmetric.NewMeterProvider(tOpts.metricOpts...), @@ -68,11 +70,27 @@ func NewTelemetry(opts ...TelemetryOption) Telemetry { func (tt *Telemetry) NewTelemetrySettings() component.TelemetrySettings { set := NewNopTelemetrySettings() set.MeterProvider = tt.meterProvider - set.MetricsLevel = configtelemetry.LevelDetailed + set.MetricsLevel = configtelemetry.LevelDetailed //nolint:staticcheck //SA1019 set.TracerProvider = tt.traceProvider return set } +func (tt *Telemetry) GetMetric(name string) (metricdata.Metrics, error) { + var rm metricdata.ResourceMetrics + if err := tt.Reader.Collect(context.Background(), &rm); err != nil { + return metricdata.Metrics{}, err + } + + for _, sm := range rm.ScopeMetrics { + for _, m := range sm.Metrics { + if m.Name == name { + return m, nil + } + } + } + return metricdata.Metrics{}, fmt.Errorf("metric '%s' not found", name) +} + func (tt *Telemetry) Shutdown(ctx context.Context) error { return errors.Join( tt.meterProvider.Shutdown(ctx), diff --git a/component/componenttest/telemetry_test.go b/component/componenttest/telemetry_test.go index 4361bb488c99..2bae32d84d31 100644 --- a/component/componenttest/telemetry_test.go +++ b/component/componenttest/telemetry_test.go @@ -20,7 +20,7 @@ func TestNewTelemetry(t *testing.T) { assert.NotNil(t, tel.Reader) assert.NotNil(t, tel.SpanRecorder) set := tel.NewTelemetrySettings() - assert.Equal(t, configtelemetry.LevelDetailed, set.MetricsLevel) + assert.Equal(t, configtelemetry.LevelDetailed, set.MetricsLevel) //nolint:staticcheck //SA1019 assert.IsType(t, &sdktrace.TracerProvider{}, set.TracerProvider) assert.IsType(t, &sdkmetric.MeterProvider{}, set.MeterProvider) require.NoError(t, tel.Shutdown(context.Background())) diff --git a/component/config.go b/component/config.go index 11cbf7dabc8e..a5862798fdd8 100644 --- a/component/config.go +++ b/component/config.go @@ -4,9 +4,11 @@ package component // import "go.opentelemetry.io/collector/component" import ( + "errors" + "fmt" "reflect" - - "go.uber.org/multierr" + "strconv" + "strings" ) // Config defines the configuration for a component.Component. @@ -31,10 +33,44 @@ type ConfigValidator interface { // ValidateConfig validates a config, by doing this: // - Call Validate on the config itself if the config implements ConfigValidator. func ValidateConfig(cfg Config) error { - return validate(reflect.ValueOf(cfg)) + var err error + + for _, validationErr := range validate(reflect.ValueOf(cfg)) { + err = errors.Join(err, validationErr) + } + + return err +} + +type pathError struct { + err error + path []string +} + +func (pe pathError) Error() string { + if len(pe.path) > 0 { + var path string + sb := strings.Builder{} + + _, _ = sb.WriteString(pe.path[len(pe.path)-1]) + for i := len(pe.path) - 2; i >= 0; i-- { + _, _ = sb.WriteString("::") + _, _ = sb.WriteString(pe.path[i]) + } + path = sb.String() + + return fmt.Sprintf("%s: %s", path, pe.err) + } + + return pe.err.Error() +} + +func (pe pathError) Unwrap() error { + return pe.err } -func validate(v reflect.Value) error { +func validate(v reflect.Value) []pathError { + errs := []pathError{} // Validate the value itself. switch v.Kind() { case reflect.Invalid: @@ -42,35 +78,74 @@ func validate(v reflect.Value) error { case reflect.Ptr, reflect.Interface: return validate(v.Elem()) case reflect.Struct: - var errs error - errs = multierr.Append(errs, callValidateIfPossible(v)) + err := callValidateIfPossible(v) + if err != nil { + errs = append(errs, pathError{err: err}) + } + // Reflect on the pointed data and check each of its fields. for i := 0; i < v.NumField(); i++ { if !v.Type().Field(i).IsExported() { continue } - errs = multierr.Append(errs, validate(v.Field(i))) + field := v.Type().Field(i) + path := fieldName(field) + + subpathErrs := validate(v.Field(i)) + for _, err := range subpathErrs { + errs = append(errs, pathError{ + err: err.err, + path: append(err.path, path), + }) + } } return errs case reflect.Slice, reflect.Array: - var errs error - errs = multierr.Append(errs, callValidateIfPossible(v)) + err := callValidateIfPossible(v) + if err != nil { + errs = append(errs, pathError{err: err}) + } + // Reflect on the pointed data and check each of its fields. for i := 0; i < v.Len(); i++ { - errs = multierr.Append(errs, validate(v.Index(i))) + subPathErrs := validate(v.Index(i)) + + for _, err := range subPathErrs { + errs = append(errs, pathError{ + err: err.err, + path: append(err.path, strconv.Itoa(i)), + }) + } } return errs case reflect.Map: - var errs error - errs = multierr.Append(errs, callValidateIfPossible(v)) + err := callValidateIfPossible(v) + if err != nil { + errs = append(errs, pathError{err: err}) + } + iter := v.MapRange() for iter.Next() { - errs = multierr.Append(errs, validate(iter.Key())) - errs = multierr.Append(errs, validate(iter.Value())) + keyErrs := validate(iter.Key()) + valueErrs := validate(iter.Value()) + key := stringifyMapKey(iter.Key()) + + for _, err := range keyErrs { + errs = append(errs, pathError{err: err.err, path: append(err.path, key)}) + } + + for _, err := range valueErrs { + errs = append(errs, pathError{err: err.err, path: append(err.path, key)}) + } } return errs default: - return callValidateIfPossible(v) + err := callValidateIfPossible(v) + if err != nil { + return []pathError{{err: err}} + } + + return nil } } @@ -93,3 +168,39 @@ func callValidateIfPossible(v reflect.Value) error { return nil } + +func fieldName(field reflect.StructField) string { + var fieldName string + if tag, ok := field.Tag.Lookup("mapstructure"); ok { + tags := strings.Split(tag, ",") + if len(tags) > 0 { + fieldName = tags[0] + } + } + // Even if the mapstructure tag exists, the field name may not + // be available, so set it if it is still blank. + if len(fieldName) == 0 { + fieldName = strings.ToLower(field.Name) + } + + return fieldName +} + +func stringifyMapKey(val reflect.Value) string { + var key string + + if str, ok := val.Interface().(string); ok { + key = str + } else if stringer, ok := val.Interface().(fmt.Stringer); ok { + key = stringer.String() + } else { + switch val.Kind() { + case reflect.Ptr, reflect.Interface, reflect.Struct, reflect.Slice, reflect.Array, reflect.Map: + key = fmt.Sprintf("[%T key]", val.Interface()) + default: + key = fmt.Sprintf("%v", val.Interface()) + } + } + + return key +} diff --git a/component/config_test.go b/component/config_test.go index c3b316c2a947..686c0fb7d98d 100644 --- a/component/config_test.go +++ b/component/config_test.go @@ -5,7 +5,6 @@ package component import ( "errors" - "reflect" "testing" "github.com/stretchr/testify/assert" @@ -68,11 +67,48 @@ func (e errMapType) Validate() error { return errors.New(e["err"]) } +type structKey struct { + k string + e error +} + +func (s structKey) String() string { + return s.k +} + +func (s structKey) Validate() error { + return s.e +} + +type configChildMapCustomKey struct { + Child map[structKey]errConfig +} + func newErrMapType() *errMapType { et := errMapType(nil) return &et } +type configMapstructure struct { + Valid *errConfig `mapstructure:"validtag,omitempty"` + NoData *errConfig `mapstructure:""` + NoName *errConfig `mapstructure:",remain"` +} + +type configDeeplyNested struct { + MapKeyChild map[configChildStruct]string + MapValueChild map[string]configChildStruct + SliceChild []configChildSlice + MapIntKey map[int]errConfig + MapFloatKey map[float64]errConfig +} + +type sliceTypeAlias []configChildSlice + +func (sliceTypeAlias) Validate() error { + return errors.New("sliceTypeAlias error") +} + func TestValidateConfig(t *testing.T) { tests := []struct { name string @@ -127,104 +163,159 @@ func TestValidateConfig(t *testing.T) { { name: "child struct", cfg: configChildStruct{Child: errConfig{err: errors.New("child struct")}}, - expected: errors.New("child struct"), + expected: errors.New("child: child struct"), }, { name: "pointer child struct", cfg: &configChildStruct{Child: errConfig{err: errors.New("pointer child struct")}}, - expected: errors.New("pointer child struct"), + expected: errors.New("child: pointer child struct"), }, { name: "child struct pointer", cfg: &configChildStruct{ChildPtr: &errConfig{err: errors.New("child struct pointer")}}, - expected: errors.New("child struct pointer"), + expected: errors.New("childptr: child struct pointer"), }, { name: "child interface", cfg: configChildInterface{Child: errConfig{err: errors.New("child interface")}}, - expected: errors.New("child interface"), + expected: errors.New("child: child interface"), }, { name: "pointer to child interface", cfg: &configChildInterface{Child: errConfig{err: errors.New("pointer to child interface")}}, - expected: errors.New("pointer to child interface"), + expected: errors.New("child: pointer to child interface"), }, { name: "child interface with pointer", cfg: configChildInterface{Child: &errConfig{err: errors.New("child interface with pointer")}}, - expected: errors.New("child interface with pointer"), + expected: errors.New("child: child interface with pointer"), }, { name: "pointer to child interface with pointer", cfg: &configChildInterface{Child: &errConfig{err: errors.New("pointer to child interface with pointer")}}, - expected: errors.New("pointer to child interface with pointer"), + expected: errors.New("child: pointer to child interface with pointer"), }, { name: "child slice", cfg: configChildSlice{Child: []errConfig{{}, {err: errors.New("child slice")}}}, - expected: errors.New("child slice"), + expected: errors.New("child::1: child slice"), }, { name: "pointer child slice", cfg: &configChildSlice{Child: []errConfig{{}, {err: errors.New("pointer child slice")}}}, - expected: errors.New("pointer child slice"), + expected: errors.New("child::1: pointer child slice"), }, { name: "child slice pointer", cfg: &configChildSlice{ChildPtr: []*errConfig{{}, {err: errors.New("child slice pointer")}}}, - expected: errors.New("child slice pointer"), + expected: errors.New("childptr::1: child slice pointer"), }, { name: "child map value", cfg: configChildMapValue{Child: map[string]errConfig{"test": {err: errors.New("child map")}}}, - expected: errors.New("child map"), + expected: errors.New("child::test: child map"), }, { name: "pointer child map value", cfg: &configChildMapValue{Child: map[string]errConfig{"test": {err: errors.New("pointer child map")}}}, - expected: errors.New("pointer child map"), + expected: errors.New("child::test: pointer child map"), }, { name: "child map value pointer", cfg: &configChildMapValue{ChildPtr: map[string]*errConfig{"test": {err: errors.New("child map pointer")}}}, - expected: errors.New("child map pointer"), + expected: errors.New("childptr::test: child map pointer"), }, { name: "child map key", - cfg: configChildMapKey{Child: map[errType]string{"child map key": ""}}, - expected: errors.New("child map key"), + cfg: configChildMapKey{Child: map[errType]string{"child_map_key": ""}}, + expected: errors.New("child::child_map_key: child_map_key"), }, { name: "pointer child map key", - cfg: &configChildMapKey{Child: map[errType]string{"pointer child map key": ""}}, - expected: errors.New("pointer child map key"), + cfg: &configChildMapKey{Child: map[errType]string{"pointer_child_map_key": ""}}, + expected: errors.New("child::pointer_child_map_key: pointer_child_map_key"), }, { name: "child map key pointer", cfg: &configChildMapKey{ChildPtr: map[*errType]string{newErrType("child map key pointer"): ""}}, - expected: errors.New("child map key pointer"), + expected: errors.New("childptr::[*component.errType key]: child map key pointer"), + }, + { + name: "map with stringified non-string key type", + cfg: &configChildMapCustomKey{Child: map[structKey]errConfig{{k: "struct_key", e: errors.New("custom key error")}: {err: errors.New("value error")}}}, + expected: errors.New("child::struct_key: custom key error\nchild::struct_key: value error"), }, { name: "child type", cfg: configChildTypeDef{Child: "child type"}, - expected: errors.New("child type"), + expected: errors.New("child: child type"), }, { name: "pointer child type", cfg: &configChildTypeDef{Child: "pointer child type"}, - expected: errors.New("pointer child type"), + expected: errors.New("child: pointer child type"), }, { name: "child type pointer", cfg: &configChildTypeDef{ChildPtr: newErrType("child type pointer")}, - expected: errors.New("child type pointer"), + expected: errors.New("childptr: child type pointer"), + }, + { + name: "valid mapstructure tag", + cfg: configMapstructure{Valid: &errConfig{errors.New("test")}}, + expected: errors.New("validtag: test"), + }, + { + name: "zero-length mapstructure tag", + cfg: configMapstructure{NoData: &errConfig{errors.New("test")}}, + expected: errors.New("nodata: test"), + }, + { + name: "no field name in mapstructure tag", + cfg: configMapstructure{NoName: &errConfig{errors.New("test")}}, + expected: errors.New("noname: test"), + }, + { + name: "nested map key error", + cfg: configDeeplyNested{MapKeyChild: map[configChildStruct]string{{Child: errConfig{err: errors.New("child key error")}}: "val"}}, + expected: errors.New("mapkeychild::[component.configChildStruct key]::child: child key error"), + }, + { + name: "nested map value error", + cfg: configDeeplyNested{MapValueChild: map[string]configChildStruct{"key": {Child: errConfig{err: errors.New("child key error")}}}}, + expected: errors.New("mapvaluechild::key::child: child key error"), + }, + { + name: "nested slice value error", + cfg: configDeeplyNested{SliceChild: []configChildSlice{{Child: []errConfig{{err: errors.New("child key error")}}}}}, + expected: errors.New("slicechild::0::child::0: child key error"), + }, + { + name: "nested map with int key", + cfg: configDeeplyNested{MapIntKey: map[int]errConfig{1: {err: errors.New("int key error")}}}, + expected: errors.New("mapintkey::1: int key error"), + }, + { + name: "nested map with float key", + cfg: configDeeplyNested{MapFloatKey: map[float64]errConfig{1.2: {err: errors.New("float key error")}}}, + expected: errors.New("mapfloatkey::1.2: float key error"), + }, + { + name: "slice type alias", + cfg: sliceTypeAlias{}, + expected: errors.New("sliceTypeAlias error"), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := validate(reflect.ValueOf(tt.cfg)) - assert.Equal(t, tt.expected, err) + err := ValidateConfig(tt.cfg) + + if tt.expected != nil { + assert.EqualError(t, err, tt.expected.Error()) + } else { + assert.NoError(t, err) + } }) } } diff --git a/component/go.mod b/component/go.mod index 7057576920a3..14e536575c10 100644 --- a/component/go.mod +++ b/component/go.mod @@ -9,7 +9,6 @@ require ( go.opentelemetry.io/otel/metric v1.34.0 go.opentelemetry.io/otel/trace v1.34.0 go.uber.org/goleak v1.3.0 - go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 ) @@ -18,12 +17,13 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opentelemetry.io/otel v1.34.0 // indirect + go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/component/go.sum b/component/go.sum index a7bf2c27469f..68c5d74f9162 100644 --- a/component/go.sum +++ b/component/go.sum @@ -32,10 +32,10 @@ go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -75,12 +75,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/component/identifiable.go b/component/identifiable.go index 63b890b47aca..6b814768161c 100644 --- a/component/identifiable.go +++ b/component/identifiable.go @@ -123,23 +123,19 @@ func (id ID) MarshalText() (text []byte, err error) { // UnmarshalText implements the encoding.TextUnmarshaler interface. func (id *ID) UnmarshalText(text []byte) error { idStr := string(text) - items := strings.SplitN(idStr, typeAndNameSeparator, 2) - var typeStr, nameStr string - if len(items) >= 1 { - typeStr = strings.TrimSpace(items[0]) - } - - if len(items) == 1 && typeStr == "" { - return errors.New("id must not be empty") - } + typeStr, nameStr, hasName := strings.Cut(idStr, typeAndNameSeparator) + typeStr = strings.TrimSpace(typeStr) if typeStr == "" { - return fmt.Errorf("in %q id: the part before %s should not be empty", idStr, typeAndNameSeparator) + if hasName { + return fmt.Errorf("in %q id: the part before %s should not be empty", idStr, typeAndNameSeparator) + } + return errors.New("id must not be empty") } - if len(items) > 1 { + if hasName { // "name" part is present. - nameStr = strings.TrimSpace(items[1]) + nameStr = strings.TrimSpace(nameStr) if nameStr == "" { return fmt.Errorf("in %q id: the part after %s should not be empty", idStr, typeAndNameSeparator) } diff --git a/component/telemetry.go b/component/telemetry.go index 359562e5f924..13331e95e111 100644 --- a/component/telemetry.go +++ b/component/telemetry.go @@ -27,6 +27,9 @@ type TelemetrySettings struct { // MetricsLevel represents the configuration value set when the collector // is configured. Components may use this level to decide whether it is // appropriate to avoid computationally expensive calculations. + // + // Deprecated: [v0.119.0] Use https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric@v1.34.0/internal/x#readme-instrument-enabled instead. + // Components will temporarily need to add a view to `service/telemetry` to drop metrics based on the level. MetricsLevel configtelemetry.Level // Resource contains the resource attributes for the collector's telemetry. diff --git a/config/configauth/go.mod b/config/configauth/go.mod index c3745f103649..45594331fe42 100644 --- a/config/configauth/go.mod +++ b/config/configauth/go.mod @@ -24,9 +24,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/config/configauth/go.sum b/config/configauth/go.sum index e7b3f1f53225..ac84fbc4cf94 100644 --- a/config/configauth/go.sum +++ b/config/configauth/go.sum @@ -75,12 +75,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/config/configgrpc/go.mod b/config/configgrpc/go.mod index a51fee3bd1bb..3ddddc61bf83 100644 --- a/config/configgrpc/go.mod +++ b/config/configgrpc/go.mod @@ -20,7 +20,7 @@ require ( go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 go.opentelemetry.io/otel v1.34.0 go.uber.org/goleak v1.3.0 - google.golang.org/grpc v1.69.4 + google.golang.org/grpc v1.70.0 ) require ( @@ -50,7 +50,7 @@ require ( golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/config/configgrpc/go.sum b/config/configgrpc/go.sum index 73a22f634798..57e7f9de1480 100644 --- a/config/configgrpc/go.sum +++ b/config/configgrpc/go.sum @@ -99,10 +99,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/config/confighttp/confighttp_test.go b/config/confighttp/confighttp_test.go index c4b69ae8e271..8172946d5c1a 100644 --- a/config/confighttp/confighttp_test.go +++ b/config/confighttp/confighttp_test.go @@ -29,7 +29,6 @@ import ( "go.opentelemetry.io/collector/config/configauth" "go.opentelemetry.io/collector/config/configcompression" "go.opentelemetry.io/collector/config/configopaque" - "go.opentelemetry.io/collector/config/configtelemetry" "go.opentelemetry.io/collector/config/configtls" "go.opentelemetry.io/collector/extension/auth" "go.opentelemetry.io/collector/extension/auth/authtest" @@ -49,7 +48,7 @@ var ( dummyID = component.MustNewID("dummy") nonExistingID = component.MustNewID("nonexisting") // Omit TracerProvider and MeterProvider in TelemetrySettings as otelhttp.Transport cannot be introspected - nilProvidersSettings = component.TelemetrySettings{Logger: zap.NewNop(), MetricsLevel: configtelemetry.LevelNone} + nilProvidersSettings = component.TelemetrySettings{Logger: zap.NewNop()} ) func TestAllHTTPClientSettings(t *testing.T) { diff --git a/config/confighttp/go.mod b/config/confighttp/go.mod index 0d327845520d..12fb010b485d 100644 --- a/config/confighttp/go.mod +++ b/config/confighttp/go.mod @@ -14,7 +14,6 @@ require ( go.opentelemetry.io/collector/config/configauth v0.118.0 go.opentelemetry.io/collector/config/configcompression v1.24.0 go.opentelemetry.io/collector/config/configopaque v1.24.0 - go.opentelemetry.io/collector/config/configtelemetry v0.118.0 go.opentelemetry.io/collector/config/configtls v1.24.0 go.opentelemetry.io/collector/extension/auth v0.118.0 go.opentelemetry.io/collector/extension/auth/authtest v0.118.0 @@ -35,6 +34,7 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.118.0 // indirect go.opentelemetry.io/collector/extension v0.118.0 // indirect go.opentelemetry.io/collector/pdata v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.34.0 // indirect @@ -44,9 +44,9 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/config/confighttp/go.sum b/config/confighttp/go.sum index a5b98164786e..f908628c60d7 100644 --- a/config/confighttp/go.sum +++ b/config/confighttp/go.sum @@ -96,12 +96,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/config/confighttp/xconfighttp/go.mod b/config/confighttp/xconfighttp/go.mod index bfe5d0e1b11b..20059ed18d85 100644 --- a/config/confighttp/xconfighttp/go.mod +++ b/config/confighttp/xconfighttp/go.mod @@ -43,9 +43,9 @@ require ( golang.org/x/net v0.34.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/config/confighttp/xconfighttp/go.sum b/config/confighttp/xconfighttp/go.sum index a5b98164786e..f908628c60d7 100644 --- a/config/confighttp/xconfighttp/go.sum +++ b/config/confighttp/xconfighttp/go.sum @@ -96,12 +96,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/config/configtls/README.md b/config/configtls/README.md index b7ea4e84e769..f91636287bb6 100644 --- a/config/configtls/README.md +++ b/config/configtls/README.md @@ -14,6 +14,12 @@ By default, TLS is enabled: the exporter's HTTPs or gRPC connection. See [grpc.WithInsecure()](https://godoc.org/google.golang.org/grpc#WithInsecure) for gRPC. +- `curve_preferences` (default = []): specify your curve preferences that will + be used in an ECDHE handshake, in preference order. Accepted values are: + - X25519 + - P521 + - P256 + - P384 As a result, the following parameters are also required: diff --git a/config/configtls/configtls.go b/config/configtls/configtls.go index 0cbcc5f40727..8b2c6ea26744 100644 --- a/config/configtls/configtls.go +++ b/config/configtls/configtls.go @@ -70,6 +70,11 @@ type Config struct { // ReloadInterval specifies the duration after which the certificate will be reloaded // If not set, it will never be reloaded (optional) ReloadInterval time.Duration `mapstructure:"reload_interval"` + + // contains the elliptic curves that will be used in + // an ECDHE handshake, in preference order + // Defaults to empty list and "crypto/tls" defaults are used, internally. + CurvePreferences []string `mapstructure:"curve_preferences"` } // NewDefaultConfig creates a new TLSSetting with any default values set. @@ -231,6 +236,14 @@ func (c Config) loadTLSConfig() (*tls.Config, error) { if err != nil { return nil, err } + curvePreferences := make([]tls.CurveID, 0, len(c.CurvePreferences)) + for _, curve := range c.CurvePreferences { + curveID, ok := tlsCurveTypes[curve] + if !ok { + return nil, fmt.Errorf("invalid curve type: %s. Expected values are [P-256, P-384, P-521, X25519]", curveID) + } + curvePreferences = append(curvePreferences, curveID) + } return &tls.Config{ RootCAs: certPool, @@ -239,6 +252,7 @@ func (c Config) loadTLSConfig() (*tls.Config, error) { MinVersion: minTLS, MaxVersion: maxTLS, CipherSuites: cipherSuites, + CurvePreferences: curvePreferences, }, nil } @@ -448,3 +462,10 @@ var tlsVersions = map[string]uint16{ "1.2": tls.VersionTLS12, "1.3": tls.VersionTLS13, } + +var tlsCurveTypes = map[string]tls.CurveID{ + "P256": tls.CurveP256, + "P384": tls.CurveP384, + "P521": tls.CurveP521, + "X25519": tls.X25519, +} diff --git a/config/configtls/configtls_test.go b/config/configtls/configtls_test.go index 2f1f1fb34397..823c35e7f9a6 100644 --- a/config/configtls/configtls_test.go +++ b/config/configtls/configtls_test.go @@ -871,3 +871,53 @@ func TestSystemCertPool_loadCert(t *testing.T) { }) } } + +func TestCurvePreferences(t *testing.T) { + tests := []struct { + name string + preferences []string + expectedCurveIDs []tls.CurveID + expectedErr string + }{ + { + name: "X25519", + preferences: []string{"X25519"}, + expectedCurveIDs: []tls.CurveID{tls.X25519}, + }, + { + name: "P521", + preferences: []string{"P521"}, + expectedCurveIDs: []tls.CurveID{tls.CurveP521}, + }, + { + name: "P-256", + preferences: []string{"P256"}, + expectedCurveIDs: []tls.CurveID{tls.CurveP256}, + }, + { + name: "multiple", + preferences: []string{"P256", "P521", "X25519"}, + expectedCurveIDs: []tls.CurveID{tls.CurveP256, tls.CurveP521, tls.X25519}, + }, + { + name: "invalid-curve", + preferences: []string{"P25223236"}, + expectedCurveIDs: []tls.CurveID{}, + expectedErr: "invalid curve type", + }, + } + for _, test := range tests { + tlsSetting := ClientConfig{ + Config: Config{ + CurvePreferences: test.preferences, + }, + } + config, err := tlsSetting.LoadTLSConfig(context.Background()) + if test.expectedErr == "" { + require.NoError(t, err) + require.ElementsMatchf(t, test.expectedCurveIDs, config.CurvePreferences, "expected %v, got %v", test.expectedCurveIDs, config.CurvePreferences) + } else { + require.ErrorContains(t, err, test.expectedErr) + } + } +} diff --git a/confmap/README.md b/confmap/README.md index bfa24c8bcc02..40c6b1a40bb3 100644 --- a/confmap/README.md +++ b/confmap/README.md @@ -37,7 +37,7 @@ that can be used by code that is oblivious to the usage of `Providers` and `Conv or an individual value (partial configuration) when the `configURI` is embedded into the `Conf` as a values using the syntax `${configURI}`. -**Limitation:** +**Limitation:** - When embedding a `${configURI}` the uri cannot contain dollar sign ("$") character unless it embeds another uri. - The number of URIs is limited to 100. @@ -87,7 +87,26 @@ The `Resolve` method proceeds in the following steps: After the configuration was processed, the `Resolver` can be used as a single point to watch for updates in the configuration retrieved via the `Provider` used to retrieve the “initial” configuration and to generate the “effective” one. -```terminal +```terminal + Resolver Provider + │ │ + Watch │ │ +───────────►│ │ + │ │ + . . + . . + . . + │ onChange │ + │◄────────────────────┤ +◄───────────┤ │ + +``` + +The `Resolver` does that by passing an `onChange` func to each `Provider.Retrieve` call and capturing all watch events. + +Calling the `onChange` func from a provider triggers the collector to re-resolve new configuration: + +```terminal Resolver Provider │ │ Watch │ │ @@ -98,17 +117,26 @@ configuration retrieved via the `Provider` used to retrieve the “initial” co . . │ onChange │ │◄────────────────────┤ +◄───────────┤ │ + | | + Resolve │ │ +───────────►│ │ + │ │ + │ Retrieve │ + ├────────────────────►│ + │ Conf │ + │◄────────────────────┤ ◄───────────┤ │ ``` -The `Resolver` does that by passing an `onChange` func to each `Provider.Retrieve` call and capturing all watch events. +An example of a `Provider` with an `onChange` func that periodically gets notified can be found in provider_test.go as UpdatingProvider ## Troubleshooting ### Null Maps Due to how our underlying merge library, [koanf](https://github.com/knadh/koanf), behaves, configuration resolution -will treat configuration such as +will treat configuration such as ```yaml processors: diff --git a/confmap/provider.go b/confmap/provider.go index c462b9bb6fe7..55d0d69341d2 100644 --- a/confmap/provider.go +++ b/confmap/provider.go @@ -64,7 +64,7 @@ type Provider interface { // - For testing, all implementation MUST check that confmaptest.ValidateProviderScheme returns no error. // // `watcher` callback is called when the config changes. watcher may be called from - // a different go routine. After watcher is called Retrieved.Get should be called + // a different go routine. After watcher is called, Provider.Retrieve should be called // to get the new config. See description of Retrieved for more details. // watcher may be nil, which indicates that the caller is not interested in // knowing about the changes. diff --git a/confmap/provider/envprovider/provider.go b/confmap/provider/envprovider/provider.go index 8a0b87a9174e..eab5e63f14b5 100644 --- a/confmap/provider/envprovider/provider.go +++ b/confmap/provider/envprovider/provider.go @@ -76,9 +76,9 @@ func (*provider) Shutdown(context.Context) error { // returns (var name, default value) func parseEnvVarURI(uri string) (string, *string) { const defaultSuffix = ":-" - if strings.Contains(uri, defaultSuffix) { - parts := strings.SplitN(uri, defaultSuffix, 2) - return parts[0], &parts[1] + name, defaultValue, hasDefault := strings.Cut(uri, defaultSuffix) + if hasDefault { + return name, &defaultValue } return uri, nil } diff --git a/confmap/provider_test.go b/confmap/provider_test.go index 68d3e33765b8..07635ee7fc2e 100644 --- a/confmap/provider_test.go +++ b/confmap/provider_test.go @@ -6,6 +6,7 @@ package confmap import ( "context" "errors" + "fmt" "testing" "time" @@ -13,6 +14,78 @@ import ( "github.com/stretchr/testify/require" ) +// This is an example of a provider that calls a provided WatcherFunc to update configuration dynamically every second. +// The example is useful for implementing Providers of configuration that changes over time. +type UpdatingProvider struct{} + +func (p UpdatingProvider) getCurrentConfig(_ string) any { + return "hello" +} + +func (p UpdatingProvider) Retrieve(ctx context.Context, uri string, watcher WatcherFunc) (*Retrieved, error) { + ticker := time.NewTicker(1 * time.Second) + stop := make(chan bool, 1) + + retrieved, err := NewRetrieved(p.getCurrentConfig(uri), WithRetrievedClose(func(_ context.Context) error { + // the retriever should call this function when it no longer wants config updates + ticker.Stop() + stop <- true + return nil + })) + if err != nil { + return nil, err + } + // it's necessary to start a go function that can notify the caller of changes asynchronously + go func() { + for { + select { + case <-ctx.Done(): + // if the context is closed, then we should stop sending updates + ticker.Stop() + return + case <-stop: + // closeFunc was called, so stop updating the watcher + return + case <-ticker.C: + // the configuration has "changed". Notify the watcher that a new config is available + // the watcher is expected to call Provider.Retrieve again to get the update + // note that the collector calls closeFunc before calling Retrieve for the second time, + // so these go functions don't accumulate indefinitely. (see otelcol/collector.go, Collector.reloadConfiguration) + watcher(&ChangeEvent{}) + } + } + }() + + return retrieved, nil +} + +func ExampleProvider() { + provider := UpdatingProvider{} + + receivedNotification := make(chan bool) + + watcherFunc := func(_ *ChangeEvent) { + fmt.Println("received notification of new config") + receivedNotification <- true + } + + retrieved, err := provider.Retrieve(context.Background(), "example", watcherFunc) + if err != nil { + fmt.Println("received an error") + } else { + fmt.Printf("received: %s\n", retrieved.rawConf) + } + + // after one second, we should receive a notification that config has changed + <-receivedNotification + // signal that we no longer want updates + retrieved.Close(context.Background()) + + // Output: + // received: hello + // received notification of new config +} + func TestNewRetrieved(t *testing.T) { ret, err := NewRetrieved(nil) require.NoError(t, err) diff --git a/connector/connectortest/go.mod b/connector/connectortest/go.mod index d52cb20b5358..0302fb3dda9c 100644 --- a/connector/connectortest/go.mod +++ b/connector/connectortest/go.mod @@ -41,9 +41,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/connector/connectortest/go.sum b/connector/connectortest/go.sum index 72d2e725c6a8..d47340448917 100644 --- a/connector/connectortest/go.sum +++ b/connector/connectortest/go.sum @@ -87,12 +87,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/connector/forwardconnector/go.mod b/connector/forwardconnector/go.mod index b721c9112517..f44ef5be79d8 100644 --- a/connector/forwardconnector/go.mod +++ b/connector/forwardconnector/go.mod @@ -49,9 +49,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/connector/forwardconnector/go.sum b/connector/forwardconnector/go.sum index 6686af8fbb16..8bd3034e9c01 100644 --- a/connector/forwardconnector/go.sum +++ b/connector/forwardconnector/go.sum @@ -99,12 +99,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/connector/go.mod b/connector/go.mod index 2320f60a5889..e07d59b194ca 100644 --- a/connector/go.mod +++ b/connector/go.mod @@ -33,9 +33,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/connector/go.sum b/connector/go.sum index afff6baef2ce..41634156c889 100644 --- a/connector/go.sum +++ b/connector/go.sum @@ -43,10 +43,10 @@ go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -86,12 +86,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/connector/xconnector/go.mod b/connector/xconnector/go.mod index 80c9217b68aa..5bbc669fb109 100644 --- a/connector/xconnector/go.mod +++ b/connector/xconnector/go.mod @@ -33,9 +33,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/connector/xconnector/go.sum b/connector/xconnector/go.sum index afff6baef2ce..41634156c889 100644 --- a/connector/xconnector/go.sum +++ b/connector/xconnector/go.sum @@ -43,10 +43,10 @@ go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -86,12 +86,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/consumer/consumererror/go.mod b/consumer/consumererror/go.mod index 54a23523d547..1e8c06e60c72 100644 --- a/consumer/consumererror/go.mod +++ b/consumer/consumererror/go.mod @@ -21,9 +21,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/consumer/consumererror/go.sum b/consumer/consumererror/go.sum index a325492a9929..edc81fe738b9 100644 --- a/consumer/consumererror/go.sum +++ b/consumer/consumererror/go.sum @@ -37,16 +37,16 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -82,12 +82,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/consumer/consumererror/xconsumererror/go.mod b/consumer/consumererror/xconsumererror/go.mod index fb3b77964cfa..14f3c7c2bf65 100644 --- a/consumer/consumererror/xconsumererror/go.mod +++ b/consumer/consumererror/xconsumererror/go.mod @@ -21,9 +21,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/consumer/consumererror/xconsumererror/go.sum b/consumer/consumererror/xconsumererror/go.sum index a325492a9929..edc81fe738b9 100644 --- a/consumer/consumererror/xconsumererror/go.sum +++ b/consumer/consumererror/xconsumererror/go.sum @@ -37,16 +37,16 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -82,12 +82,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/consumer/consumertest/go.mod b/consumer/consumertest/go.mod index c6a97a6c2251..51c07d4ec5a1 100644 --- a/consumer/consumertest/go.mod +++ b/consumer/consumertest/go.mod @@ -25,9 +25,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/consumer/consumertest/go.sum b/consumer/consumertest/go.sum index a325492a9929..edc81fe738b9 100644 --- a/consumer/consumertest/go.sum +++ b/consumer/consumertest/go.sum @@ -37,16 +37,16 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -82,12 +82,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/consumer/go.mod b/consumer/go.mod index d2e7e8d1ea04..191535a3c6b3 100644 --- a/consumer/go.mod +++ b/consumer/go.mod @@ -20,9 +20,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/consumer/go.sum b/consumer/go.sum index 1a6bba54854c..64ba821605e4 100644 --- a/consumer/go.sum +++ b/consumer/go.sum @@ -38,16 +38,16 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -83,12 +83,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/consumer/xconsumer/go.mod b/consumer/xconsumer/go.mod index f44ffa73bb6c..9baead6bc554 100644 --- a/consumer/xconsumer/go.mod +++ b/consumer/xconsumer/go.mod @@ -20,9 +20,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/consumer/xconsumer/go.sum b/consumer/xconsumer/go.sum index a325492a9929..edc81fe738b9 100644 --- a/consumer/xconsumer/go.sum +++ b/consumer/xconsumer/go.sum @@ -37,16 +37,16 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -82,12 +82,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/docs/rfcs/component-universal-telemetry.md b/docs/rfcs/component-universal-telemetry.md index 4a721fbad1b5..a13ed7bfeaf6 100644 --- a/docs/rfcs/component-universal-telemetry.md +++ b/docs/rfcs/component-universal-telemetry.md @@ -19,7 +19,7 @@ be automatically captured for each kind of pipeline component. ## Goals -1. Define attributes that are (A) specific enough to describe individual component[_instances_](https://github.com/open-telemetry/opentelemetry-collector/issues/10534) +1. Define attributes that are (A) specific enough to describe individual component [_instances_](https://github.com/open-telemetry/opentelemetry-collector/issues/10534) and (B) consistent enough for correlation across signals. 2. Articulate a mechanism which enables us to _automatically_ capture telemetry from _all pipeline components_. 3. Define specific metrics for each kind of pipeline component. @@ -46,14 +46,14 @@ All signals should use the following attributes: - `otelcol.component.kind`: `exporter` - `otelcol.component.id`: The component ID -- `otelcol.signal`: `logs`, `metrics` `traces`, `profiles` +- `otelcol.signal`: `logs`, `metrics`, `traces`, `profiles` ### Connectors - `otelcol.component.kind`: `connector` - `otelcol.component.id`: The component ID - `otelcol.signal`: `logs`, `metrics` `traces` -- `otelcol.signal.output`: `logs`, `metrics` `traces`, `profiles` +- `otelcol.signal.output`: `logs`, `metrics`, `traces`, `profiles` Note: The `otelcol.signal`, `otelcol.signal.output`, or `otelcol.pipeline.id` attributes may be omitted if the corresponding component instances are unified by the component implementation. For example, the `otlp` receiver is a singleton, so its telemetry is not specific to a signal. @@ -90,11 +90,20 @@ The location of these measurements can be described in terms of whether the data component to which the telemetry is attributed. Metrics which contain the term "produced" describe data which is emitted from the component, while metrics which contain the term "consumed" describe data which is received by the component. -For both metrics, an `outcome` attribute with possible values `success` and `failure` should be automatically recorded, corresponding to -whether or not the corresponding function call returned an error. Specifically, consumed measurements will be recorded with `outcome` as -`failure` when a call from the previous component the `ConsumeX` function returns an error, and `success` otherwise. Likewise, produced -measurements will be recorded with `outcome` as `failure` when a call to the next consumer's `ConsumeX` function returns an error, and -`success` otherwise. +For both metrics, an `outcome` attribute with possible values `success`, `failure`, and `refused` should be automatically recorded, +based on whether the corresponding function call returned successfully, returned an internal error, or propagated an error from a +component further downstream. + +Specifically, a call to `ConsumeX` is recorded with: +- `outcome = success` if the call returns `nil`; +- `outcome = failure` if the call returns a regular error; +- `outcome = refused` if the call returns an error tagged as coming from downstream. +After inspecting the error, the instrumentation layer should tag it as coming from downstream before returning it to the parent component. + +The upstream component which called `ConsumeX` will have this `outcome` attribute applied to its produced measurements, and the downstream +component that `ConsumeX` was called on will have the attribute applied to its consumed measurements. + +Errors should be "tagged as coming from downstream" the same way permanent errors are currently handled: they can be wrapped in a `type downstreamError struct { err error }` wrapper error type, then checked with `errors.As`. Note that care may need to be taken when dealing with the `multiError`s returned by the `fanoutconsumer`. If PR #11085 introducing a single generic `Error` type is merged, an additional `downstream bool` field can be added to it to serve the same purpose instead. ```yaml otelcol.receiver.produced.items: @@ -140,7 +149,7 @@ measurements will be recorded with `outcome` as `failure` when a call to the nex value_type: int monotonic: true - otelcol.receiver.produced.size: + otelcol.receiver.produced.size: enabled: false description: Size of items emitted from the receiver. unit: "By" @@ -187,7 +196,7 @@ measurements will be recorded with `outcome` as `failure` when a call to the nex ### Auto-Instrumented Logs Metrics provide most of the observability we need but there are some gaps which logs can fill. Although metrics would describe the overall -item counts, it is helpful in some cases to record more granular events. e.g. If a produced batch of 10,000 spans results in an error, but +item counts, it is helpful in some cases to record more granular events. For example, if a produced batch of 10,000 spans results in an error, but 100 batches of 100 spans succeed, this may be a matter of batch size that can be detected by analyzing logs, while the corresponding metric reports only that a 50% success rate is observed. diff --git a/exporter/debugexporter/go.mod b/exporter/debugexporter/go.mod index 2cebb1d4c390..e9983c8f1e8e 100644 --- a/exporter/debugexporter/go.mod +++ b/exporter/debugexporter/go.mod @@ -61,9 +61,9 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.33.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/exporter/debugexporter/go.sum b/exporter/debugexporter/go.sum index e50ba545ebed..47db8db1b392 100644 --- a/exporter/debugexporter/go.sum +++ b/exporter/debugexporter/go.sum @@ -103,12 +103,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/exporter/exporterhelper/internal/base_exporter.go b/exporter/exporterhelper/internal/base_exporter.go index dfebb0d1086b..494c3aa0c924 100644 --- a/exporter/exporterhelper/internal/base_exporter.go +++ b/exporter/exporterhelper/internal/base_exporter.go @@ -27,12 +27,12 @@ import ( var usePullingBasedExporterQueueBatcher = featuregate.GlobalRegistry().MustRegister( "exporter.UsePullingBasedExporterQueueBatcher", - featuregate.StageBeta, + featuregate.StageAlpha, featuregate.WithRegisterFromVersion("v0.115.0"), featuregate.WithRegisterDescription("if set to true, turns on the pulling-based exporter queue bathcer"), ) -type ObsrepSenderFactory = func(obsrep *ObsReport) Sender[internal.Request] +type ObsrepSenderFactory = func(obsrep *ObsReport, next Sender[internal.Request]) Sender[internal.Request] // Option apply changes to BaseExporter. type Option func(*BaseExporter) error @@ -44,8 +44,7 @@ type BaseExporter struct { Marshaler exporterqueue.Marshaler[internal.Request] Unmarshaler exporterqueue.Unmarshaler[internal.Request] - Set exporter.Settings - Obsrep *ObsReport + Set exporter.Settings // Message for the user to be added with an export failure message. ExportFailureMessage string @@ -53,17 +52,20 @@ type BaseExporter struct { // Chain of senders that the exporter helper applies before passing the data to the actual exporter. // The data is handled by each sender in the respective order starting from the queueSender. // Most of the senders are optional, and initialized with a no-op path-through sender. - BatchSender Sender[internal.Request] - QueueSender Sender[internal.Request] - ObsrepSender Sender[internal.Request] - RetrySender Sender[internal.Request] - TimeoutSender *TimeoutSender // TimeoutSender is always initialized. + BatchSender Sender[internal.Request] + QueueSender Sender[internal.Request] + ObsrepSender Sender[internal.Request] + RetrySender Sender[internal.Request] + + firstSender Sender[internal.Request] ConsumerOptions []consumer.Option - queueCfg exporterqueue.Config + timeoutCfg TimeoutConfig + retryCfg configretry.BackOffConfig queueFactory exporterqueue.Factory[internal.Request] - BatcherCfg exporterbatcher.Config + queueCfg exporterqueue.Config + batcherCfg exporterbatcher.Config } func NewBaseExporter(set exporter.Settings, signal pipeline.Signal, osf ObsrepSenderFactory, options ...Option) (*BaseExporter, error) { @@ -73,49 +75,50 @@ func NewBaseExporter(set exporter.Settings, signal pipeline.Signal, osf ObsrepSe } be := &BaseExporter{ - BatchSender: &BaseSender[internal.Request]{}, - QueueSender: &BaseSender[internal.Request]{}, - ObsrepSender: osf(obsReport), - RetrySender: &BaseSender[internal.Request]{}, - TimeoutSender: &TimeoutSender{cfg: NewDefaultTimeoutConfig()}, - - Set: set, - Obsrep: obsReport, + timeoutCfg: NewDefaultTimeoutConfig(), + Set: set, } for _, op := range options { - err = multierr.Append(err, op(be)) - } - if err != nil { - return nil, err + if err = op(be); err != nil { + return nil, err + } } - if be.queueCfg.Enabled { - q := be.queueFactory( - context.Background(), - exporterqueue.Settings{ - Signal: signal, - ExporterSettings: be.Set, - }, - be.queueCfg) - be.QueueSender = NewQueueSender(q, be.Set, be.queueCfg.NumConsumers, be.ExportFailureMessage, be.Obsrep, be.BatcherCfg) + // TimeoutSender is always initialized. + be.firstSender = &TimeoutSender{cfg: be.timeoutCfg} + if be.retryCfg.Enabled { + be.RetrySender = newRetrySender(be.retryCfg, set, be.firstSender) + be.firstSender = be.RetrySender } - if !usePullingBasedExporterQueueBatcher.IsEnabled() && be.BatcherCfg.Enabled || - usePullingBasedExporterQueueBatcher.IsEnabled() && be.BatcherCfg.Enabled && !be.queueCfg.Enabled { - bs := NewBatchSender(be.BatcherCfg, be.Set) - be.BatchSender = bs + be.ObsrepSender = osf(obsReport, be.firstSender) + be.firstSender = be.ObsrepSender + + if be.batcherCfg.Enabled { + // Batcher mutates the data. + be.ConsumerOptions = append(be.ConsumerOptions, consumer.WithCapabilities(consumer.Capabilities{MutatesData: true})) } - be.connectSenders() + if be.batcherCfg.Enabled && !(usePullingBasedExporterQueueBatcher.IsEnabled() && be.queueCfg.Enabled) { + concurrencyLimit := int64(0) + if be.queueCfg.Enabled { + concurrencyLimit = int64(be.queueCfg.NumConsumers) + } + be.BatchSender = NewBatchSender(be.batcherCfg, set, concurrencyLimit, be.firstSender) + be.firstSender = be.BatchSender + } - if bs, ok := be.BatchSender.(*BatchSender); ok { - // If queue sender is enabled assign to the batch sender the same number of workers. - if qs, ok := be.QueueSender.(*QueueSender); ok { - bs.concurrencyLimit = int64(qs.numConsumers) + if be.queueCfg.Enabled { + qSet := exporterqueue.Settings{ + Signal: signal, + ExporterSettings: set, } - // Batcher sender mutates the data. - be.ConsumerOptions = append(be.ConsumerOptions, consumer.WithCapabilities(consumer.Capabilities{MutatesData: true})) + be.QueueSender, err = NewQueueSender(be.queueFactory, qSet, be.queueCfg, be.batcherCfg, be.ExportFailureMessage, be.firstSender) + if err != nil { + return nil, err + } + be.firstSender = be.QueueSender } return be, nil @@ -123,7 +126,7 @@ func NewBaseExporter(set exporter.Settings, signal pipeline.Signal, osf ObsrepSe // Send sends the request using the first sender in the chain. func (be *BaseExporter) Send(ctx context.Context, req internal.Request) error { - err := be.QueueSender.Send(ctx, req) + err := be.firstSender.Send(ctx, req) if err != nil { be.Set.Logger.Error("Exporting failed. Rejecting data."+be.ExportFailureMessage, zap.Error(err), zap.Int("rejected_items", req.ItemsCount())) @@ -131,39 +134,47 @@ func (be *BaseExporter) Send(ctx context.Context, req internal.Request) error { return err } -// connectSenders connects the senders in the predefined order. -func (be *BaseExporter) connectSenders() { - be.QueueSender.SetNextSender(be.BatchSender) - be.BatchSender.SetNextSender(be.ObsrepSender) - be.ObsrepSender.SetNextSender(be.RetrySender) - be.RetrySender.SetNextSender(be.TimeoutSender) -} - func (be *BaseExporter) Start(ctx context.Context, host component.Host) error { // First start the wrapped exporter. if err := be.StartFunc.Start(ctx, host); err != nil { return err } - // If no error then start the BatchSender. - if err := be.BatchSender.Start(ctx, host); err != nil { - return err + if be.BatchSender != nil { + // If no error then start the BatchSender. + if err := be.BatchSender.Start(ctx, host); err != nil { + return err + } } // Last start the queueSender. - return be.QueueSender.Start(ctx, host) + if be.QueueSender != nil { + return be.QueueSender.Start(ctx, host) + } + + return nil } func (be *BaseExporter) Shutdown(ctx context.Context) error { - return multierr.Combine( - // First shutdown the retry sender, so the queue sender can flush the queue without retries. - be.RetrySender.Shutdown(ctx), - // Then shutdown the batch sender - be.BatchSender.Shutdown(ctx), - // Then shutdown the queue sender. - be.QueueSender.Shutdown(ctx), - // Last shutdown the wrapped exporter itself. - be.ShutdownFunc.Shutdown(ctx)) + var err error + + // First shutdown the retry sender, so the queue sender can flush the queue without retries. + if be.RetrySender != nil { + err = multierr.Append(err, be.RetrySender.Shutdown(ctx)) + } + + // Then shutdown the batch sender + if be.BatchSender != nil { + err = multierr.Append(err, be.BatchSender.Shutdown(ctx)) + } + + // Then shutdown the queue sender. + if be.QueueSender != nil { + err = multierr.Append(err, be.QueueSender.Shutdown(ctx)) + } + + // Last shutdown the wrapped exporter itself. + return multierr.Append(err, be.ShutdownFunc.Shutdown(ctx)) } // WithStart overrides the default Start function for an exporter. @@ -188,7 +199,7 @@ func WithShutdown(shutdown component.ShutdownFunc) Option { // The default TimeoutConfig is 5 seconds. func WithTimeout(timeoutConfig TimeoutConfig) Option { return func(o *BaseExporter) error { - o.TimeoutSender.cfg = timeoutConfig + o.timeoutCfg = timeoutConfig return nil } } @@ -201,7 +212,7 @@ func WithRetry(config configretry.BackOffConfig) Option { o.ExportFailureMessage += " Try enabling retry_on_failure config option to retry on retryable errors." return nil } - o.RetrySender = newRetrySender(config, o.Set) + o.retryCfg = config return nil } } @@ -268,7 +279,7 @@ func WithCapabilities(capabilities consumer.Capabilities) Option { // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. func WithBatcher(cfg exporterbatcher.Config) Option { return func(o *BaseExporter) error { - o.BatcherCfg = cfg + o.batcherCfg = cfg return nil } } diff --git a/exporter/exporterhelper/internal/base_exporter_test.go b/exporter/exporterhelper/internal/base_exporter_test.go index 12c56bb76a08..d71202ac3db3 100644 --- a/exporter/exporterhelper/internal/base_exporter_test.go +++ b/exporter/exporterhelper/internal/base_exporter_test.go @@ -33,8 +33,20 @@ var ( }() ) -func newNoopObsrepSender(*ObsReport) Sender[internal.Request] { - return &BaseSender[internal.Request]{} +type noopSender struct { + component.StartFunc + component.ShutdownFunc + SendFunc[internal.Request] +} + +func newNoopExportSender() Sender[internal.Request] { + return &noopSender{SendFunc: func(ctx context.Context, req internal.Request) error { + return req.Export(ctx) + }} +} + +func newNoopObsrepSender(_ *ObsReport, next Sender[internal.Request]) Sender[internal.Request] { + return &noopSender{SendFunc: next.Send} } func TestBaseExporter(t *testing.T) { @@ -106,7 +118,7 @@ func TestBaseExporterLogging(t *testing.T) { rCfg.Enabled = false bs, err := NewBaseExporter(set, defaultSignal, newNoopObsrepSender, WithRetry(rCfg)) require.NoError(t, err) - sendErr := bs.Send(context.Background(), newErrorRequest()) + sendErr := bs.Send(context.Background(), newErrorRequest(errors.New("my error"))) require.Error(t, sendErr) require.Len(t, observed.FilterLevelExact(zap.ErrorLevel).All(), 1) diff --git a/exporter/exporterhelper/internal/batch_sender.go b/exporter/exporterhelper/internal/batch_sender.go index 4cb3ace63b02..51aa700d3abf 100644 --- a/exporter/exporterhelper/internal/batch_sender.go +++ b/exporter/exporterhelper/internal/batch_sender.go @@ -23,8 +23,8 @@ import ( // - cfg.FlushTimeout is elapsed since the timestamp when the previous batch was sent out. // - concurrencyLimit is reached. type BatchSender struct { - BaseSender[internal.Request] - cfg exporterbatcher.Config + cfg exporterbatcher.Config + next Sender[internal.Request] // concurrencyLimit is the maximum number of goroutines that can be blocked by the batcher. // If this number is reached and all the goroutines are busy, the batch will be sent right away. @@ -43,11 +43,13 @@ type BatchSender struct { stopped *atomic.Bool } -// newBatchSender returns a new batch consumer component. -func NewBatchSender(cfg exporterbatcher.Config, set exporter.Settings) *BatchSender { +// NewBatchSender returns a new batch consumer component. +func NewBatchSender(cfg exporterbatcher.Config, set exporter.Settings, concurrencyLimit int64, next Sender[internal.Request]) *BatchSender { bs := &BatchSender{ - activeBatch: newEmptyBatch(), cfg: cfg, + next: next, + concurrencyLimit: concurrencyLimit, + activeBatch: newEmptyBatch(), logger: set.Logger, shutdownCh: nil, shutdownCompleteCh: make(chan struct{}), @@ -119,7 +121,7 @@ func newEmptyBatch() *batch { // Caller must hold the lock. func (bs *BatchSender) exportActiveBatch() { go func(b *batch) { - b.err = bs.NextSender.Send(b.ctx, b.request) + b.err = bs.next.Send(b.ctx, b.request) close(b.done) bs.activeRequests.Add(-b.requestsBlocked) }(bs.activeBatch) @@ -138,7 +140,7 @@ func (bs *BatchSender) isActiveBatchReady() bool { func (bs *BatchSender) Send(ctx context.Context, req internal.Request) error { // Stopped batch sender should act as pass-through to allow the queue to be drained. if bs.stopped.Load() { - return bs.NextSender.Send(ctx, req) + return bs.next.Send(ctx, req) } if bs.cfg.MaxSizeItems > 0 { @@ -190,7 +192,7 @@ func (bs *BatchSender) sendMergeSplitBatch(ctx context.Context, req internal.Req // Intentionally do not put the last request in the active batch to not block it. // TODO: Consider including the partial request in the error to avoid double publishing. for _, r := range reqs { - if err := bs.NextSender.Send(ctx, r); err != nil { + if err := bs.next.Send(ctx, r); err != nil { return err } } diff --git a/exporter/exporterhelper/internal/batch_sender_test.go b/exporter/exporterhelper/internal/batch_sender_test.go index ede5a7dd84bf..6263ae514040 100644 --- a/exporter/exporterhelper/internal/batch_sender_test.go +++ b/exporter/exporterhelper/internal/batch_sender_test.go @@ -374,14 +374,6 @@ func TestBatchSender_ConcurrencyLimitReached(t *testing.T) { expectedItems: 51, }, } - - // Why do we not expect the same behavior when usePullingBasedExporterQueueBatcher is true? - // This test checks that when concurrency limit of batch_sender is reached, the batch_sender will flush immediately. - // To avoid blocking, the concurrency limit is set to the number of concurrent goroutines that are in charge of - // reading from the queue and adding to batch. With the new model, we are pulling instead of pushing so we don't - // block the reading goroutine anymore. - defer setFeatureGateForTest(t, usePullingBasedExporterQueueBatcher, false)() - for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { qCfg := exporterqueue.NewDefaultConfig() diff --git a/exporter/exporterhelper/internal/metadata/generated_telemetry.go b/exporter/exporterhelper/internal/metadata/generated_telemetry.go index dde220119330..28f03fdb7fec 100644 --- a/exporter/exporterhelper/internal/metadata/generated_telemetry.go +++ b/exporter/exporterhelper/internal/metadata/generated_telemetry.go @@ -5,8 +5,10 @@ package metadata import ( "context" "errors" + "sync" "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/embedded" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" @@ -24,17 +26,23 @@ func Tracer(settings component.TelemetrySettings) trace.Tracer { // as defined in metadata and user config. type TelemetryBuilder struct { meter metric.Meter + mu sync.Mutex + registrations []metric.Registration ExporterEnqueueFailedLogRecords metric.Int64Counter ExporterEnqueueFailedMetricPoints metric.Int64Counter ExporterEnqueueFailedSpans metric.Int64Counter ExporterQueueCapacity metric.Int64ObservableGauge - ExporterQueueSize metric.Int64ObservableGauge - ExporterSendFailedLogRecords metric.Int64Counter - ExporterSendFailedMetricPoints metric.Int64Counter - ExporterSendFailedSpans metric.Int64Counter - ExporterSentLogRecords metric.Int64Counter - ExporterSentMetricPoints metric.Int64Counter - ExporterSentSpans metric.Int64Counter + // TODO: Remove in v0.119.0 when remove deprecated funcs. + observeExporterQueueCapacity func(context.Context, metric.Observer) error + ExporterQueueSize metric.Int64ObservableGauge + // TODO: Remove in v0.119.0 when remove deprecated funcs. + observeExporterQueueSize func(context.Context, metric.Observer) error + ExporterSendFailedLogRecords metric.Int64Counter + ExporterSendFailedMetricPoints metric.Int64Counter + ExporterSendFailedSpans metric.Int64Counter + ExporterSentLogRecords metric.Int64Counter + ExporterSentMetricPoints metric.Int64Counter + ExporterSentSpans metric.Int64Counter } // TelemetryBuilderOption applies changes to default builder. @@ -48,40 +56,73 @@ func (tbof telemetryBuilderOptionFunc) apply(mb *TelemetryBuilder) { tbof(mb) } -// InitExporterQueueCapacity configures the ExporterQueueCapacity metric. -func (builder *TelemetryBuilder) InitExporterQueueCapacity(cb func() int64, opts ...metric.ObserveOption) (metric.Registration, error) { - var err error - builder.ExporterQueueCapacity, err = builder.meter.Int64ObservableGauge( - "otelcol_exporter_queue_capacity", - metric.WithDescription("Fixed capacity of the retry queue (in batches)"), - metric.WithUnit("{batches}"), - ) - if err != nil { - return nil, err - } - reg, err := builder.meter.RegisterCallback(func(_ context.Context, o metric.Observer) error { - o.ObserveInt64(builder.ExporterQueueCapacity, cb(), opts...) - return nil - }, builder.ExporterQueueCapacity) - return reg, err +// Deprecated: [v0.119.0] use RegisterExporterQueueCapacityCallback. +func WithExporterQueueCapacityCallback(cb func() int64, opts ...metric.ObserveOption) TelemetryBuilderOption { + return telemetryBuilderOptionFunc(func(builder *TelemetryBuilder) { + builder.observeExporterQueueCapacity = func(_ context.Context, o metric.Observer) error { + o.ObserveInt64(builder.ExporterQueueCapacity, cb(), opts...) + return nil + } + }) } -// InitExporterQueueSize configures the ExporterQueueSize metric. -func (builder *TelemetryBuilder) InitExporterQueueSize(cb func() int64, opts ...metric.ObserveOption) (metric.Registration, error) { - var err error - builder.ExporterQueueSize, err = builder.meter.Int64ObservableGauge( - "otelcol_exporter_queue_size", - metric.WithDescription("Current size of the retry queue (in batches)"), - metric.WithUnit("{batches}"), - ) +// RegisterExporterQueueCapacityCallback sets callback for observable ExporterQueueCapacity metric. +func (builder *TelemetryBuilder) RegisterExporterQueueCapacityCallback(cb metric.Int64Callback) error { + reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { + cb(ctx, &observerInt64{inst: builder.ExporterQueueCapacity, obs: o}) + return nil + }, builder.ExporterQueueCapacity) if err != nil { - return nil, err + return err } - reg, err := builder.meter.RegisterCallback(func(_ context.Context, o metric.Observer) error { - o.ObserveInt64(builder.ExporterQueueSize, cb(), opts...) + builder.mu.Lock() + defer builder.mu.Unlock() + builder.registrations = append(builder.registrations, reg) + return nil +} + +// Deprecated: [v0.119.0] use RegisterExporterQueueSizeCallback. +func WithExporterQueueSizeCallback(cb func() int64, opts ...metric.ObserveOption) TelemetryBuilderOption { + return telemetryBuilderOptionFunc(func(builder *TelemetryBuilder) { + builder.observeExporterQueueSize = func(_ context.Context, o metric.Observer) error { + o.ObserveInt64(builder.ExporterQueueSize, cb(), opts...) + return nil + } + }) +} + +// RegisterExporterQueueSizeCallback sets callback for observable ExporterQueueSize metric. +func (builder *TelemetryBuilder) RegisterExporterQueueSizeCallback(cb metric.Int64Callback) error { + reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { + cb(ctx, &observerInt64{inst: builder.ExporterQueueSize, obs: o}) return nil }, builder.ExporterQueueSize) - return reg, err + if err != nil { + return err + } + builder.mu.Lock() + defer builder.mu.Unlock() + builder.registrations = append(builder.registrations, reg) + return nil +} + +type observerInt64 struct { + embedded.Int64Observer + inst metric.Int64Observable + obs metric.Observer +} + +func (oi *observerInt64) Observe(value int64, opts ...metric.ObserveOption) { + oi.obs.ObserveInt64(oi.inst, value, opts...) +} + +// Shutdown unregister all registered callbacks for async instruments. +func (builder *TelemetryBuilder) Shutdown() { + builder.mu.Lock() + defer builder.mu.Unlock() + for _, reg := range builder.registrations { + reg.Unregister() + } } // NewTelemetryBuilder provides a struct with methods to update all internal telemetry @@ -111,6 +152,32 @@ func NewTelemetryBuilder(settings component.TelemetrySettings, options ...Teleme metric.WithUnit("{spans}"), ) errs = errors.Join(errs, err) + builder.ExporterQueueCapacity, err = builder.meter.Int64ObservableGauge( + "otelcol_exporter_queue_capacity", + metric.WithDescription("Fixed capacity of the retry queue (in batches) [alpha]"), + metric.WithUnit("{batches}"), + ) + errs = errors.Join(errs, err) + if builder.observeExporterQueueCapacity != nil { + reg, err := builder.meter.RegisterCallback(builder.observeExporterQueueCapacity, builder.ExporterQueueCapacity) + errs = errors.Join(errs, err) + if err == nil { + builder.registrations = append(builder.registrations, reg) + } + } + builder.ExporterQueueSize, err = builder.meter.Int64ObservableGauge( + "otelcol_exporter_queue_size", + metric.WithDescription("Current size of the retry queue (in batches) [alpha]"), + metric.WithUnit("{batches}"), + ) + errs = errors.Join(errs, err) + if builder.observeExporterQueueSize != nil { + reg, err := builder.meter.RegisterCallback(builder.observeExporterQueueSize, builder.ExporterQueueSize) + errs = errors.Join(errs, err) + if err == nil { + builder.registrations = append(builder.registrations, reg) + } + } builder.ExporterSendFailedLogRecords, err = builder.meter.Int64Counter( "otelcol_exporter_send_failed_log_records", metric.WithDescription("Number of log records in failed attempts to send to destination. [alpha]"), diff --git a/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest.go b/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest.go index 9aa491c001f5..9619749ff3c9 100644 --- a/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest.go +++ b/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest.go @@ -10,32 +10,26 @@ import ( "go.opentelemetry.io/otel/sdk/metric/metricdata" "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" - "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" - "go.opentelemetry.io/collector/exporter" - "go.opentelemetry.io/collector/exporter/exportertest" ) +// Deprecated: [v0.119.0] Use componenttest.Telemetry type Telemetry struct { - componenttest.Telemetry + *componenttest.Telemetry } +// Deprecated: [v0.119.0] Use componenttest.NewTelemetry func SetupTelemetry(opts ...componenttest.TelemetryOption) Telemetry { return Telemetry{Telemetry: componenttest.NewTelemetry(opts...)} } -func (tt *Telemetry) NewSettings() exporter.Settings { - set := exportertest.NewNopSettings() - set.ID = component.NewID(component.MustNewType("exporterhelper")) - set.TelemetrySettings = tt.NewTelemetrySettings() - return set -} +// Deprecated: [v0.119.0] Use metadatatest.AssertEqual* func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { var md metricdata.ResourceMetrics require.NoError(t, tt.Reader.Collect(context.Background(), &md)) // ensure all required metrics are present for _, want := range expected { - got := getMetric(want.Name, md) + got := getMetricFromResource(want.Name, md) metricdatatest.AssertEqual(t, want, got, opts...) } @@ -43,7 +37,179 @@ func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, require.Equal(t, len(expected), lenMetrics(md)) } -func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { +func AssertEqualExporterEnqueueFailedLogRecords(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_exporter_enqueue_failed_log_records", + Description: "Number of log records failed to be added to the sending queue. [alpha]", + Unit: "{records}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_exporter_enqueue_failed_log_records") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualExporterEnqueueFailedMetricPoints(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_exporter_enqueue_failed_metric_points", + Description: "Number of metric points failed to be added to the sending queue. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_exporter_enqueue_failed_metric_points") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualExporterEnqueueFailedSpans(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_exporter_enqueue_failed_spans", + Description: "Number of spans failed to be added to the sending queue. [alpha]", + Unit: "{spans}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_exporter_enqueue_failed_spans") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualExporterQueueCapacity(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_exporter_queue_capacity", + Description: "Fixed capacity of the retry queue (in batches) [alpha]", + Unit: "{batches}", + Data: metricdata.Gauge[int64]{ + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_exporter_queue_capacity") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualExporterQueueSize(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_exporter_queue_size", + Description: "Current size of the retry queue (in batches) [alpha]", + Unit: "{batches}", + Data: metricdata.Gauge[int64]{ + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_exporter_queue_size") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualExporterSendFailedLogRecords(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_exporter_send_failed_log_records", + Description: "Number of log records in failed attempts to send to destination. [alpha]", + Unit: "{records}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_exporter_send_failed_log_records") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualExporterSendFailedMetricPoints(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_exporter_send_failed_metric_points", + Description: "Number of metric points in failed attempts to send to destination. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_exporter_send_failed_metric_points") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualExporterSendFailedSpans(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_exporter_send_failed_spans", + Description: "Number of spans in failed attempts to send to destination. [alpha]", + Unit: "{spans}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_exporter_send_failed_spans") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualExporterSentLogRecords(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_exporter_sent_log_records", + Description: "Number of log record successfully sent to destination. [alpha]", + Unit: "{records}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_exporter_sent_log_records") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualExporterSentMetricPoints(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_exporter_sent_metric_points", + Description: "Number of metric points successfully sent to destination. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_exporter_sent_metric_points") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualExporterSentSpans(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_exporter_sent_spans", + Description: "Number of spans successfully sent to destination. [alpha]", + Unit: "{spans}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_exporter_sent_spans") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func getMetricFromResource(name string, got metricdata.ResourceMetrics) metricdata.Metrics { for _, sm := range got.ScopeMetrics { for _, m := range sm.Metrics { if m.Name == name { diff --git a/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest_test.go b/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest_test.go index ba7584abdf3f..1662b1b2bdb2 100644 --- a/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest_test.go +++ b/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/sdk/metric/metricdata" "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" @@ -15,11 +16,17 @@ import ( func TestSetupTelemetry(t *testing.T) { testTel := SetupTelemetry() - tb, err := metadata.NewTelemetryBuilder( - testTel.NewTelemetrySettings(), - ) + tb, err := metadata.NewTelemetryBuilder(testTel.NewTelemetrySettings()) require.NoError(t, err) - require.NotNil(t, tb) + defer tb.Shutdown() + require.NoError(t, tb.RegisterExporterQueueCapacityCallback(func(_ context.Context, observer metric.Int64Observer) error { + observer.Observe(1) + return nil + })) + require.NoError(t, tb.RegisterExporterQueueSizeCallback(func(_ context.Context, observer metric.Int64Observer) error { + observer.Observe(1) + return nil + })) tb.ExporterEnqueueFailedLogRecords.Add(context.Background(), 1) tb.ExporterEnqueueFailedMetricPoints.Add(context.Background(), 1) tb.ExporterEnqueueFailedSpans.Add(context.Background(), 1) @@ -67,6 +74,26 @@ func TestSetupTelemetry(t *testing.T) { }, }, }, + { + Name: "otelcol_exporter_queue_capacity", + Description: "Fixed capacity of the retry queue (in batches) [alpha]", + Unit: "{batches}", + Data: metricdata.Gauge[int64]{ + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_exporter_queue_size", + Description: "Current size of the retry queue (in batches) [alpha]", + Unit: "{batches}", + Data: metricdata.Gauge[int64]{ + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, { Name: "otelcol_exporter_send_failed_log_records", Description: "Number of log records in failed attempts to send to destination. [alpha]", @@ -140,5 +167,39 @@ func TestSetupTelemetry(t *testing.T) { }, }, }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + AssertEqualExporterEnqueueFailedLogRecords(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualExporterEnqueueFailedMetricPoints(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualExporterEnqueueFailedSpans(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualExporterQueueCapacity(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualExporterQueueSize(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualExporterSendFailedLogRecords(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualExporterSendFailedMetricPoints(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualExporterSendFailedSpans(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualExporterSentLogRecords(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualExporterSentMetricPoints(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualExporterSentSpans(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + require.NoError(t, testTel.Shutdown(context.Background())) } diff --git a/exporter/exporterhelper/internal/obs_queue.go b/exporter/exporterhelper/internal/obs_queue.go new file mode 100644 index 000000000000..594affd14bb5 --- /dev/null +++ b/exporter/exporterhelper/internal/obs_queue.go @@ -0,0 +1,81 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package internal // import "go.opentelemetry.io/collector/exporter/exporterhelper/internal" + +import ( + "context" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" + + "go.opentelemetry.io/collector/exporter/exporterhelper/internal/metadata" + "go.opentelemetry.io/collector/exporter/exporterqueue" + "go.opentelemetry.io/collector/exporter/internal" + "go.opentelemetry.io/collector/pipeline" +) + +// obsQueue is a helper to add observability to a queue. +type obsQueue[T internal.Request] struct { + exporterqueue.Queue[T] + tb *metadata.TelemetryBuilder + metricAttr metric.MeasurementOption + enqueueFailedInst metric.Int64Counter +} + +func newObsQueue[T internal.Request](set exporterqueue.Settings, delegate exporterqueue.Queue[T]) (exporterqueue.Queue[T], error) { + tb, err := metadata.NewTelemetryBuilder(set.ExporterSettings.TelemetrySettings) + if err != nil { + return nil, err + } + + exporterAttr := attribute.String(ExporterKey, set.ExporterSettings.ID.String()) + asyncAttr := metric.WithAttributeSet(attribute.NewSet(exporterAttr, attribute.String(DataTypeKey, set.Signal.String()))) + err = tb.RegisterExporterQueueSizeCallback(func(_ context.Context, o metric.Int64Observer) error { + o.Observe(delegate.Size(), asyncAttr) + return nil + }) + if err != nil { + return nil, err + } + + err = tb.RegisterExporterQueueCapacityCallback(func(_ context.Context, o metric.Int64Observer) error { + o.Observe(delegate.Capacity(), asyncAttr) + return nil + }) + if err != nil { + return nil, err + } + + or := &obsQueue[T]{ + Queue: delegate, + tb: tb, + metricAttr: metric.WithAttributeSet(attribute.NewSet(exporterAttr)), + } + + switch set.Signal { + case pipeline.SignalTraces: + or.enqueueFailedInst = tb.ExporterEnqueueFailedSpans + case pipeline.SignalMetrics: + or.enqueueFailedInst = tb.ExporterEnqueueFailedMetricPoints + case pipeline.SignalLogs: + or.enqueueFailedInst = tb.ExporterEnqueueFailedLogRecords + } + + return or, nil +} + +func (or *obsQueue[T]) Shutdown(ctx context.Context) error { + defer or.tb.Shutdown() + return or.Queue.Shutdown(ctx) +} + +func (or *obsQueue[T]) Offer(ctx context.Context, req T) error { + numItems := req.ItemsCount() + err := or.Queue.Offer(ctx, req) + // No metrics recorded for profiles, remove enqueueFailedInst check with nil when profiles metrics available. + if err != nil && or.enqueueFailedInst != nil { + or.enqueueFailedInst.Add(ctx, int64(numItems), or.metricAttr) + } + return err +} diff --git a/exporter/exporterhelper/internal/obs_queue_test.go b/exporter/exporterhelper/internal/obs_queue_test.go new file mode 100644 index 000000000000..5350c8192fa2 --- /dev/null +++ b/exporter/exporterhelper/internal/obs_queue_test.go @@ -0,0 +1,197 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package internal + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exporterhelper/internal/metadatatest" + "go.opentelemetry.io/collector/exporter/exporterqueue" + "go.opentelemetry.io/collector/exporter/internal" + "go.opentelemetry.io/collector/exporter/internal/requesttest" + "go.opentelemetry.io/collector/pipeline" +) + +type fakeQueue[T any] struct { + exporterqueue.Queue[T] + offerErr error + size int64 + capacity int64 +} + +func (fq *fakeQueue[T]) Size() int64 { + return fq.size +} + +func (fq *fakeQueue[T]) Capacity() int64 { + return fq.capacity +} + +func (fq *fakeQueue[T]) Offer(context.Context, T) error { + return fq.offerErr +} + +func newFakeQueue[T internal.Request](offerErr error, size, capacity int64) exporterqueue.Queue[T] { + return &fakeQueue[T]{offerErr: offerErr, size: size, capacity: capacity} +} + +func TestObsQueueLogsSizeCapacity(t *testing.T) { + tt := componenttest.NewTelemetry() + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + te, err := newObsQueue[internal.Request](exporterqueue.Settings{ + Signal: pipeline.SignalLogs, + ExporterSettings: exporter.Settings{ID: exporterID, TelemetrySettings: tt.NewTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }, newFakeQueue[internal.Request](nil, 7, 9)) + require.NoError(t, err) + require.NoError(t, te.Offer(context.Background(), &requesttest.FakeRequest{Items: 2})) + metadatatest.AssertEqualExporterQueueSize(t, tt, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String()), + attribute.String(DataTypeKey, pipeline.SignalLogs.String())), + Value: int64(7), + }, + }, metricdatatest.IgnoreTimestamp()) + metadatatest.AssertEqualExporterQueueCapacity(t, tt, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String()), + attribute.String(DataTypeKey, pipeline.SignalLogs.String())), + Value: int64(9), + }, + }, metricdatatest.IgnoreTimestamp()) +} + +func TestObsQueueLogsFailure(t *testing.T) { + tt := componenttest.NewTelemetry() + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + te, err := newObsQueue[internal.Request](exporterqueue.Settings{ + Signal: pipeline.SignalLogs, + ExporterSettings: exporter.Settings{ID: exporterID, TelemetrySettings: tt.NewTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }, newFakeQueue[internal.Request](errors.New("my error"), 7, 9)) + require.NoError(t, err) + require.Error(t, te.Offer(context.Background(), &requesttest.FakeRequest{Items: 2})) + metadatatest.AssertEqualExporterEnqueueFailedLogRecords(t, tt, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String())), + Value: int64(2), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) +} + +func TestObsQueueTracesSizeCapacity(t *testing.T) { + tt := componenttest.NewTelemetry() + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + te, err := newObsQueue[internal.Request](exporterqueue.Settings{ + Signal: pipeline.SignalTraces, + ExporterSettings: exporter.Settings{ID: exporterID, TelemetrySettings: tt.NewTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }, newFakeQueue[internal.Request](nil, 17, 19)) + require.NoError(t, err) + require.NoError(t, te.Offer(context.Background(), &requesttest.FakeRequest{Items: 12})) + metadatatest.AssertEqualExporterQueueSize(t, tt, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String()), + attribute.String(DataTypeKey, pipeline.SignalTraces.String())), + Value: int64(17), + }, + }, metricdatatest.IgnoreTimestamp()) + metadatatest.AssertEqualExporterQueueCapacity(t, tt, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String()), + attribute.String(DataTypeKey, pipeline.SignalTraces.String())), + Value: int64(19), + }, + }, metricdatatest.IgnoreTimestamp()) +} + +func TestObsQueueTracesFailure(t *testing.T) { + tt := componenttest.NewTelemetry() + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + te, err := newObsQueue[internal.Request](exporterqueue.Settings{ + Signal: pipeline.SignalTraces, + ExporterSettings: exporter.Settings{ID: exporterID, TelemetrySettings: tt.NewTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }, newFakeQueue[internal.Request](errors.New("my error"), 0, 0)) + require.NoError(t, err) + require.Error(t, te.Offer(context.Background(), &requesttest.FakeRequest{Items: 12})) + metadatatest.AssertEqualExporterEnqueueFailedSpans(t, tt, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String())), + Value: int64(12), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) +} + +func TestObsQueueMetrics(t *testing.T) { + tt := componenttest.NewTelemetry() + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + te, err := newObsQueue[internal.Request](exporterqueue.Settings{ + Signal: pipeline.SignalMetrics, + ExporterSettings: exporter.Settings{ID: exporterID, TelemetrySettings: tt.NewTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }, newFakeQueue[internal.Request](nil, 27, 29)) + require.NoError(t, err) + require.NoError(t, te.Offer(context.Background(), &requesttest.FakeRequest{Items: 22})) + metadatatest.AssertEqualExporterQueueSize(t, tt, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String()), + attribute.String(DataTypeKey, pipeline.SignalMetrics.String())), + Value: int64(27), + }, + }, metricdatatest.IgnoreTimestamp()) + metadatatest.AssertEqualExporterQueueCapacity(t, tt, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String()), + attribute.String(DataTypeKey, pipeline.SignalMetrics.String())), + Value: int64(29), + }, + }, metricdatatest.IgnoreTimestamp()) +} + +func TestObsQueueMetricsFailure(t *testing.T) { + tt := componenttest.NewTelemetry() + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + te, err := newObsQueue[internal.Request](exporterqueue.Settings{ + Signal: pipeline.SignalMetrics, + ExporterSettings: exporter.Settings{ID: exporterID, TelemetrySettings: tt.NewTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }, newFakeQueue[internal.Request](errors.New("my error"), 0, 0)) + require.NoError(t, err) + require.Error(t, te.Offer(context.Background(), &requesttest.FakeRequest{Items: 22})) + metadatatest.AssertEqualExporterEnqueueFailedMetricPoints(t, tt, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String())), + Value: int64(22), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) +} diff --git a/exporter/exporterhelper/internal/obs_report.go b/exporter/exporterhelper/internal/obs_report.go index e6cea1963b37..09c6fb391c54 100644 --- a/exporter/exporterhelper/internal/obs_report.go +++ b/exporter/exporterhelper/internal/obs_report.go @@ -36,14 +36,11 @@ const ( type ObsReport struct { spanName string tracer trace.Tracer - Signal pipeline.Signal - - spanAttrs trace.SpanStartEventOption - metricAttr metric.MeasurementOption - TelemetryBuilder *metadata.TelemetryBuilder - enqueueFailedInst metric.Int64Counter - itemsSentInst metric.Int64Counter - itemsFailedInst metric.Int64Counter + + spanAttrs trace.SpanStartEventOption + metricAttr metric.MeasurementOption + itemsSentInst metric.Int64Counter + itemsFailedInst metric.Int64Counter } // ObsReportSettings are settings for creating an ObsReport. @@ -62,29 +59,24 @@ func NewObsReport(set ObsReportSettings) (*ObsReport, error) { expAttr := attribute.String(ExporterKey, idStr) or := &ObsReport{ - spanName: ExporterKey + spanNameSep + idStr + spanNameSep + set.Signal.String(), - tracer: metadata.Tracer(set.ExporterSettings.TelemetrySettings), - Signal: set.Signal, - spanAttrs: trace.WithAttributes(expAttr, attribute.String(DataTypeKey, set.Signal.String())), - metricAttr: metric.WithAttributeSet(attribute.NewSet(expAttr)), - TelemetryBuilder: telemetryBuilder, + spanName: ExporterKey + spanNameSep + idStr + spanNameSep + set.Signal.String(), + tracer: metadata.Tracer(set.ExporterSettings.TelemetrySettings), + spanAttrs: trace.WithAttributes(expAttr, attribute.String(DataTypeKey, set.Signal.String())), + metricAttr: metric.WithAttributeSet(attribute.NewSet(expAttr)), } switch set.Signal { case pipeline.SignalTraces: - or.enqueueFailedInst = or.TelemetryBuilder.ExporterEnqueueFailedSpans - or.itemsSentInst = or.TelemetryBuilder.ExporterSentSpans - or.itemsFailedInst = or.TelemetryBuilder.ExporterSendFailedSpans + or.itemsSentInst = telemetryBuilder.ExporterSentSpans + or.itemsFailedInst = telemetryBuilder.ExporterSendFailedSpans case pipeline.SignalMetrics: - or.enqueueFailedInst = or.TelemetryBuilder.ExporterEnqueueFailedMetricPoints - or.itemsSentInst = or.TelemetryBuilder.ExporterSentMetricPoints - or.itemsFailedInst = or.TelemetryBuilder.ExporterSendFailedMetricPoints + or.itemsSentInst = telemetryBuilder.ExporterSentMetricPoints + or.itemsFailedInst = telemetryBuilder.ExporterSendFailedMetricPoints case pipeline.SignalLogs: - or.enqueueFailedInst = or.TelemetryBuilder.ExporterEnqueueFailedLogRecords - or.itemsSentInst = or.TelemetryBuilder.ExporterSentLogRecords - or.itemsFailedInst = or.TelemetryBuilder.ExporterSendFailedLogRecords + or.itemsSentInst = telemetryBuilder.ExporterSentLogRecords + or.itemsFailedInst = telemetryBuilder.ExporterSendFailedLogRecords } return or, nil @@ -130,12 +122,3 @@ func toNumItems(numExportedItems int, err error) (int64, int64) { } return int64(numExportedItems), 0 } - -func (or *ObsReport) RecordEnqueueFailure(ctx context.Context, failed int64) { - // No metrics recorded for profiles. - if or.enqueueFailedInst == nil { - return - } - - or.enqueueFailedInst.Add(ctx, failed, or.metricAttr) -} diff --git a/exporter/exporterhelper/internal/obs_report_sender.go b/exporter/exporterhelper/internal/obs_report_sender.go index e72e62d71285..d33a43e0e0da 100644 --- a/exporter/exporterhelper/internal/obs_report_sender.go +++ b/exporter/exporterhelper/internal/obs_report_sender.go @@ -6,23 +6,26 @@ package internal // import "go.opentelemetry.io/collector/exporter/exporterhelpe import ( "context" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/exporter/internal" ) type obsReportSender[K internal.Request] struct { - BaseSender[K] + component.StartFunc + component.ShutdownFunc obsrep *ObsReport + next Sender[K] } -func NewObsReportSender[K internal.Request](obsrep *ObsReport) Sender[K] { - return &obsReportSender[K]{obsrep: obsrep} +func NewObsReportSender[K internal.Request](obsrep *ObsReport, next Sender[K]) Sender[K] { + return &obsReportSender[K]{obsrep: obsrep, next: next} } func (ors *obsReportSender[K]) Send(ctx context.Context, req K) error { c := ors.obsrep.StartOp(ctx) items := req.ItemsCount() // Forward the data to the next consumer (this pusher is the next). - err := ors.NextSender.Send(c, req) + err := ors.next.Send(c, req) ors.obsrep.EndOp(c, items, err) return err } diff --git a/exporter/exporterhelper/internal/obs_report_test.go b/exporter/exporterhelper/internal/obs_report_test.go index f5ac73e3a89e..2264c6d0281f 100644 --- a/exporter/exporterhelper/internal/obs_report_test.go +++ b/exporter/exporterhelper/internal/obs_report_test.go @@ -12,10 +12,13 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exporterhelper/internal/metadatatest" "go.opentelemetry.io/collector/pipeline" ) @@ -72,7 +75,25 @@ func TestExportTraceDataOp(t *testing.T) { } } - require.NoError(t, tt.CheckExporterTraces(int64(sentSpans), int64(failedToSendSpans))) + metadatatest.AssertEqualExporterSentSpans(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String())), + Value: int64(sentSpans), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + + if failedToSendSpans > 0 { + metadatatest.AssertEqualExporterSendFailedSpans(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String())), + Value: int64(failedToSendSpans), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + } } func TestExportMetricsOp(t *testing.T) { @@ -123,7 +144,25 @@ func TestExportMetricsOp(t *testing.T) { } } - require.NoError(t, tt.CheckExporterMetrics(int64(sentMetricPoints), int64(failedToSendMetricPoints))) + metadatatest.AssertEqualExporterSentMetricPoints(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String())), + Value: int64(sentMetricPoints), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + + if failedToSendMetricPoints > 0 { + metadatatest.AssertEqualExporterSendFailedMetricPoints(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String())), + Value: int64(failedToSendMetricPoints), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + } } func TestExportLogsOp(t *testing.T) { @@ -174,37 +213,25 @@ func TestExportLogsOp(t *testing.T) { } } - require.NoError(t, tt.CheckExporterLogs(int64(sentLogRecords), int64(failedToSendLogRecords))) -} - -func TestExportEnqueueFailure(t *testing.T) { - tt, err := componenttest.SetupTelemetry(exporterID) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - obsrep, err := NewObsReport(ObsReportSettings{ - ExporterSettings: exporter.Settings{ID: exporterID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, - Signal: pipeline.SignalLogs, - }) - require.NoError(t, err) - obsrep.RecordEnqueueFailure(context.Background(), int64(7)) - require.NoError(t, tt.CheckExporterEnqueueFailedLogs(int64(7))) - - obsrep, err = NewObsReport(ObsReportSettings{ - ExporterSettings: exporter.Settings{ID: exporterID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, - Signal: pipeline.SignalTraces, - }) - require.NoError(t, err) - obsrep.RecordEnqueueFailure(context.Background(), int64(12)) - require.NoError(t, tt.CheckExporterEnqueueFailedTraces(int64(12))) - - obsrep, err = NewObsReport(ObsReportSettings{ - ExporterSettings: exporter.Settings{ID: exporterID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, - Signal: pipeline.SignalMetrics, - }) - require.NoError(t, err) - obsrep.RecordEnqueueFailure(context.Background(), int64(21)) - require.NoError(t, tt.CheckExporterEnqueueFailedMetrics(int64(21))) + metadatatest.AssertEqualExporterSentLogRecords(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String())), + Value: int64(sentLogRecords), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + + if failedToSendLogRecords > 0 { + metadatatest.AssertEqualExporterSendFailedLogRecords(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", exporterID.String())), + Value: int64(failedToSendLogRecords), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + } } type testParams struct { diff --git a/exporter/exporterhelper/internal/queue_sender.go b/exporter/exporterhelper/internal/queue_sender.go index 7e25364f3871..e2b125bbd444 100644 --- a/exporter/exporterhelper/internal/queue_sender.go +++ b/exporter/exporterhelper/internal/queue_sender.go @@ -7,13 +7,10 @@ import ( "context" "errors" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exporterbatcher" "go.opentelemetry.io/collector/exporter/exporterqueue" "go.opentelemetry.io/collector/exporter/internal" @@ -69,48 +66,50 @@ func (qCfg *QueueConfig) Validate() error { } type QueueSender struct { - BaseSender[internal.Request] - queue exporterqueue.Queue[internal.Request] - numConsumers int - batcher queue.Batcher - consumers *queue.Consumers[internal.Request] - - obsrep *ObsReport - exporterID component.ID - logger *zap.Logger - shutdownFns []component.ShutdownFunc + queue exporterqueue.Queue[internal.Request] + batcher component.Component } func NewQueueSender( - q exporterqueue.Queue[internal.Request], - set exporter.Settings, - numConsumers int, + qf exporterqueue.Factory[internal.Request], + qSet exporterqueue.Settings, + qCfg exporterqueue.Config, + bCfg exporterbatcher.Config, exportFailureMessage string, - obsrep *ObsReport, - batcherCfg exporterbatcher.Config, -) *QueueSender { - qs := &QueueSender{ - queue: q, - numConsumers: numConsumers, - obsrep: obsrep, - exporterID: set.ID, - logger: set.Logger, - } - + next Sender[internal.Request], +) (*QueueSender, error) { exportFunc := func(ctx context.Context, req internal.Request) error { - err := qs.NextSender.Send(ctx, req) + err := next.Send(ctx, req) if err != nil { - set.Logger.Error("Exporting failed. Dropping data."+exportFailureMessage, + qSet.ExporterSettings.Logger.Error("Exporting failed. Dropping data."+exportFailureMessage, zap.Error(err), zap.Int("dropped_items", req.ItemsCount())) } return err } - if usePullingBasedExporterQueueBatcher.IsEnabled() { - qs.batcher, _ = queue.NewBatcher(batcherCfg, q, exportFunc, numConsumers) - } else { - qs.consumers = queue.NewQueueConsumers[internal.Request](q, numConsumers, exportFunc) + if !usePullingBasedExporterQueueBatcher.IsEnabled() { + q, err := newObsQueue(qSet, qf(context.Background(), qSet, qCfg, func(ctx context.Context, req internal.Request, done exporterqueue.DoneCallback) { + done(exportFunc(ctx, req)) + })) + if err != nil { + return nil, err + } + return &QueueSender{queue: q}, nil + } + + b, err := queue.NewBatcher(bCfg, exportFunc, qCfg.NumConsumers) + if err != nil { + return nil, err } - return qs + // TODO: https://github.com/open-telemetry/opentelemetry-collector/issues/12244 + if bCfg.Enabled { + qCfg.NumConsumers = 1 + } + q, err := newObsQueue(qSet, qf(context.Background(), qSet, qCfg, b.Consume)) + if err != nil { + return nil, err + } + + return &QueueSender{queue: q, batcher: b}, nil } // Start is invoked during service startup. @@ -120,62 +119,24 @@ func (qs *QueueSender) Start(ctx context.Context, host component.Host) error { } if usePullingBasedExporterQueueBatcher.IsEnabled() { - if err := qs.batcher.Start(ctx, host); err != nil { - return err - } - } else { - if err := qs.consumers.Start(ctx, host); err != nil { - return err - } + return qs.batcher.Start(ctx, host) } - exporterAttr := attribute.String(ExporterKey, qs.exporterID.String()) - dataTypeAttr := attribute.String(DataTypeKey, qs.obsrep.Signal.String()) - - reg1, err1 := qs.obsrep.TelemetryBuilder.InitExporterQueueSize(func() int64 { return qs.queue.Size() }, - metric.WithAttributeSet(attribute.NewSet(exporterAttr, dataTypeAttr))) - - if reg1 != nil { - qs.shutdownFns = append(qs.shutdownFns, func(context.Context) error { - return reg1.Unregister() - }) - } - - reg2, err2 := qs.obsrep.TelemetryBuilder.InitExporterQueueCapacity(func() int64 { return qs.queue.Capacity() }, - metric.WithAttributeSet(attribute.NewSet(exporterAttr))) - - if reg2 != nil { - qs.shutdownFns = append(qs.shutdownFns, func(context.Context) error { - return reg2.Unregister() - }) - } - - return errors.Join(err1, err2) + return nil } // Shutdown is invoked during service shutdown. func (qs *QueueSender) Shutdown(ctx context.Context) error { - // Stop the queue and consumers, this will drain the queue and will call the retry (which is stopped) that will only + // Stop the queue and batcher, this will drain the queue and will call the retry (which is stopped) that will only // try once every request. - - for _, fn := range qs.shutdownFns { - err := fn(ctx) - if err != nil { - qs.logger.Warn("Error while shutting down QueueSender", zap.Error(err)) - } - } - qs.shutdownFns = nil - - if err := qs.queue.Shutdown(ctx); err != nil { - return err - } + err := qs.queue.Shutdown(ctx) if usePullingBasedExporterQueueBatcher.IsEnabled() { - return qs.batcher.Shutdown(ctx) + return errors.Join(err, qs.batcher.Shutdown(ctx)) } - return qs.consumers.Shutdown(ctx) + return err } -// send implements the requestSender interface. It puts the request in the queue. +// Send implements the requestSender interface. It puts the request in the queue. func (qs *QueueSender) Send(ctx context.Context, req internal.Request) error { // Prevent cancellation and deadline to propagate to the context stored in the queue. // The grpc/http based receivers will cancel the request context after this function returns. diff --git a/exporter/exporterhelper/internal/queue_sender_test.go b/exporter/exporterhelper/internal/queue_sender_test.go index 003b23bb0cb6..fae3d8256d8e 100644 --- a/exporter/exporterhelper/internal/queue_sender_test.go +++ b/exporter/exporterhelper/internal/queue_sender_test.go @@ -11,7 +11,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opentelemetry.io/otel/attribute" "go.uber.org/zap" "go.uber.org/zap/zaptest/observer" @@ -41,7 +40,7 @@ func TestQueuedRetry_StopWhileWaiting(t *testing.T) { ocs := be.ObsrepSender.(*observabilityConsumerSender) require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - firstMockR := newErrorRequest() + firstMockR := newErrorRequest(errors.New("transient error")) ocs.run(func() { // This is asynchronous so it should just enqueue, no errors expected. require.NoError(t, be.Send(context.Background(), firstMockR)) @@ -58,7 +57,7 @@ func TestQueuedRetry_StopWhileWaiting(t *testing.T) { require.NoError(t, be.Shutdown(context.Background())) - secondMockR.checkNumRequests(t, 1) + secondMockR.checkOneRequests(t) ocs.checkSendItemsCount(t, 3) ocs.checkDroppedItemsCount(t, 7) require.Zero(t, be.QueueSender.(*QueueSender).queue.Size()) @@ -95,7 +94,7 @@ func TestQueuedRetry_DoNotPreserveCancellation(t *testing.T) { }) ocs.awaitAsyncProcessing() - mockR.checkNumRequests(t, 1) + mockR.checkOneRequests(t) ocs.checkSendItemsCount(t, 2) ocs.checkDroppedItemsCount(t, 0) require.Zero(t, be.QueueSender.(*QueueSender).queue.Size()) @@ -229,7 +228,7 @@ func TestQueuedRetryHappyPath(t *testing.T) { require.Len(t, reqs, wantRequests) for _, req := range reqs { - req.checkNumRequests(t, 1) + req.checkOneRequests(t) } ocs.checkSendItemsCount(t, 2*wantRequests) @@ -242,45 +241,6 @@ func TestQueuedRetryHappyPath(t *testing.T) { } } -func TestQueuedRetry_QueueMetricsReported(t *testing.T) { - runTest := func(testName string, enableQueueBatcher bool) { - t.Run(testName, func(t *testing.T) { - defer setFeatureGateForTest(t, usePullingBasedExporterQueueBatcher, enableQueueBatcher)() - dataTypes := []pipeline.Signal{pipeline.SignalLogs, pipeline.SignalTraces, pipeline.SignalMetrics} - for _, dataType := range dataTypes { - tt, err := componenttest.SetupTelemetry(defaultID) - require.NoError(t, err) - - qCfg := NewDefaultQueueConfig() - qCfg.NumConsumers = -1 // to make QueueMetricsReportedvery request go straight to the queue - rCfg := configretry.NewDefaultBackOffConfig() - set := exporter.Settings{ID: defaultID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()} - be, err := NewBaseExporter(set, dataType, newObservabilityConsumerSender, - WithMarshaler(mockRequestMarshaler), WithUnmarshaler(mockRequestUnmarshaler(&mockRequest{})), - WithRetry(rCfg), WithQueue(qCfg)) - require.NoError(t, err) - require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - - require.NoError(t, tt.CheckExporterMetricGauge("otelcol_exporter_queue_capacity", int64(1000))) - - for i := 0; i < 7; i++ { - require.NoError(t, be.Send(context.Background(), newErrorRequest())) - } - require.NoError(t, tt.CheckExporterMetricGauge("otelcol_exporter_queue_size", int64(7), - attribute.String(DataTypeKey, dataType.String()))) - - assert.NoError(t, be.Shutdown(context.Background())) - // metrics should be unregistered at shutdown to prevent memory leak - require.Error(t, tt.CheckExporterMetricGauge("otelcol_exporter_queue_capacity", int64(1000))) - require.Error(t, tt.CheckExporterMetricGauge("otelcol_exporter_queue_size", int64(7), - attribute.String(DataTypeKey, dataType.String()))) - } - }) - } - runTest("enable_queue_batcher", true) - runTest("disable_queue_batcher", false) -} - func TestNoCancellationContext(t *testing.T) { runTest := func(testName string, enableQueueBatcher bool) { t.Run(testName, func(t *testing.T) { @@ -380,7 +340,7 @@ func TestQueueRetryWithDisabledQueue(t *testing.T) { assert.Len(t, observed.All(), 1) assert.Equal(t, "Exporting failed. Rejecting data. Try enabling sending_queue to survive temporary failures.", observed.All()[0].Message) ocs.awaitAsyncProcessing() - mockR.checkNumRequests(t, 1) + mockR.checkOneRequests(t) ocs.checkSendItemsCount(t, 0) ocs.checkDroppedItemsCount(t, 2) require.NoError(t, be.Shutdown(context.Background())) @@ -406,7 +366,7 @@ func TestQueueFailedRequestDropped(t *testing.T) { mockR := newMockRequest(2, errors.New("some error")) require.NoError(t, be.Send(context.Background(), mockR)) require.NoError(t, be.Shutdown(context.Background())) - mockR.checkNumRequests(t, 1) + mockR.checkOneRequests(t) assert.Len(t, observed.All(), 1) assert.Equal(t, "Exporting failed. Dropping data.", observed.All()[0].Message) }) @@ -494,7 +454,7 @@ func TestQueuedRetryPersistentEnabled_NoDataLossOnShutdown(t *testing.T) { rCfg.InitialInterval = time.Millisecond rCfg.MaxElapsedTime = 0 // retry infinitely so shutdown can be triggered - mockReq := newErrorRequest() + mockReq := newErrorRequest(errors.New("transient error")) be, err := NewBaseExporter(defaultSettings, defaultSignal, newNoopObsrepSender, WithMarshaler(mockRequestMarshaler), WithUnmarshaler(mockRequestUnmarshaler(mockReq)), WithRetry(rCfg), WithQueue(qCfg)) require.NoError(t, err) @@ -529,7 +489,7 @@ func TestQueuedRetryPersistentEnabled_NoDataLossOnShutdown(t *testing.T) { }) // wait for the item to be consumed from the queue - replacedReq.checkNumRequests(t, 1) + replacedReq.checkOneRequests(t) }) } runTest("enable_queue_batcher", true) @@ -542,19 +502,12 @@ func TestQueueSenderNoStartShutdown(t *testing.T) { defer setFeatureGateForTest(t, usePullingBasedExporterQueueBatcher, enableQueueBatcher)() set := exportertest.NewNopSettings() set.ID = exporterID - queue := exporterqueue.NewMemoryQueueFactory[internal.Request]()( - context.Background(), - exporterqueue.Settings{ - Signal: pipeline.SignalTraces, - ExporterSettings: set, - }, - exporterqueue.NewDefaultConfig()) - obsrep, err := NewObsReport(ObsReportSettings{ - ExporterSettings: set, + qSet := exporterqueue.Settings{ Signal: pipeline.SignalTraces, - }) + ExporterSettings: set, + } + qs, err := NewQueueSender(exporterqueue.NewMemoryQueueFactory[internal.Request](), qSet, exporterqueue.NewDefaultConfig(), exporterbatcher.NewDefaultConfig(), "", noopSender{}) require.NoError(t, err) - qs := NewQueueSender(queue, set, 1, "", obsrep, exporterbatcher.NewDefaultConfig()) assert.NoError(t, qs.Shutdown(context.Background())) }) } diff --git a/exporter/exporterhelper/internal/request.go b/exporter/exporterhelper/internal/request.go deleted file mode 100644 index b47ff63f0d55..000000000000 --- a/exporter/exporterhelper/internal/request.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package internal // import "go.opentelemetry.io/collector/exporter/exporterhelper/internal" - -import ( - "context" - - "go.opentelemetry.io/collector/exporter/internal" - "go.opentelemetry.io/collector/exporter/internal/requesttest" - "go.opentelemetry.io/collector/pdata/plog" - "go.opentelemetry.io/collector/pdata/pmetric" - "go.opentelemetry.io/collector/pdata/ptrace" -) - -func RequestFromMetricsFunc(reqErr error) func(context.Context, pmetric.Metrics) (internal.Request, error) { - return func(_ context.Context, md pmetric.Metrics) (internal.Request, error) { - return &requesttest.FakeRequest{Items: md.DataPointCount(), ExportErr: reqErr}, nil - } -} - -func RequestFromTracesFunc(reqErr error) func(context.Context, ptrace.Traces) (internal.Request, error) { - return func(_ context.Context, td ptrace.Traces) (internal.Request, error) { - return &requesttest.FakeRequest{Items: td.SpanCount(), ExportErr: reqErr}, nil - } -} - -func RequestFromLogsFunc(reqErr error) func(context.Context, plog.Logs) (internal.Request, error) { - return func(_ context.Context, ld plog.Logs) (internal.Request, error) { - return &requesttest.FakeRequest{Items: ld.LogRecordCount(), ExportErr: reqErr}, nil - } -} diff --git a/exporter/exporterhelper/internal/request_sender.go b/exporter/exporterhelper/internal/request_sender.go index 8ca75f66fb6b..5504da5c6381 100644 --- a/exporter/exporterhelper/internal/request_sender.go +++ b/exporter/exporterhelper/internal/request_sender.go @@ -7,27 +7,18 @@ import ( "context" // Sender is an abstraction of a sender for a request independent of the type of the data (traces, metrics, logs). "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/exporter/internal" ) type Sender[K any] interface { component.Component Send(context.Context, K) error - SetNextSender(nextSender Sender[K]) } -type BaseSender[K any] struct { - component.StartFunc - component.ShutdownFunc - NextSender Sender[K] -} - -var _ Sender[internal.Request] = (*BaseSender[internal.Request])(nil) - -func (b *BaseSender[K]) Send(ctx context.Context, req K) error { - return b.NextSender.Send(ctx, req) -} +type SendFunc[K any] func(context.Context, K) error -func (b *BaseSender[K]) SetNextSender(nextSender Sender[K]) { - b.NextSender = nextSender +func (f SendFunc[K]) Send(ctx context.Context, k K) error { + if f == nil { + return nil + } + return f(ctx, k) } diff --git a/exporter/exporterhelper/internal/retry_sender.go b/exporter/exporterhelper/internal/retry_sender.go index 0a81f12503fe..8a565bf051b5 100644 --- a/exporter/exporterhelper/internal/retry_sender.go +++ b/exporter/exporterhelper/internal/retry_sender.go @@ -14,6 +14,7 @@ import ( "go.opentelemetry.io/otel/trace" "go.uber.org/zap" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/exporter" @@ -44,17 +45,19 @@ func NewThrottleRetry(err error, delay time.Duration) error { } type retrySender struct { - BaseSender[internal.Request] + component.StartFunc cfg configretry.BackOffConfig stopCh chan struct{} logger *zap.Logger + next Sender[internal.Request] } -func newRetrySender(config configretry.BackOffConfig, set exporter.Settings) *retrySender { +func newRetrySender(config configretry.BackOffConfig, set exporter.Settings, next Sender[internal.Request]) *retrySender { return &retrySender{ cfg: config, stopCh: make(chan struct{}), logger: set.Logger, + next: next, } } @@ -84,7 +87,7 @@ func (rs *retrySender) Send(ctx context.Context, req internal.Request) error { "Sending request.", trace.WithAttributes(attribute.Int64("retry_num", retryNum))) - err := rs.NextSender.Send(ctx, req) + err := rs.next.Send(ctx, req) if err == nil { return nil } @@ -130,7 +133,7 @@ func (rs *retrySender) Send(ctx context.Context, req internal.Request) error { // back-off, but get interrupted when shutting down or request is cancelled or timed out. select { case <-ctx.Done(): - return fmt.Errorf("request is cancelled or timed out %w", err) + return fmt.Errorf("request is cancelled or timed out: %w", err) case <-rs.stopCh: return experr.NewShutdownErr(err) case <-time.After(backoffDelay): diff --git a/exporter/exporterhelper/internal/retry_sender_test.go b/exporter/exporterhelper/internal/retry_sender_test.go index e6b5ae94ce23..3264af9764dc 100644 --- a/exporter/exporterhelper/internal/retry_sender_test.go +++ b/exporter/exporterhelper/internal/retry_sender_test.go @@ -6,6 +6,7 @@ package internal import ( "context" "errors" + "fmt" "sync" "sync/atomic" "testing" @@ -16,6 +17,7 @@ import ( "go.uber.org/zap" "go.uber.org/zap/zaptest/observer" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/consumer/consumererror" @@ -23,8 +25,7 @@ import ( "go.opentelemetry.io/collector/exporter/exporterqueue" "go.opentelemetry.io/collector/exporter/exportertest" "go.opentelemetry.io/collector/exporter/internal" - "go.opentelemetry.io/collector/pdata/testdata" - "go.opentelemetry.io/collector/pipeline" + "go.opentelemetry.io/collector/exporter/internal/requesttest" ) func mockRequestUnmarshaler(mr internal.Request) exporterqueue.Unmarshaler[internal.Request] { @@ -37,377 +38,126 @@ func mockRequestMarshaler(internal.Request) ([]byte, error) { return []byte("mockRequest"), nil } -func TestQueuedRetry_DropOnPermanentError(t *testing.T) { - runTest := func(testName string, enableQueueBatcher bool) { - t.Run(testName, func(t *testing.T) { - resetFeatureGate := setFeatureGateForTest(t, usePullingBasedExporterQueueBatcher, enableQueueBatcher) - qCfg := NewDefaultQueueConfig() - rCfg := configretry.NewDefaultBackOffConfig() - mockR := newMockRequest(2, consumererror.NewPermanent(errors.New("bad data"))) - be, err := NewBaseExporter(defaultSettings, defaultSignal, newObservabilityConsumerSender, - WithMarshaler(mockRequestMarshaler), WithUnmarshaler(mockRequestUnmarshaler(mockR)), WithRetry(rCfg), WithQueue(qCfg)) - require.NoError(t, err) - ocs := be.ObsrepSender.(*observabilityConsumerSender) - require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - t.Cleanup(func() { - assert.NoError(t, be.Shutdown(context.Background())) - resetFeatureGate() - }) - - ocs.run(func() { - // This is asynchronous so it should just enqueue, no errors expected. - require.NoError(t, be.Send(context.Background(), mockR)) - }) - ocs.awaitAsyncProcessing() - // In the newMockConcurrentExporter we count requests and items even for failed requests - mockR.checkNumRequests(t, 1) - ocs.checkSendItemsCount(t, 0) - ocs.checkDroppedItemsCount(t, 2) - }) - } - runTest("enable_queue_batcher", true) - runTest("disable_queue_batcher", false) -} - -func TestQueuedRetry_DropOnNoRetry(t *testing.T) { - runTest := func(testName string, enableQueueBatcher bool) { - t.Run(testName, func(t *testing.T) { - resetFeatureGate := setFeatureGateForTest(t, usePullingBasedExporterQueueBatcher, enableQueueBatcher) - qCfg := NewDefaultQueueConfig() - rCfg := configretry.NewDefaultBackOffConfig() - rCfg.Enabled = false - be, err := NewBaseExporter(defaultSettings, defaultSignal, newObservabilityConsumerSender, WithMarshaler(mockRequestMarshaler), - WithUnmarshaler(mockRequestUnmarshaler(newMockRequest(2, errors.New("transient error")))), - WithQueue(qCfg), WithRetry(rCfg)) - require.NoError(t, err) - ocs := be.ObsrepSender.(*observabilityConsumerSender) - require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - t.Cleanup(func() { - assert.NoError(t, be.Shutdown(context.Background())) - resetFeatureGate() - }) - - mockR := newMockRequest(2, errors.New("transient error")) - ocs.run(func() { - // This is asynchronous so it should just enqueue, no errors expected. - require.NoError(t, be.Send(context.Background(), mockR)) - }) - ocs.awaitAsyncProcessing() - // In the newMockConcurrentExporter we count requests and items even for failed requests - mockR.checkNumRequests(t, 1) - ocs.checkSendItemsCount(t, 0) - ocs.checkDroppedItemsCount(t, 2) - }) - } - runTest("enable_queue_batcher", true) - runTest("disable_queue_batcher", false) -} - -func TestQueuedRetry_OnError(t *testing.T) { - runTest := func(testName string, enableQueueBatcher bool) { - t.Run(testName, func(t *testing.T) { - resetFeatureGate := setFeatureGateForTest(t, usePullingBasedExporterQueueBatcher, enableQueueBatcher) - qCfg := NewDefaultQueueConfig() - qCfg.NumConsumers = 1 - rCfg := configretry.NewDefaultBackOffConfig() - rCfg.InitialInterval = 0 - be, err := NewBaseExporter(defaultSettings, defaultSignal, newObservabilityConsumerSender, - WithMarshaler(mockRequestMarshaler), WithUnmarshaler(mockRequestUnmarshaler(&mockRequest{})), - WithRetry(rCfg), WithQueue(qCfg)) - require.NoError(t, err) - require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - t.Cleanup(func() { - assert.NoError(t, be.Shutdown(context.Background())) - resetFeatureGate() - }) - - traceErr := consumererror.NewTraces(errors.New("some error"), testdata.GenerateTraces(1)) - mockR := newMockRequest(2, traceErr) - ocs := be.ObsrepSender.(*observabilityConsumerSender) - ocs.run(func() { - // This is asynchronous so it should just enqueue, no errors expected. - require.NoError(t, be.Send(context.Background(), mockR)) - }) - ocs.awaitAsyncProcessing() - - // In the newMockConcurrentExporter we count requests and items even for failed requests - mockR.checkNumRequests(t, 2) - ocs.checkSendItemsCount(t, 2) - ocs.checkDroppedItemsCount(t, 0) - }) - } - runTest("enable_queue_batcher", true) - runTest("disable_queue_batcher", false) -} - -func TestQueuedRetry_MaxElapsedTime(t *testing.T) { - runTest := func(testName string, enableQueueBatcher bool) { - t.Run(testName, func(t *testing.T) { - resetFeatureGate := setFeatureGateForTest(t, usePullingBasedExporterQueueBatcher, enableQueueBatcher) - qCfg := NewDefaultQueueConfig() - qCfg.NumConsumers = 1 - rCfg := configretry.NewDefaultBackOffConfig() - rCfg.InitialInterval = time.Millisecond - rCfg.MaxElapsedTime = 100 * time.Millisecond - be, err := NewBaseExporter(defaultSettings, defaultSignal, newObservabilityConsumerSender, - WithMarshaler(mockRequestMarshaler), WithUnmarshaler(mockRequestUnmarshaler(&mockRequest{})), - WithRetry(rCfg), WithQueue(qCfg)) - require.NoError(t, err) - ocs := be.ObsrepSender.(*observabilityConsumerSender) - require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - t.Cleanup(func() { - assert.NoError(t, be.Shutdown(context.Background())) - resetFeatureGate() - }) - - ocs.run(func() { - // Add an item that will always fail. - require.NoError(t, be.Send(context.Background(), newErrorRequest())) - }) - - mockR := newMockRequest(2, nil) - start := time.Now() - ocs.run(func() { - // This is asynchronous so it should just enqueue, no errors expected. - require.NoError(t, be.Send(context.Background(), mockR)) - }) - ocs.awaitAsyncProcessing() - - // We should ensure that we wait for more than 50ms but less than 150ms (50% less and 50% more than max elapsed). - waitingTime := time.Since(start) - assert.Less(t, 50*time.Millisecond, waitingTime) - assert.Less(t, waitingTime, 150*time.Millisecond) - - // In the newMockConcurrentExporter we count requests and items even for failed requests. - mockR.checkNumRequests(t, 1) - ocs.checkSendItemsCount(t, 2) - ocs.checkDroppedItemsCount(t, 7) - require.Zero(t, be.QueueSender.(*QueueSender).queue.Size()) - }) - } - runTest("enable_queue_batcher", true) - runTest("disable_queue_batcher", false) -} - -type wrappedError struct { - error -} - -func (e wrappedError) Unwrap() error { - return e.error -} - -func TestQueuedRetry_ThrottleError(t *testing.T) { - runTest := func(testName string, enableQueueBatcher bool) { - t.Run(testName, func(t *testing.T) { - resetFeatureGate := setFeatureGateForTest(t, usePullingBasedExporterQueueBatcher, enableQueueBatcher) - qCfg := NewDefaultQueueConfig() - qCfg.NumConsumers = 1 - rCfg := configretry.NewDefaultBackOffConfig() - rCfg.InitialInterval = 10 * time.Millisecond - be, err := NewBaseExporter(defaultSettings, defaultSignal, newObservabilityConsumerSender, - WithMarshaler(mockRequestMarshaler), WithUnmarshaler(mockRequestUnmarshaler(&mockRequest{})), - WithRetry(rCfg), WithQueue(qCfg)) - require.NoError(t, err) - ocs := be.ObsrepSender.(*observabilityConsumerSender) - require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - t.Cleanup(func() { - assert.NoError(t, be.Shutdown(context.Background())) - resetFeatureGate() - }) - - retry := NewThrottleRetry(errors.New("throttle error"), 100*time.Millisecond) - mockR := newMockRequest(2, wrappedError{retry}) - start := time.Now() - ocs.run(func() { - // This is asynchronous so it should just enqueue, no errors expected. - require.NoError(t, be.Send(context.Background(), mockR)) - }) - ocs.awaitAsyncProcessing() - - // The initial backoff is 10ms, but because of the throttle this should wait at least 100ms. - assert.Less(t, 100*time.Millisecond, time.Since(start)) - - mockR.checkNumRequests(t, 2) - ocs.checkSendItemsCount(t, 2) - ocs.checkDroppedItemsCount(t, 0) - require.Zero(t, be.QueueSender.(*QueueSender).queue.Size()) - }) - } - runTest("enable_queue_batcher", true) - runTest("disable_queue_batcher", false) -} - -func TestQueuedRetry_RetryOnError(t *testing.T) { - runTest := func(testName string, enableQueueBatcher bool) { - t.Run(testName, func(t *testing.T) { - resetFeatureGate := setFeatureGateForTest(t, usePullingBasedExporterQueueBatcher, enableQueueBatcher) - qCfg := NewDefaultQueueConfig() - qCfg.NumConsumers = 1 - qCfg.QueueSize = 1 - rCfg := configretry.NewDefaultBackOffConfig() - rCfg.InitialInterval = 0 - be, err := NewBaseExporter(defaultSettings, defaultSignal, newObservabilityConsumerSender, - WithMarshaler(mockRequestMarshaler), WithUnmarshaler(mockRequestUnmarshaler(&mockRequest{})), - WithRetry(rCfg), WithQueue(qCfg)) - require.NoError(t, err) - ocs := be.ObsrepSender.(*observabilityConsumerSender) - require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - t.Cleanup(func() { - assert.NoError(t, be.Shutdown(context.Background())) - resetFeatureGate() - }) - - mockR := newMockRequest(2, errors.New("transient error")) - ocs.run(func() { - // This is asynchronous so it should just enqueue, no errors expected. - require.NoError(t, be.Send(context.Background(), mockR)) - }) - ocs.awaitAsyncProcessing() - - // In the newMockConcurrentExporter we count requests and items even for failed requests - mockR.checkNumRequests(t, 2) - ocs.checkSendItemsCount(t, 2) - ocs.checkDroppedItemsCount(t, 0) - require.Zero(t, be.QueueSender.(*QueueSender).queue.Size()) - }) - } - runTest("enable_queue_batcher", true) - runTest("disable_queue_batcher", false) -} - -func TestQueueRetryWithNoQueue(t *testing.T) { - runTest := func(testName string, enableQueueBatcher bool) { - t.Run(testName, func(t *testing.T) { - defer setFeatureGateForTest(t, usePullingBasedExporterQueueBatcher, enableQueueBatcher)() - rCfg := configretry.NewDefaultBackOffConfig() - rCfg.MaxElapsedTime = time.Nanosecond // fail fast - be, err := NewBaseExporter(exportertest.NewNopSettings(), pipeline.SignalLogs, newObservabilityConsumerSender, WithRetry(rCfg)) - require.NoError(t, err) - require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - ocs := be.ObsrepSender.(*observabilityConsumerSender) - mockR := newMockRequest(2, errors.New("some error")) - ocs.run(func() { - require.Error(t, be.Send(context.Background(), mockR)) - }) - ocs.awaitAsyncProcessing() - mockR.checkNumRequests(t, 1) - ocs.checkSendItemsCount(t, 0) - ocs.checkDroppedItemsCount(t, 2) - require.NoError(t, be.Shutdown(context.Background())) - }) - } - runTest("enable_queue_batcher", true) - runTest("disable_queue_batcher", false) -} - -func TestQueueRetryWithDisabledRetires(t *testing.T) { - runTest := func(testName string, enableQueueBatcher bool) { - t.Run(testName, func(t *testing.T) { - defer setFeatureGateForTest(t, usePullingBasedExporterQueueBatcher, enableQueueBatcher)() - rCfg := configretry.NewDefaultBackOffConfig() - rCfg.Enabled = false - set := exportertest.NewNopSettings() - logger, observed := observer.New(zap.ErrorLevel) - set.Logger = zap.New(logger) - be, err := NewBaseExporter(set, pipeline.SignalLogs, newObservabilityConsumerSender, WithRetry(rCfg)) - require.NoError(t, err) - require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - ocs := be.ObsrepSender.(*observabilityConsumerSender) - mockR := newMockRequest(2, errors.New("some error")) - ocs.run(func() { - require.Error(t, be.Send(context.Background(), mockR)) - }) - assert.Len(t, observed.All(), 1) - assert.Equal(t, "Exporting failed. Rejecting data. "+ - "Try enabling retry_on_failure config option to retry on retryable errors.", observed.All()[0].Message) - ocs.awaitAsyncProcessing() - mockR.checkNumRequests(t, 1) - ocs.checkSendItemsCount(t, 0) - ocs.checkDroppedItemsCount(t, 2) - require.NoError(t, be.Shutdown(context.Background())) - }) - } - runTest("enable_queue_batcher", true) - runTest("disable_queue_batcher", false) -} - -func TestRetryWithContextTimeout(t *testing.T) { - runTest := func(testName string, enableQueueBatcher bool) { - t.Run(testName, func(t *testing.T) { - defer setFeatureGateForTest(t, usePullingBasedExporterQueueBatcher, enableQueueBatcher)() - const testTimeout = 10 * time.Second - - rCfg := configretry.NewDefaultBackOffConfig() - rCfg.Enabled = true - - // First attempt after 100ms is attempted - rCfg.InitialInterval = 100 * time.Millisecond - rCfg.RandomizationFactor = 0 - // Second attempt is at twice the testTimeout - rCfg.Multiplier = float64(2 * testTimeout / rCfg.InitialInterval) - qCfg := exporterqueue.NewDefaultConfig() - qCfg.Enabled = false - set := exportertest.NewNopSettings() - logger, observed := observer.New(zap.InfoLevel) - set.Logger = zap.New(logger) - be, err := NewBaseExporter( - set, - pipeline.SignalLogs, - newObservabilityConsumerSender, - WithRetry(rCfg), - WithRequestQueue(qCfg, exporterqueue.NewMemoryQueueFactory[internal.Request]()), - ) - require.NoError(t, err) - require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - ocs := be.ObsrepSender.(*observabilityConsumerSender) - mockR := newErrorRequest() - - start := time.Now() - ocs.run(func() { - ctx, cancel := context.WithTimeout(context.Background(), testTimeout) - defer cancel() - err := be.Send(ctx, mockR) - require.Error(t, err) - require.Equal(t, "request will be cancelled before next retry: transient error", err.Error()) - }) - assert.Len(t, observed.All(), 2) - assert.Equal(t, "Exporting failed. Will retry the request after interval.", observed.All()[0].Message) - assert.Equal(t, "Exporting failed. Rejecting data. "+ - "Try enabling sending_queue to survive temporary failures.", observed.All()[1].Message) - ocs.awaitAsyncProcessing() - ocs.checkDroppedItemsCount(t, 7) - require.Equal(t, 2, mockR.(*mockErrorRequest).getNumRequests()) - require.NoError(t, be.Shutdown(context.Background())) - - // There should be no delay, because the initial interval is - // longer than the context timeout. Merely checking that no - // delays on the order of either the context timeout or the - // retry interval were introduced, i.e., fail fast. - elapsed := time.Since(start) - require.Less(t, elapsed, testTimeout/2) - }) - } - runTest("enable_queue_batcher", true) - runTest("disable_queue_batcher", false) +func TestRetrySenderDropOnPermanentError(t *testing.T) { + rCfg := configretry.NewDefaultBackOffConfig() + sink := requesttest.NewSink() + expErr := consumererror.NewPermanent(errors.New("bad data")) + rs := newRetrySender(rCfg, exportertest.NewNopSettings(), newNoopExportSender()) + require.NoError(t, rs.Start(context.Background(), componenttest.NewNopHost())) + require.ErrorIs(t, rs.Send(context.Background(), &requesttest.FakeRequest{Items: 2, Sink: sink, ExportErr: expErr}), expErr) + require.ErrorIs(t, rs.Send(context.Background(), &requesttest.FakeRequest{Items: 3, Sink: sink, ExportErr: expErr}), expErr) + assert.Equal(t, int64(0), sink.ItemsCount()) + assert.Equal(t, int64(0), sink.RequestsCount()) + require.NoError(t, rs.Shutdown(context.Background())) +} + +func TestRetrySenderSimpleRetry(t *testing.T) { + rCfg := configretry.NewDefaultBackOffConfig() + rCfg.InitialInterval = 0 + sink := requesttest.NewSink() + expErr := errors.New("transient error") + rs := newRetrySender(rCfg, exportertest.NewNopSettings(), newNoopExportSender()) + require.NoError(t, rs.Start(context.Background(), componenttest.NewNopHost())) + require.NoError(t, rs.Send(context.Background(), &requesttest.FakeRequest{Items: 2, Sink: sink, ExportErr: expErr})) + assert.Equal(t, int64(2), sink.ItemsCount()) + assert.Equal(t, int64(1), sink.RequestsCount()) + require.NoError(t, rs.Shutdown(context.Background())) +} + +func TestRetrySenderRetryPartial(t *testing.T) { + rCfg := configretry.NewDefaultBackOffConfig() + rCfg.InitialInterval = 0 + sink := requesttest.NewSink() + rs := newRetrySender(rCfg, exportertest.NewNopSettings(), newNoopExportSender()) + require.NoError(t, rs.Start(context.Background(), componenttest.NewNopHost())) + require.NoError(t, rs.Send(context.Background(), &requesttest.FakeRequest{Items: 5, Sink: sink, Partial: 3})) + assert.Equal(t, int64(5), sink.ItemsCount()) + assert.Equal(t, int64(2), sink.RequestsCount()) + require.NoError(t, rs.Shutdown(context.Background())) +} + +func TestRetrySenderMaxElapsedTime(t *testing.T) { + rCfg := configretry.NewDefaultBackOffConfig() + rCfg.InitialInterval = time.Millisecond + rCfg.MaxElapsedTime = 100 * time.Millisecond + sink := requesttest.NewSink() + rs := newRetrySender(rCfg, exportertest.NewNopSettings(), newNoopExportSender()) + require.NoError(t, rs.Start(context.Background(), componenttest.NewNopHost())) + expErr := errors.New("transient error") + require.ErrorIs(t, rs.Send(context.Background(), newErrorRequest(expErr)), expErr) + assert.Equal(t, int64(0), sink.ItemsCount()) + assert.Equal(t, int64(0), sink.RequestsCount()) + require.NoError(t, rs.Shutdown(context.Background())) +} + +func TestRetrySenderThrottleError(t *testing.T) { + rCfg := configretry.NewDefaultBackOffConfig() + rCfg.InitialInterval = 10 * time.Millisecond + sink := requesttest.NewSink() + rs := newRetrySender(rCfg, exportertest.NewNopSettings(), newNoopExportSender()) + require.NoError(t, rs.Start(context.Background(), componenttest.NewNopHost())) + retry := fmt.Errorf("wrappe error: %w", NewThrottleRetry(errors.New("throttle error"), 100*time.Millisecond)) + start := time.Now() + require.NoError(t, rs.Send(context.Background(), &requesttest.FakeRequest{Items: 5, Sink: sink, ExportErr: retry})) + // The initial backoff is 10ms, but because of the throttle this should wait at least 100ms. + assert.Less(t, 100*time.Millisecond, time.Since(start)) + assert.Equal(t, int64(5), sink.ItemsCount()) + assert.Equal(t, int64(1), sink.RequestsCount()) + require.NoError(t, rs.Shutdown(context.Background())) +} + +func TestRetrySenderWithContextTimeout(t *testing.T) { + const testTimeout = 10 * time.Second + rCfg := configretry.NewDefaultBackOffConfig() + rCfg.Enabled = true + // First attempt after 100ms is attempted + rCfg.InitialInterval = 100 * time.Millisecond + rCfg.RandomizationFactor = 0 + // Second attempt is at twice the testTimeout + rCfg.Multiplier = float64(2 * testTimeout / rCfg.InitialInterval) + set := exportertest.NewNopSettings() + logger, observed := observer.New(zap.InfoLevel) + set.Logger = zap.New(logger) + rs := newRetrySender(rCfg, set, newNoopExportSender()) + require.NoError(t, rs.Start(context.Background(), componenttest.NewNopHost())) + start := time.Now() + ctx, cancel := context.WithTimeout(context.Background(), testTimeout) + defer cancel() + require.ErrorContains(t, + rs.Send(ctx, newErrorRequest(errors.New("transient error"))), + "request will be cancelled before next retry: transient error") + assert.Len(t, observed.All(), 1) + assert.Equal(t, "Exporting failed. Will retry the request after interval.", observed.All()[0].Message) + require.Less(t, time.Since(start), testTimeout/2) + require.NoError(t, rs.Shutdown(context.Background())) +} + +func TestRetrySenderWithCancelledContext(t *testing.T) { + rCfg := configretry.NewDefaultBackOffConfig() + rCfg.Enabled = true + // First attempt after 1s is attempted + rCfg.InitialInterval = 1 * time.Second + rs := newRetrySender(rCfg, exportertest.NewNopSettings(), newNoopExportSender()) + require.NoError(t, rs.Start(context.Background(), componenttest.NewNopHost())) + start := time.Now() + ctx, cancel := context.WithCancelCause(context.Background()) + go func() { + <-time.After(100 * time.Millisecond) + cancel(errors.New("my reason")) + }() + require.ErrorContains(t, + rs.Send(ctx, newErrorRequest(errors.New("transient error"))), + "request is cancelled or timed out: transient error") + require.Less(t, time.Since(start), 1*time.Second) + require.NoError(t, rs.Shutdown(context.Background())) } type mockErrorRequest struct { - mu sync.Mutex - requests int + err error } func (mer *mockErrorRequest) Export(context.Context) error { - mer.mu.Lock() - defer mer.mu.Unlock() - mer.requests++ - return errors.New("transient error") -} - -func (mer *mockErrorRequest) getNumRequests() int { - mer.mu.Lock() - defer mer.mu.Unlock() - return mer.requests + return mer.err } func (mer *mockErrorRequest) OnError(error) internal.Request { @@ -426,8 +176,8 @@ func (mer *mockErrorRequest) MergeSplit(context.Context, exporterbatcher.MaxSize return nil, nil } -func newErrorRequest() internal.Request { - return &mockErrorRequest{} +func newErrorRequest(err error) internal.Request { + return &mockErrorRequest{err: err} } type mockRequest struct { @@ -458,9 +208,9 @@ func (m *mockRequest) OnError(error) internal.Request { } } -func (m *mockRequest) checkNumRequests(t *testing.T, want int) { +func (m *mockRequest) checkOneRequests(t *testing.T) { assert.Eventually(t, func() bool { - return int64(want) == m.requestCount.Load() + return int64(1) == m.requestCount.Load() }, time.Second, 1*time.Millisecond) } @@ -485,22 +235,25 @@ func newMockRequest(cnt int, consumeError error) *mockRequest { } type observabilityConsumerSender struct { - BaseSender[internal.Request] + component.StartFunc + component.ShutdownFunc waitGroup *sync.WaitGroup sentItemsCount *atomic.Int64 droppedItemsCount *atomic.Int64 + next Sender[internal.Request] } -func newObservabilityConsumerSender(*ObsReport) Sender[internal.Request] { +func newObservabilityConsumerSender(_ *ObsReport, next Sender[internal.Request]) Sender[internal.Request] { return &observabilityConsumerSender{ waitGroup: new(sync.WaitGroup), droppedItemsCount: &atomic.Int64{}, sentItemsCount: &atomic.Int64{}, + next: next, } } func (ocs *observabilityConsumerSender) Send(ctx context.Context, req internal.Request) error { - err := ocs.NextSender.Send(ctx, req) + err := ocs.next.Send(ctx, req) if err != nil { ocs.droppedItemsCount.Add(int64(req.ItemsCount())) } else { diff --git a/exporter/exporterhelper/internal/timeout_sender.go b/exporter/exporterhelper/internal/timeout_sender.go index a47ddccfb8c2..31da1840effd 100644 --- a/exporter/exporterhelper/internal/timeout_sender.go +++ b/exporter/exporterhelper/internal/timeout_sender.go @@ -8,6 +8,7 @@ import ( "errors" "time" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/exporter/internal" ) @@ -35,7 +36,8 @@ func NewDefaultTimeoutConfig() TimeoutConfig { // TimeoutSender is a requestSender that adds a `timeout` to every request that passes this sender. type TimeoutSender struct { - BaseSender[internal.Request] + component.StartFunc + component.ShutdownFunc cfg TimeoutConfig } diff --git a/exporter/exporterhelper/logs.go b/exporter/exporterhelper/logs.go index a2726d874f08..c29ed1945041 100644 --- a/exporter/exporterhelper/logs.go +++ b/exporter/exporterhelper/logs.go @@ -143,11 +143,7 @@ func NewLogsRequest( zap.Error(err)) return consumererror.NewPermanent(cErr) } - sErr := be.Send(ctx, req) - if errors.Is(sErr, exporterqueue.ErrQueueIsFull) { - be.Obsrep.RecordEnqueueFailure(ctx, int64(req.ItemsCount())) - } - return sErr + return be.Send(ctx, req) }, be.ConsumerOptions...) return &logsExporter{ diff --git a/exporter/exporterhelper/logs_batch_test.go b/exporter/exporterhelper/logs_batch_test.go index 10caf1b5dcd3..d7b21292fd06 100644 --- a/exporter/exporterhelper/logs_batch_test.go +++ b/exporter/exporterhelper/logs_batch_test.go @@ -157,9 +157,9 @@ func BenchmarkSplittingBasedOnItemCountManySmallLogs(b *testing.B) { // All requests merge into a single batch. cfg := exporterbatcher.MaxSizeConfig{MaxSizeItems: 10000} for i := 0; i < b.N; i++ { - merged := []Request{&logsRequest{ld: testdata.GenerateLogs(10)}} + merged := []Request{newLogsRequest(testdata.GenerateLogs(10), nil)} for j := 0; j < 1000; j++ { - lr2 := &logsRequest{ld: testdata.GenerateLogs(10)} + lr2 := newLogsRequest(testdata.GenerateLogs(10), nil) res, _ := merged[len(merged)-1].MergeSplit(context.Background(), cfg, lr2) merged = append(merged[0:len(merged)-1], res...) } @@ -171,9 +171,9 @@ func BenchmarkSplittingBasedOnItemCountManyLogsSlightlyAboveLimit(b *testing.B) // Every incoming request results in a split. cfg := exporterbatcher.MaxSizeConfig{MaxSizeItems: 10000} for i := 0; i < b.N; i++ { - merged := []Request{&logsRequest{ld: testdata.GenerateLogs(0)}} + merged := []Request{newLogsRequest(testdata.GenerateLogs(0), nil)} for j := 0; j < 10; j++ { - lr2 := &logsRequest{ld: testdata.GenerateLogs(10001)} + lr2 := newLogsRequest(testdata.GenerateLogs(10001), nil) res, _ := merged[len(merged)-1].MergeSplit(context.Background(), cfg, lr2) merged = append(merged[0:len(merged)-1], res...) } @@ -185,8 +185,8 @@ func BenchmarkSplittingBasedOnItemCountHugeLogs(b *testing.B) { // One request splits into many batches. cfg := exporterbatcher.MaxSizeConfig{MaxSizeItems: 10000} for i := 0; i < b.N; i++ { - merged := []Request{&logsRequest{ld: testdata.GenerateLogs(0)}} - lr2 := &logsRequest{ld: testdata.GenerateLogs(100000)} + merged := []Request{newLogsRequest(testdata.GenerateLogs(0), nil)} + lr2 := newLogsRequest(testdata.GenerateLogs(100000), nil) res, _ := merged[len(merged)-1].MergeSplit(context.Background(), cfg, lr2) merged = append(merged[0:len(merged)-1], res...) assert.Len(b, merged, 10) diff --git a/exporter/exporterhelper/logs_test.go b/exporter/exporterhelper/logs_test.go index 5c23a53002e8..94587defeb3a 100644 --- a/exporter/exporterhelper/logs_test.go +++ b/exporter/exporterhelper/logs_test.go @@ -13,6 +13,8 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/sdk/trace/tracetest" "go.opentelemetry.io/otel/trace" @@ -26,7 +28,9 @@ import ( "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exporterhelper/internal" + "go.opentelemetry.io/collector/exporter/exporterhelper/internal/metadatatest" "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/exporter/internal/requesttest" "go.opentelemetry.io/collector/exporter/internal/storagetest" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/testdata" @@ -67,7 +71,7 @@ func TestLogs_NilLogger(t *testing.T) { } func TestLogsRequest_NilLogger(t *testing.T) { - le, err := NewLogsRequest(context.Background(), exporter.Settings{}, internal.RequestFromLogsFunc(nil)) + le, err := NewLogsRequest(context.Background(), exporter.Settings{}, requesttest.RequestFromLogsFunc(nil)) require.Nil(t, le) require.Equal(t, errNilLogger, err) } @@ -99,7 +103,7 @@ func TestLogs_Default(t *testing.T) { func TestLogsRequest_Default(t *testing.T) { ld := plog.NewLogs() le, err := NewLogsRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromLogsFunc(nil)) + requesttest.RequestFromLogsFunc(nil)) assert.NotNil(t, le) require.NoError(t, err) @@ -121,7 +125,7 @@ func TestLogs_WithCapabilities(t *testing.T) { func TestLogsRequest_WithCapabilities(t *testing.T) { capabilities := consumer.Capabilities{MutatesData: true} le, err := NewLogsRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromLogsFunc(nil), WithCapabilities(capabilities)) + requesttest.RequestFromLogsFunc(nil), WithCapabilities(capabilities)) require.NoError(t, err) require.NotNil(t, le) @@ -153,7 +157,7 @@ func TestLogsRequest_Default_ExportError(t *testing.T) { ld := plog.NewLogs() want := errors.New("export_error") le, err := NewLogsRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromLogsFunc(want)) + requesttest.RequestFromLogsFunc(want)) require.NoError(t, err) require.NotNil(t, le) require.Equal(t, want, le.ConsumeLogs(context.Background(), ld)) @@ -192,7 +196,7 @@ func TestLogs_WithRecordMetrics(t *testing.T) { require.NoError(t, err) require.NotNil(t, le) - checkRecordedMetricsForLogs(t, tt, le, nil) + checkRecordedMetricsForLogs(t, tt, fakeLogsName, le, nil) } func TestLogs_pLogModifiedDownStream_WithRecordMetrics(t *testing.T) { @@ -207,7 +211,15 @@ func TestLogs_pLogModifiedDownStream_WithRecordMetrics(t *testing.T) { require.NoError(t, le.ConsumeLogs(context.Background(), ld)) assert.Equal(t, 0, ld.LogRecordCount()) - require.NoError(t, tt.CheckExporterLogs(int64(2), 0)) + + metadatatest.AssertEqualExporterSentLogRecords(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", fakeLogsName.String())), + Value: int64(2), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) } func TestLogsRequest_WithRecordMetrics(t *testing.T) { @@ -217,11 +229,11 @@ func TestLogsRequest_WithRecordMetrics(t *testing.T) { le, err := NewLogsRequest(context.Background(), exporter.Settings{ID: fakeLogsName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, - internal.RequestFromLogsFunc(nil)) + requesttest.RequestFromLogsFunc(nil)) require.NoError(t, err) require.NotNil(t, le) - checkRecordedMetricsForLogs(t, tt, le, nil) + checkRecordedMetricsForLogs(t, tt, fakeLogsName, le, nil) } func TestLogs_WithRecordMetrics_ReturnError(t *testing.T) { @@ -234,7 +246,7 @@ func TestLogs_WithRecordMetrics_ReturnError(t *testing.T) { require.NoError(t, err) require.NotNil(t, le) - checkRecordedMetricsForLogs(t, tt, le, want) + checkRecordedMetricsForLogs(t, tt, fakeLogsName, le, want) } func TestLogsRequest_WithRecordMetrics_ExportError(t *testing.T) { @@ -244,36 +256,11 @@ func TestLogsRequest_WithRecordMetrics_ExportError(t *testing.T) { t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) le, err := NewLogsRequest(context.Background(), exporter.Settings{ID: fakeLogsName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, - internal.RequestFromLogsFunc(want)) + requesttest.RequestFromLogsFunc(want)) require.NoError(t, err) require.NotNil(t, le) - checkRecordedMetricsForLogs(t, tt, le, want) -} - -func TestLogs_WithRecordEnqueueFailedMetrics(t *testing.T) { - tt, err := componenttest.SetupTelemetry(fakeLogsName) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - rCfg := configretry.NewDefaultBackOffConfig() - qCfg := NewDefaultQueueConfig() - qCfg.NumConsumers = 1 - qCfg.QueueSize = 2 - wantErr := errors.New("some-error") - te, err := NewLogs(context.Background(), exporter.Settings{ID: fakeLogsName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, &fakeLogsConfig, newPushLogsData(wantErr), WithRetry(rCfg), WithQueue(qCfg)) - require.NoError(t, err) - require.NotNil(t, te) - - md := testdata.GenerateLogs(3) - const numBatches = 7 - for i := 0; i < numBatches; i++ { - // errors are checked in the checkEnqueueFailedLogsStats function below. - _ = te.ConsumeLogs(context.Background(), md) - } - - // 2 batched must be in queue, and 5 batches (15 log records) rejected due to queue overflow - require.NoError(t, tt.CheckExporterEnqueueFailedLogs(int64(15))) + checkRecordedMetricsForLogs(t, tt, fakeLogsName, le, want) } func TestLogs_WithSpan(t *testing.T) { @@ -296,7 +283,7 @@ func TestLogsRequest_WithSpan(t *testing.T) { otel.SetTracerProvider(set.TracerProvider) defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) - le, err := NewLogsRequest(context.Background(), set, internal.RequestFromLogsFunc(nil)) + le, err := NewLogsRequest(context.Background(), set, requesttest.RequestFromLogsFunc(nil)) require.NoError(t, err) require.NotNil(t, le) checkWrapSpanForLogs(t, sr, set.TracerProvider.Tracer("test"), le, nil) @@ -324,7 +311,7 @@ func TestLogsRequest_WithSpan_ReturnError(t *testing.T) { defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) want := errors.New("my_error") - le, err := NewLogsRequest(context.Background(), set, internal.RequestFromLogsFunc(want)) + le, err := NewLogsRequest(context.Background(), set, requesttest.RequestFromLogsFunc(want)) require.NoError(t, err) require.NotNil(t, le) checkWrapSpanForLogs(t, sr, set.TracerProvider.Tracer("test"), le, want) @@ -347,7 +334,7 @@ func TestLogsRequest_WithShutdown(t *testing.T) { shutdown := func(context.Context) error { shutdownCalled = true; return nil } le, err := NewLogsRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromLogsFunc(nil), WithShutdown(shutdown)) + requesttest.RequestFromLogsFunc(nil), WithShutdown(shutdown)) assert.NotNil(t, le) assert.NoError(t, err) @@ -371,7 +358,7 @@ func TestLogsRequest_WithShutdown_ReturnError(t *testing.T) { shutdownErr := func(context.Context) error { return want } le, err := NewLogsRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromLogsFunc(nil), WithShutdown(shutdownErr)) + requesttest.RequestFromLogsFunc(nil), WithShutdown(shutdownErr)) assert.NotNil(t, le) require.NoError(t, err) @@ -391,7 +378,7 @@ func newPushLogsData(retError error) consumer.ConsumeLogsFunc { } } -func checkRecordedMetricsForLogs(t *testing.T, tt componenttest.TestTelemetry, le exporter.Logs, wantError error) { +func checkRecordedMetricsForLogs(t *testing.T, tt componenttest.TestTelemetry, id component.ID, le exporter.Logs, wantError error) { ld := testdata.GenerateLogs(2) const numBatches = 7 for i := 0; i < numBatches; i++ { @@ -400,9 +387,23 @@ func checkRecordedMetricsForLogs(t *testing.T, tt componenttest.TestTelemetry, l // TODO: When the new metrics correctly count partial dropped fix this. if wantError != nil { - require.NoError(t, tt.CheckExporterLogs(0, int64(numBatches*ld.LogRecordCount()))) + metadatatest.AssertEqualExporterSendFailedLogRecords(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", id.String())), + Value: int64(numBatches * ld.LogRecordCount()), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) } else { - require.NoError(t, tt.CheckExporterLogs(int64(numBatches*ld.LogRecordCount()), 0)) + metadatatest.AssertEqualExporterSentLogRecords(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("exporter", id.String())), + Value: int64(numBatches * ld.LogRecordCount()), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) } } diff --git a/exporter/exporterhelper/metadata.yaml b/exporter/exporterhelper/metadata.yaml index 9ce34e0306aa..fc6a372a15ef 100644 --- a/exporter/exporterhelper/metadata.yaml +++ b/exporter/exporterhelper/metadata.yaml @@ -2,8 +2,7 @@ type: exporterhelper github_project: open-telemetry/opentelemetry-collector status: - class: exporter - not_component: true + class: pkg stability: beta: [traces, metrics, logs] @@ -105,7 +104,6 @@ telemetry: level: alpha description: Current size of the retry queue (in batches) unit: "{batches}" - optional: true gauge: value_type: int async: true @@ -116,7 +114,6 @@ telemetry: level: alpha description: Fixed capacity of the retry queue (in batches) unit: "{batches}" - optional: true gauge: value_type: int async: true diff --git a/exporter/exporterhelper/metrics.go b/exporter/exporterhelper/metrics.go index d95f2f62fc40..af7b356bc49f 100644 --- a/exporter/exporterhelper/metrics.go +++ b/exporter/exporterhelper/metrics.go @@ -143,11 +143,7 @@ func NewMetricsRequest( zap.Error(err)) return consumererror.NewPermanent(cErr) } - sErr := be.Send(ctx, req) - if errors.Is(sErr, exporterqueue.ErrQueueIsFull) { - be.Obsrep.RecordEnqueueFailure(ctx, int64(req.ItemsCount())) - } - return sErr + return be.Send(ctx, req) }, be.ConsumerOptions...) return &metricsExporter{ diff --git a/exporter/exporterhelper/metrics_batch_test.go b/exporter/exporterhelper/metrics_batch_test.go index ebe89ca25be6..090b504c3c7e 100644 --- a/exporter/exporterhelper/metrics_batch_test.go +++ b/exporter/exporterhelper/metrics_batch_test.go @@ -165,9 +165,9 @@ func BenchmarkSplittingBasedOnItemCountManySmallMetrics(b *testing.B) { // All requests merge into a single batch. cfg := exporterbatcher.MaxSizeConfig{MaxSizeItems: 20000} for i := 0; i < b.N; i++ { - merged := []Request{&metricsRequest{md: testdata.GenerateMetrics(10)}} + merged := []Request{newMetricsRequest(testdata.GenerateMetrics(10), nil)} for j := 0; j < 1000; j++ { - lr2 := &metricsRequest{md: testdata.GenerateMetrics(10)} + lr2 := newMetricsRequest(testdata.GenerateMetrics(10), nil) res, _ := merged[len(merged)-1].MergeSplit(context.Background(), cfg, lr2) merged = append(merged[0:len(merged)-1], res...) } @@ -179,9 +179,9 @@ func BenchmarkSplittingBasedOnItemCountManyMetricsSlightlyAboveLimit(b *testing. // Every incoming request results in a split. cfg := exporterbatcher.MaxSizeConfig{MaxSizeItems: 20000} for i := 0; i < b.N; i++ { - merged := []Request{&metricsRequest{md: testdata.GenerateMetrics(0)}} + merged := []Request{newMetricsRequest(testdata.GenerateMetrics(0), nil)} for j := 0; j < 10; j++ { - lr2 := &metricsRequest{md: testdata.GenerateMetrics(10001)} + lr2 := newMetricsRequest(testdata.GenerateMetrics(10001), nil) res, _ := merged[len(merged)-1].MergeSplit(context.Background(), cfg, lr2) merged = append(merged[0:len(merged)-1], res...) } @@ -193,8 +193,8 @@ func BenchmarkSplittingBasedOnItemCountHugeMetrics(b *testing.B) { // One request splits into many batches. cfg := exporterbatcher.MaxSizeConfig{MaxSizeItems: 20000} for i := 0; i < b.N; i++ { - merged := []Request{&metricsRequest{md: testdata.GenerateMetrics(0)}} - lr2 := &metricsRequest{md: testdata.GenerateMetrics(100000)} + merged := []Request{newMetricsRequest(testdata.GenerateMetrics(0), nil)} + lr2 := newMetricsRequest(testdata.GenerateMetrics(100000), nil) res, _ := merged[len(merged)-1].MergeSplit(context.Background(), cfg, lr2) merged = append(merged[0:len(merged)-1], res...) assert.Len(b, merged, 10) diff --git a/exporter/exporterhelper/metrics_test.go b/exporter/exporterhelper/metrics_test.go index 7f2066dc49c0..098d17846ea9 100644 --- a/exporter/exporterhelper/metrics_test.go +++ b/exporter/exporterhelper/metrics_test.go @@ -13,6 +13,8 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/sdk/trace/tracetest" "go.opentelemetry.io/otel/trace" @@ -26,7 +28,9 @@ import ( "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exporterhelper/internal" + "go.opentelemetry.io/collector/exporter/exporterhelper/internal/metadatatest" "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/exporter/internal/requesttest" "go.opentelemetry.io/collector/exporter/internal/storagetest" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/testdata" @@ -68,7 +72,7 @@ func TestMetrics_NilLogger(t *testing.T) { func TestMetricsRequest_NilLogger(t *testing.T) { me, err := NewMetricsRequest(context.Background(), exporter.Settings{}, - internal.RequestFromMetricsFunc(nil)) + requesttest.RequestFromMetricsFunc(nil)) require.Nil(t, me) require.Equal(t, errNilLogger, err) } @@ -100,7 +104,7 @@ func TestMetrics_Default(t *testing.T) { func TestMetricsRequest_Default(t *testing.T) { md := pmetric.NewMetrics() me, err := NewMetricsRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromMetricsFunc(nil)) + requesttest.RequestFromMetricsFunc(nil)) require.NoError(t, err) assert.NotNil(t, me) @@ -122,7 +126,7 @@ func TestMetrics_WithCapabilities(t *testing.T) { func TestMetricsRequest_WithCapabilities(t *testing.T) { capabilities := consumer.Capabilities{MutatesData: true} me, err := NewMetricsRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromMetricsFunc(nil), WithCapabilities(capabilities)) + requesttest.RequestFromMetricsFunc(nil), WithCapabilities(capabilities)) require.NoError(t, err) assert.NotNil(t, me) @@ -154,7 +158,7 @@ func TestMetricsRequest_Default_ExportError(t *testing.T) { md := pmetric.NewMetrics() want := errors.New("export_error") me, err := NewMetricsRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromMetricsFunc(want)) + requesttest.RequestFromMetricsFunc(want)) require.NoError(t, err) require.NotNil(t, me) require.Equal(t, want, me.ConsumeMetrics(context.Background(), md)) @@ -193,7 +197,7 @@ func TestMetrics_WithRecordMetrics(t *testing.T) { require.NoError(t, err) require.NotNil(t, me) - checkRecordedMetricsForMetrics(t, tt, me, nil) + checkRecordedMetricsForMetrics(t, tt, fakeMetricsName, me, nil) } func TestMetrics_pMetricModifiedDownStream_WithRecordMetrics(t *testing.T) { @@ -208,7 +212,15 @@ func TestMetrics_pMetricModifiedDownStream_WithRecordMetrics(t *testing.T) { require.NoError(t, me.ConsumeMetrics(context.Background(), md)) assert.Equal(t, 0, md.MetricCount()) - require.NoError(t, tt.CheckExporterMetrics(int64(4), 0)) + + metadatatest.AssertEqualExporterSentMetricPoints(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String(internal.ExporterKey, fakeMetricsName.String())), + Value: int64(4), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) } func TestMetricsRequest_WithRecordMetrics(t *testing.T) { @@ -218,11 +230,11 @@ func TestMetricsRequest_WithRecordMetrics(t *testing.T) { me, err := NewMetricsRequest(context.Background(), exporter.Settings{ID: fakeMetricsName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, - internal.RequestFromMetricsFunc(nil)) + requesttest.RequestFromMetricsFunc(nil)) require.NoError(t, err) require.NotNil(t, me) - checkRecordedMetricsForMetrics(t, tt, me, nil) + checkRecordedMetricsForMetrics(t, tt, fakeMetricsName, me, nil) } func TestMetrics_WithRecordMetrics_ReturnError(t *testing.T) { @@ -235,7 +247,7 @@ func TestMetrics_WithRecordMetrics_ReturnError(t *testing.T) { require.NoError(t, err) require.NotNil(t, me) - checkRecordedMetricsForMetrics(t, tt, me, want) + checkRecordedMetricsForMetrics(t, tt, fakeMetricsName, me, want) } func TestMetricsRequest_WithRecordMetrics_ExportError(t *testing.T) { @@ -246,36 +258,11 @@ func TestMetricsRequest_WithRecordMetrics_ExportError(t *testing.T) { me, err := NewMetricsRequest(context.Background(), exporter.Settings{ID: fakeMetricsName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, - internal.RequestFromMetricsFunc(want)) + requesttest.RequestFromMetricsFunc(want)) require.NoError(t, err) require.NotNil(t, me) - checkRecordedMetricsForMetrics(t, tt, me, want) -} - -func TestMetrics_WithRecordEnqueueFailedMetrics(t *testing.T) { - tt, err := componenttest.SetupTelemetry(fakeMetricsName) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - rCfg := configretry.NewDefaultBackOffConfig() - qCfg := NewDefaultQueueConfig() - qCfg.NumConsumers = 1 - qCfg.QueueSize = 2 - wantErr := errors.New("some-error") - te, err := NewMetrics(context.Background(), exporter.Settings{ID: fakeMetricsName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, &fakeMetricsConfig, newPushMetricsData(wantErr), WithRetry(rCfg), WithQueue(qCfg)) - require.NoError(t, err) - require.NotNil(t, te) - - md := testdata.GenerateMetrics(1) - const numBatches = 7 - for i := 0; i < numBatches; i++ { - // errors are checked in the checkExporterEnqueueFailedMetricsStats function below. - _ = te.ConsumeMetrics(context.Background(), md) - } - - // 2 batched must be in queue, and 10 metric points rejected due to queue overflow - require.NoError(t, tt.CheckExporterEnqueueFailedMetrics(int64(10))) + checkRecordedMetricsForMetrics(t, tt, fakeMetricsName, me, want) } func TestMetrics_WithSpan(t *testing.T) { @@ -298,7 +285,7 @@ func TestMetricsRequest_WithSpan(t *testing.T) { otel.SetTracerProvider(set.TracerProvider) defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) - me, err := NewMetricsRequest(context.Background(), set, internal.RequestFromMetricsFunc(nil)) + me, err := NewMetricsRequest(context.Background(), set, requesttest.RequestFromMetricsFunc(nil)) require.NoError(t, err) require.NotNil(t, me) checkWrapSpanForMetrics(t, sr, set.TracerProvider.Tracer("test"), me, nil) @@ -326,7 +313,7 @@ func TestMetricsRequest_WithSpan_ExportError(t *testing.T) { defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) want := errors.New("my_error") - me, err := NewMetricsRequest(context.Background(), set, internal.RequestFromMetricsFunc(want)) + me, err := NewMetricsRequest(context.Background(), set, requesttest.RequestFromMetricsFunc(want)) require.NoError(t, err) require.NotNil(t, me) checkWrapSpanForMetrics(t, sr, set.TracerProvider.Tracer("test"), me, want) @@ -350,7 +337,7 @@ func TestMetricsRequest_WithShutdown(t *testing.T) { shutdown := func(context.Context) error { shutdownCalled = true; return nil } me, err := NewMetricsRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromMetricsFunc(nil), WithShutdown(shutdown)) + requesttest.RequestFromMetricsFunc(nil), WithShutdown(shutdown)) assert.NotNil(t, me) assert.NoError(t, err) @@ -376,7 +363,7 @@ func TestMetricsRequest_WithShutdown_ReturnError(t *testing.T) { shutdownErr := func(context.Context) error { return want } me, err := NewMetricsRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromMetricsFunc(nil), WithShutdown(shutdownErr)) + requesttest.RequestFromMetricsFunc(nil), WithShutdown(shutdownErr)) assert.NotNil(t, me) assert.NoError(t, err) @@ -397,7 +384,7 @@ func newPushMetricsDataModifiedDownstream(retError error) consumer.ConsumeMetric } } -func checkRecordedMetricsForMetrics(t *testing.T, tt componenttest.TestTelemetry, me exporter.Metrics, wantError error) { +func checkRecordedMetricsForMetrics(t *testing.T, tt componenttest.TestTelemetry, id component.ID, me exporter.Metrics, wantError error) { md := testdata.GenerateMetrics(2) const numBatches = 7 for i := 0; i < numBatches; i++ { @@ -407,9 +394,23 @@ func checkRecordedMetricsForMetrics(t *testing.T, tt componenttest.TestTelemetry // TODO: When the new metrics correctly count partial dropped fix this. numPoints := int64(numBatches * md.MetricCount() * 2) /* 2 points per metric*/ if wantError != nil { - require.NoError(t, tt.CheckExporterMetrics(0, numPoints)) + metadatatest.AssertEqualExporterSendFailedMetricPoints(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String(internal.ExporterKey, id.String())), + Value: numPoints, + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) } else { - require.NoError(t, tt.CheckExporterMetrics(numPoints, 0)) + metadatatest.AssertEqualExporterSentMetricPoints(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String(internal.ExporterKey, id.String())), + Value: numPoints, + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) } } diff --git a/exporter/exporterhelper/traces.go b/exporter/exporterhelper/traces.go index 2f49c8a07c80..cb19ff665a23 100644 --- a/exporter/exporterhelper/traces.go +++ b/exporter/exporterhelper/traces.go @@ -143,11 +143,7 @@ func NewTracesRequest( zap.Error(err)) return consumererror.NewPermanent(cErr) } - sErr := be.Send(ctx, req) - if errors.Is(sErr, exporterqueue.ErrQueueIsFull) { - be.Obsrep.RecordEnqueueFailure(ctx, int64(req.ItemsCount())) - } - return sErr + return be.Send(ctx, req) }, be.ConsumerOptions...) return &tracesExporter{ diff --git a/exporter/exporterhelper/traces_batch_test.go b/exporter/exporterhelper/traces_batch_test.go index a578f977160e..122b0bb5e60b 100644 --- a/exporter/exporterhelper/traces_batch_test.go +++ b/exporter/exporterhelper/traces_batch_test.go @@ -163,10 +163,11 @@ func TestExtractTraces(t *testing.T) { func BenchmarkSplittingBasedOnItemCountManySmallTraces(b *testing.B) { // All requests merge into a single batch. cfg := exporterbatcher.MaxSizeConfig{MaxSizeItems: 10000} + b.ReportAllocs() for i := 0; i < b.N; i++ { - merged := []Request{&tracesRequest{td: testdata.GenerateTraces(10)}} + merged := []Request{newTracesRequest(testdata.GenerateTraces(10), nil)} for j := 0; j < 1000; j++ { - lr2 := &tracesRequest{td: testdata.GenerateTraces(10)} + lr2 := newTracesRequest(testdata.GenerateTraces(10), nil) res, _ := merged[len(merged)-1].MergeSplit(context.Background(), cfg, lr2) merged = append(merged[0:len(merged)-1], res...) } @@ -177,10 +178,11 @@ func BenchmarkSplittingBasedOnItemCountManySmallTraces(b *testing.B) { func BenchmarkSplittingBasedOnItemCountManyTracesSlightlyAboveLimit(b *testing.B) { // Every incoming request results in a split. cfg := exporterbatcher.MaxSizeConfig{MaxSizeItems: 10000} + b.ReportAllocs() for i := 0; i < b.N; i++ { - merged := []Request{&tracesRequest{td: testdata.GenerateTraces(0)}} + merged := []Request{newTracesRequest(testdata.GenerateTraces(0), nil)} for j := 0; j < 10; j++ { - lr2 := &tracesRequest{td: testdata.GenerateTraces(10001)} + lr2 := newTracesRequest(testdata.GenerateTraces(10001), nil) res, _ := merged[len(merged)-1].MergeSplit(context.Background(), cfg, lr2) merged = append(merged[0:len(merged)-1], res...) } @@ -192,8 +194,8 @@ func BenchmarkSplittingBasedOnItemCountHugeTraces(b *testing.B) { // One request splits into many batches. cfg := exporterbatcher.MaxSizeConfig{MaxSizeItems: 10000} for i := 0; i < b.N; i++ { - merged := []Request{&tracesRequest{td: testdata.GenerateTraces(0)}} - lr2 := &tracesRequest{td: testdata.GenerateTraces(100000)} + merged := []Request{newTracesRequest(testdata.GenerateTraces(0), nil)} + lr2 := newTracesRequest(testdata.GenerateTraces(100000), nil) res, _ := merged[len(merged)-1].MergeSplit(context.Background(), cfg, lr2) merged = append(merged[0:len(merged)-1], res...) assert.Len(b, merged, 10) diff --git a/exporter/exporterhelper/traces_test.go b/exporter/exporterhelper/traces_test.go index 8312815c2312..2641b14e9501 100644 --- a/exporter/exporterhelper/traces_test.go +++ b/exporter/exporterhelper/traces_test.go @@ -13,6 +13,8 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/sdk/trace/tracetest" "go.opentelemetry.io/otel/trace" @@ -26,7 +28,9 @@ import ( "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exporterhelper/internal" + "go.opentelemetry.io/collector/exporter/exporterhelper/internal/metadatatest" "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/exporter/internal/requesttest" "go.opentelemetry.io/collector/exporter/internal/storagetest" "go.opentelemetry.io/collector/pdata/ptrace" "go.opentelemetry.io/collector/pdata/testdata" @@ -63,7 +67,7 @@ func TestTraces_NilLogger(t *testing.T) { } func TestTracesRequest_NilLogger(t *testing.T) { - te, err := NewTracesRequest(context.Background(), exporter.Settings{}, internal.RequestFromTracesFunc(nil)) + te, err := NewTracesRequest(context.Background(), exporter.Settings{}, requesttest.RequestFromTracesFunc(nil)) require.Nil(t, te) require.Equal(t, errNilLogger, err) } @@ -95,7 +99,7 @@ func TestTraces_Default(t *testing.T) { func TestTracesRequest_Default(t *testing.T) { td := ptrace.NewTraces() te, err := NewTracesRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromTracesFunc(nil)) + requesttest.RequestFromTracesFunc(nil)) assert.NotNil(t, te) require.NoError(t, err) @@ -117,7 +121,7 @@ func TestTraces_WithCapabilities(t *testing.T) { func TestTracesRequest_WithCapabilities(t *testing.T) { capabilities := consumer.Capabilities{MutatesData: true} te, err := NewTracesRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromTracesFunc(nil), WithCapabilities(capabilities)) + requesttest.RequestFromTracesFunc(nil), WithCapabilities(capabilities)) assert.NotNil(t, te) require.NoError(t, err) @@ -151,7 +155,7 @@ func TestTracesRequest_Default_ExportError(t *testing.T) { td := ptrace.NewTraces() want := errors.New("export_error") te, err := NewTracesRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromTracesFunc(want)) + requesttest.RequestFromTracesFunc(want)) require.NoError(t, err) require.NotNil(t, te) require.Equal(t, want, te.ConsumeTraces(context.Background(), td)) @@ -190,7 +194,7 @@ func TestTraces_WithRecordMetrics(t *testing.T) { require.NoError(t, err) require.NotNil(t, te) - checkRecordedMetricsForTraces(t, tt, te, nil) + checkRecordedMetricsForTraces(t, tt, fakeTracesName, te, nil) } func TestTraces_pLogModifiedDownStream_WithRecordMetrics(t *testing.T) { @@ -205,7 +209,15 @@ func TestTraces_pLogModifiedDownStream_WithRecordMetrics(t *testing.T) { require.NoError(t, te.ConsumeTraces(context.Background(), td)) assert.Equal(t, 0, td.SpanCount()) - require.NoError(t, tt.CheckExporterTraces(int64(2), 0)) + + metadatatest.AssertEqualExporterSentSpans(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String(internal.ExporterKey, fakeTracesName.String())), + Value: int64(2), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) } func TestTracesRequest_WithRecordMetrics(t *testing.T) { @@ -215,11 +227,11 @@ func TestTracesRequest_WithRecordMetrics(t *testing.T) { te, err := NewTracesRequest(context.Background(), exporter.Settings{ID: fakeTracesName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, - internal.RequestFromTracesFunc(nil)) + requesttest.RequestFromTracesFunc(nil)) require.NoError(t, err) require.NotNil(t, te) - checkRecordedMetricsForTraces(t, tt, te, nil) + checkRecordedMetricsForTraces(t, tt, fakeTracesName, te, nil) } func TestTraces_WithRecordMetrics_ReturnError(t *testing.T) { @@ -232,7 +244,7 @@ func TestTraces_WithRecordMetrics_ReturnError(t *testing.T) { require.NoError(t, err) require.NotNil(t, te) - checkRecordedMetricsForTraces(t, tt, te, want) + checkRecordedMetricsForTraces(t, tt, fakeTracesName, te, want) } func TestTracesRequest_WithRecordMetrics_RequestSenderError(t *testing.T) { @@ -243,36 +255,11 @@ func TestTracesRequest_WithRecordMetrics_RequestSenderError(t *testing.T) { te, err := NewTracesRequest(context.Background(), exporter.Settings{ID: fakeTracesName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, - internal.RequestFromTracesFunc(want)) + requesttest.RequestFromTracesFunc(want)) require.NoError(t, err) require.NotNil(t, te) - checkRecordedMetricsForTraces(t, tt, te, want) -} - -func TestTraces_WithRecordEnqueueFailedMetrics(t *testing.T) { - tt, err := componenttest.SetupTelemetry(fakeTracesName) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - rCfg := configretry.NewDefaultBackOffConfig() - qCfg := NewDefaultQueueConfig() - qCfg.NumConsumers = 1 - qCfg.QueueSize = 2 - wantErr := errors.New("some-error") - te, err := NewTraces(context.Background(), exporter.Settings{ID: fakeTracesName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, &fakeTracesConfig, newTraceDataPusher(wantErr), WithRetry(rCfg), WithQueue(qCfg)) - require.NoError(t, err) - require.NotNil(t, te) - - td := testdata.GenerateTraces(2) - const numBatches = 7 - for i := 0; i < numBatches; i++ { - // errors are checked in the checkEnqueueFailedTracesStats function below. - _ = te.ConsumeTraces(context.Background(), td) - } - - // 2 batched must be in queue, and 5 batches (10 spans) rejected due to queue overflow - require.NoError(t, tt.CheckExporterEnqueueFailedTraces(int64(10))) + checkRecordedMetricsForTraces(t, tt, fakeTracesName, te, want) } func TestTraces_WithSpan(t *testing.T) { @@ -296,7 +283,7 @@ func TestTracesRequest_WithSpan(t *testing.T) { otel.SetTracerProvider(set.TracerProvider) defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) - te, err := NewTracesRequest(context.Background(), set, internal.RequestFromTracesFunc(nil)) + te, err := NewTracesRequest(context.Background(), set, requesttest.RequestFromTracesFunc(nil)) require.NoError(t, err) require.NotNil(t, te) @@ -326,7 +313,7 @@ func TestTracesRequest_WithSpan_ExportError(t *testing.T) { defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) want := errors.New("export_error") - te, err := NewTracesRequest(context.Background(), set, internal.RequestFromTracesFunc(want)) + te, err := NewTracesRequest(context.Background(), set, requesttest.RequestFromTracesFunc(want)) require.NoError(t, err) require.NotNil(t, te) @@ -351,7 +338,7 @@ func TestTracesRequest_WithShutdown(t *testing.T) { shutdown := func(context.Context) error { shutdownCalled = true; return nil } te, err := NewTracesRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromTracesFunc(nil), WithShutdown(shutdown)) + requesttest.RequestFromTracesFunc(nil), WithShutdown(shutdown)) assert.NotNil(t, te) assert.NoError(t, err) @@ -377,7 +364,7 @@ func TestTracesRequest_WithShutdown_ReturnError(t *testing.T) { shutdownErr := func(context.Context) error { return want } te, err := NewTracesRequest(context.Background(), exportertest.NewNopSettings(), - internal.RequestFromTracesFunc(nil), WithShutdown(shutdownErr)) + requesttest.RequestFromTracesFunc(nil), WithShutdown(shutdownErr)) assert.NotNil(t, te) assert.NoError(t, err) @@ -398,7 +385,7 @@ func newTraceDataPusherModifiedDownstream(retError error) consumer.ConsumeTraces } } -func checkRecordedMetricsForTraces(t *testing.T, tt componenttest.TestTelemetry, te exporter.Traces, wantError error) { +func checkRecordedMetricsForTraces(t *testing.T, tt componenttest.TestTelemetry, id component.ID, te exporter.Traces, wantError error) { td := testdata.GenerateTraces(2) const numBatches = 7 for i := 0; i < numBatches; i++ { @@ -407,9 +394,23 @@ func checkRecordedMetricsForTraces(t *testing.T, tt componenttest.TestTelemetry, // TODO: When the new metrics correctly count partial dropped fix this. if wantError != nil { - require.NoError(t, tt.CheckExporterTraces(0, int64(numBatches*td.SpanCount()))) + metadatatest.AssertEqualExporterSendFailedSpans(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String(internal.ExporterKey, id.String())), + Value: int64(numBatches * td.SpanCount()), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) } else { - require.NoError(t, tt.CheckExporterTraces(int64(numBatches*td.SpanCount()), 0)) + metadatatest.AssertEqualExporterSentSpans(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String(internal.ExporterKey, id.String())), + Value: int64(numBatches * td.SpanCount()), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) } } diff --git a/exporter/exporterhelper/xexporterhelper/go.mod b/exporter/exporterhelper/xexporterhelper/go.mod index e124617a0f62..1d63720c1753 100644 --- a/exporter/exporterhelper/xexporterhelper/go.mod +++ b/exporter/exporterhelper/xexporterhelper/go.mod @@ -52,9 +52,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/exporter/exporterhelper/xexporterhelper/go.sum b/exporter/exporterhelper/xexporterhelper/go.sum index 14b49a682528..a3cacda0f2f6 100644 --- a/exporter/exporterhelper/xexporterhelper/go.sum +++ b/exporter/exporterhelper/xexporterhelper/go.sum @@ -91,12 +91,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/exporter/exporterhelper/xexporterhelper/profiles_batch_test.go b/exporter/exporterhelper/xexporterhelper/profiles_batch_test.go index 206f8d87ada8..2b044fac14cd 100644 --- a/exporter/exporterhelper/xexporterhelper/profiles_batch_test.go +++ b/exporter/exporterhelper/xexporterhelper/profiles_batch_test.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/exporter/exporterbatcher" "go.opentelemetry.io/collector/exporter/exporterhelper" + "go.opentelemetry.io/collector/exporter/internal/requesttest" "go.opentelemetry.io/collector/pdata/pprofile" "go.opentelemetry.io/collector/pdata/testdata" ) @@ -26,9 +27,8 @@ func TestMergeProfiles(t *testing.T) { } func TestMergeProfilesInvalidInput(t *testing.T) { - pr1 := &dummyRequest{} pr2 := newProfilesRequest(testdata.GenerateProfiles(3), nil) - _, err := pr2.MergeSplit(context.Background(), exporterbatcher.MaxSizeConfig{}, pr1) + _, err := pr2.MergeSplit(context.Background(), exporterbatcher.MaxSizeConfig{}, &requesttest.FakeRequest{Items: 1}) assert.Error(t, err) } @@ -125,13 +125,6 @@ func TestMergeSplitProfiles(t *testing.T) { } } -func TestMergeSplitProfilesInvalidInput(t *testing.T) { - r1 := &dummyRequest{} - r2 := newProfilesRequest(testdata.GenerateProfiles(3), nil) - _, err := r2.MergeSplit(context.Background(), exporterbatcher.MaxSizeConfig{}, r1) - assert.Error(t, err) -} - func TestExtractProfiles(t *testing.T) { for i := 0; i < 10; i++ { ld := testdata.GenerateProfiles(10) @@ -140,24 +133,3 @@ func TestExtractProfiles(t *testing.T) { assert.Equal(t, 10-i, ld.SampleCount()) } } - -// dummyRequest implements Request. It is for checking that merging two request types would fail -type dummyRequest struct{} - -func (req *dummyRequest) Export(_ context.Context) error { - return nil -} - -func (req *dummyRequest) ItemsCount() int { - return 1 -} - -func (req *dummyRequest) ByteSize() int { - return 1 -} - -func (req *dummyRequest) MergeSplit(_ context.Context, _ exporterbatcher.MaxSizeConfig, _ exporterhelper.Request) ( - []exporterhelper.Request, error, -) { - return nil, nil -} diff --git a/exporter/exporterqueue/bounded_memory_queue.go b/exporter/exporterqueue/bounded_memory_queue.go index e94eb5da1c38..2c8e1d1e0ff0 100644 --- a/exporter/exporterqueue/bounded_memory_queue.go +++ b/exporter/exporterqueue/bounded_memory_queue.go @@ -11,6 +11,8 @@ import ( "go.opentelemetry.io/collector/component" ) +var noopDone DoneCallback = func(error) {} + // 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. @@ -28,17 +30,13 @@ type memoryQueueSettings[T any] struct { // newBoundedMemoryQueue constructs the new queue of specified capacity, and with an optional // callback for dropped items (e.g. useful to emit metrics). -func newBoundedMemoryQueue[T any](set memoryQueueSettings[T]) Queue[T] { +func newBoundedMemoryQueue[T any](set memoryQueueSettings[T]) readableQueue[T] { return &boundedMemoryQueue[T]{ sizedQueue: newSizedQueue[T](set.capacity, set.sizer, set.blocking), } } -func (q *boundedMemoryQueue[T]) Read(context.Context) (uint64, context.Context, T, bool) { +func (q *boundedMemoryQueue[T]) Read(context.Context) (context.Context, T, DoneCallback, bool) { ctx, req, ok := q.sizedQueue.pop() - return 0, ctx, req, ok + return ctx, req, noopDone, ok } - -// OnProcessingFinished should be called to remove the item of the given index from the queue once processing is finished. -// For in memory queue, this function is noop. -func (q *boundedMemoryQueue[T]) OnProcessingFinished(uint64, error) {} diff --git a/exporter/exporterqueue/bounded_memory_queue_test.go b/exporter/exporterqueue/bounded_memory_queue_test.go index a183cba6c38d..b408fbcecb7d 100644 --- a/exporter/exporterqueue/bounded_memory_queue_test.go +++ b/exporter/exporterqueue/bounded_memory_queue_test.go @@ -74,11 +74,11 @@ func TestBoundedQueue(t *testing.T) { func TestShutdownWhileNotEmpty(t *testing.T) { q := newBoundedMemoryQueue[string](memoryQueueSettings[string]{sizer: &requestSizer[string]{}, capacity: 1000}) - assert.NoError(t, q.Start(context.Background(), componenttest.NewNopHost())) + require.NoError(t, q.Start(context.Background(), componenttest.NewNopHost())) for i := 0; i < 10; i++ { require.NoError(t, q.Offer(context.Background(), strconv.FormatInt(int64(i), 10))) } - assert.NoError(t, q.Shutdown(context.Background())) + require.NoError(t, q.Shutdown(context.Background())) assert.Equal(t, int64(10), q.Size()) numConsumed := 0 @@ -115,16 +115,15 @@ func TestQueueUsage(t *testing.T) { t.Run(tt.name, func(t *testing.T) { q := newBoundedMemoryQueue[uint64](memoryQueueSettings[uint64]{sizer: tt.sizer, capacity: int64(100)}) consumed := &atomic.Int64{} - require.NoError(t, q.Start(context.Background(), componenttest.NewNopHost())) - ac := newAsyncConsumer(q, 1, func(context.Context, uint64) error { + ac := newConsumerQueue(q, 1, func(_ context.Context, _ uint64, done DoneCallback) { consumed.Add(1) - return nil + done(nil) }) + require.NoError(t, ac.Start(context.Background(), componenttest.NewNopHost())) for j := 0; j < 10; j++ { require.NoError(t, q.Offer(context.Background(), uint64(10))) } - assert.NoError(t, q.Shutdown(context.Background())) - assert.NoError(t, ac.Shutdown(context.Background())) + require.NoError(t, ac.Shutdown(context.Background())) assert.Equal(t, int64(10), consumed.Load()) }) } @@ -148,11 +147,11 @@ func TestBlockingQueueUsage(t *testing.T) { t.Run(tt.name, func(t *testing.T) { q := newBoundedMemoryQueue[uint64](memoryQueueSettings[uint64]{sizer: tt.sizer, capacity: int64(100), blocking: true}) consumed := &atomic.Int64{} - require.NoError(t, q.Start(context.Background(), componenttest.NewNopHost())) - ac := newAsyncConsumer(q, 10, func(context.Context, uint64) error { + ac := newConsumerQueue(q, 10, func(_ context.Context, _ uint64, done DoneCallback) { consumed.Add(1) - return nil + done(nil) }) + require.NoError(t, ac.Start(context.Background(), componenttest.NewNopHost())) wg := &sync.WaitGroup{} for i := 0; i < 10; i++ { wg.Add(1) @@ -164,8 +163,7 @@ func TestBlockingQueueUsage(t *testing.T) { }() } wg.Wait() - assert.NoError(t, q.Shutdown(context.Background())) - assert.NoError(t, ac.Shutdown(context.Background())) + require.NoError(t, ac.Shutdown(context.Background())) assert.Equal(t, int64(1_000_000), consumed.Load()) }) } @@ -173,53 +171,21 @@ func TestBlockingQueueUsage(t *testing.T) { func TestZeroSizeNoConsumers(t *testing.T) { q := newBoundedMemoryQueue[string](memoryQueueSettings[string]{sizer: &requestSizer[string]{}, capacity: 0}) - err := q.Start(context.Background(), componenttest.NewNopHost()) require.NoError(t, err) - require.ErrorIs(t, q.Offer(context.Background(), "a"), ErrQueueIsFull) // in process - assert.NoError(t, q.Shutdown(context.Background())) } -func consume[T any](q Queue[T], consumeFunc func(context.Context, T) error) bool { - index, ctx, req, ok := q.Read(context.Background()) +func consume[T any](q readableQueue[T], consumeFunc func(context.Context, T) error) bool { + ctx, req, done, ok := q.Read(context.Background()) if !ok { return false } - q.OnProcessingFinished(index, consumeFunc(ctx, req)) + done(consumeFunc(ctx, req)) return true } -type asyncConsumer struct { - stopWG sync.WaitGroup -} - -func newAsyncConsumer[T any](q Queue[T], numConsumers int, consumeFunc func(context.Context, T) error) *asyncConsumer { - ac := &asyncConsumer{} - - ac.stopWG.Add(numConsumers) - for i := 0; i < numConsumers; i++ { - go func() { - defer ac.stopWG.Done() - for { - index, ctx, req, ok := q.Read(context.Background()) - if !ok { - return - } - q.OnProcessingFinished(index, consumeFunc(ctx, req)) - } - }() - } - return ac -} - -// Shutdown ensures that queue and all consumers are stopped. -func (qc *asyncConsumer) Shutdown(_ context.Context) error { - qc.stopWG.Wait() - return nil -} - func BenchmarkOffer(b *testing.B) { tests := []struct { name string @@ -236,20 +202,20 @@ func BenchmarkOffer(b *testing.B) { } for _, tt := range tests { b.Run(tt.name, func(b *testing.B) { - q := newBoundedMemoryQueue[uint64](memoryQueueSettings[uint64]{sizer: &requestSizer[uint64]{}, capacity: int64(10 * b.N)}) + q := newBoundedMemoryQueue[uint64](memoryQueueSettings[uint64]{sizer: tt.sizer, capacity: int64(10 * b.N)}) consumed := &atomic.Int64{} require.NoError(b, q.Start(context.Background(), componenttest.NewNopHost())) - ac := newAsyncConsumer(q, 1, func(context.Context, uint64) error { + ac := newConsumerQueue(q, 1, func(_ context.Context, _ uint64, done DoneCallback) { consumed.Add(1) - return nil + done(nil) }) + require.NoError(b, ac.Start(context.Background(), componenttest.NewNopHost())) b.ResetTimer() b.ReportAllocs() for j := 0; j < b.N; j++ { require.NoError(b, q.Offer(context.Background(), uint64(10))) } - assert.NoError(b, q.Shutdown(context.Background())) - assert.NoError(b, ac.Shutdown(context.Background())) + require.NoError(b, ac.Shutdown(context.Background())) assert.Equal(b, int64(b.N), consumed.Load()) }) } diff --git a/exporter/exporterqueue/consumers.go b/exporter/exporterqueue/consumers.go new file mode 100644 index 000000000000..022f04b93109 --- /dev/null +++ b/exporter/exporterqueue/consumers.go @@ -0,0 +1,59 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterqueue // import "go.opentelemetry.io/collector/exporter/exporterqueue" + +import ( + "context" + "sync" + + "go.opentelemetry.io/collector/component" +) + +type consumerQueue[T any] struct { + readableQueue[T] + numConsumers int + consumeFunc ConsumeFunc[T] + stopWG sync.WaitGroup +} + +func newConsumerQueue[T any](q readableQueue[T], numConsumers int, consumeFunc ConsumeFunc[T]) *consumerQueue[T] { + return &consumerQueue[T]{ + readableQueue: q, + numConsumers: numConsumers, + consumeFunc: consumeFunc, + } +} + +// Start ensures that queue and all consumers are started. +func (qc *consumerQueue[T]) Start(ctx context.Context, host component.Host) error { + if err := qc.readableQueue.Start(ctx, host); err != nil { + return err + } + var startWG sync.WaitGroup + for i := 0; i < qc.numConsumers; i++ { + qc.stopWG.Add(1) + startWG.Add(1) + go func() { + startWG.Done() + defer qc.stopWG.Done() + for { + ctx, req, done, ok := qc.readableQueue.Read(context.Background()) + if !ok { + return + } + qc.consumeFunc(ctx, req, done) + } + }() + } + startWG.Wait() + + return nil +} + +// Shutdown ensures that queue and all consumers are stopped. +func (qc *consumerQueue[T]) Shutdown(ctx context.Context) error { + err := qc.readableQueue.Shutdown(ctx) + qc.stopWG.Wait() + return err +} diff --git a/exporter/exporterqueue/doc.go b/exporter/exporterqueue/doc.go new file mode 100644 index 000000000000..bb98ffb5324f --- /dev/null +++ b/exporter/exporterqueue/doc.go @@ -0,0 +1,7 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +//go:generate mdatagen metadata.yaml + +// Package exporterqueue provides helper functions for exporter's queue. +package exporterqueue // import "go.opentelemetry.io/collector/exporter/exporterqueue" diff --git a/exporter/exporterqueue/generated_package_test.go b/exporter/exporterqueue/generated_package_test.go new file mode 100644 index 000000000000..fde5822bacc3 --- /dev/null +++ b/exporter/exporterqueue/generated_package_test.go @@ -0,0 +1,13 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package exporterqueue + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/exporter/exporterqueue/metadata.yaml b/exporter/exporterqueue/metadata.yaml new file mode 100644 index 000000000000..9bb03b3df8e7 --- /dev/null +++ b/exporter/exporterqueue/metadata.yaml @@ -0,0 +1,7 @@ +type: exporterqueue +github_project: open-telemetry/opentelemetry-collector + +status: + class: pkg + stability: + beta: [traces, metrics, logs] diff --git a/exporter/exporterqueue/persistent_queue.go b/exporter/exporterqueue/persistent_queue.go index 5e0195ece24d..b35f98682be7 100644 --- a/exporter/exporterqueue/persistent_queue.go +++ b/exporter/exporterqueue/persistent_queue.go @@ -92,7 +92,7 @@ type persistentQueue[T any] struct { } // newPersistentQueue creates a new queue backed by file storage; name and signal must be a unique combination that identifies the queue storage -func newPersistentQueue[T any](set persistentQueueSettings[T]) Queue[T] { +func newPersistentQueue[T any](set persistentQueueSettings[T]) readableQueue[T] { _, isRequestSized := set.sizer.(*requestSizer[T]) pq := &persistentQueue[T]{ set: set, @@ -273,14 +273,14 @@ func (pq *persistentQueue[T]) putInternal(ctx context.Context, req T) error { return nil } -func (pq *persistentQueue[T]) Read(ctx context.Context) (uint64, context.Context, T, bool) { +func (pq *persistentQueue[T]) Read(ctx context.Context) (context.Context, T, DoneCallback, bool) { pq.mu.Lock() defer pq.mu.Unlock() for { if pq.stopped { var req T - return 0, context.Background(), req, false + return context.Background(), req, nil, false } // Read until either a successful retrieved element or no more elements in the storage. @@ -301,7 +301,7 @@ func (pq *persistentQueue[T]) Read(ctx context.Context) (uint64, context.Context } pq.hasMoreSpace.Signal() - return index, context.Background(), req, true + return context.Background(), req, func(processErr error) { pq.onDone(index, processErr) }, true } } @@ -312,7 +312,7 @@ func (pq *persistentQueue[T]) Read(ctx context.Context) (uint64, context.Context } // getNextItem pulls the next available item from the persistent storage along with its index. Once processing is -// finished, the index should be called with OnProcessingFinished to clean up the storage. If no new item is available, +// finished, the index should be called with onDone to clean up the storage. If no new item is available, // returns false. func (pq *persistentQueue[T]) getNextItem(ctx context.Context) (uint64, T, bool) { index := pq.readIndex @@ -347,8 +347,8 @@ func (pq *persistentQueue[T]) getNextItem(ctx context.Context) (uint64, T, bool) return index, request, true } -// OnProcessingFinished should be called to remove the item of the given index from the queue once processing is finished. -func (pq *persistentQueue[T]) OnProcessingFinished(index uint64, consumeErr error) { +// onDone should be called to remove the item of the given index from the queue once processing is finished. +func (pq *persistentQueue[T]) onDone(index uint64, consumeErr error) { // Delete the item from the persistent storage after it was processed. pq.mu.Lock() // Always unref client even if the consumer is shutdown because we always ref it for every valid request. diff --git a/exporter/exporterqueue/persistent_queue_test.go b/exporter/exporterqueue/persistent_queue_test.go index 02c63017a276..7abdf3e481cb 100644 --- a/exporter/exporterqueue/persistent_queue_test.go +++ b/exporter/exporterqueue/persistent_queue_test.go @@ -229,13 +229,14 @@ func createAndStartTestPersistentQueue(t *testing.T, sizer sizer[uint64], capaci unmarshaler: uint64Unmarshaler, set: exportertest.NewNopSettings(), }) + ac := newConsumerQueue(pq, numConsumers, func(ctx context.Context, item uint64, done DoneCallback) { + done(consumeFunc(ctx, item)) + }) host := &mockHost{ext: map[component.ID]component.Component{ {}: storagetest.NewMockStorageExtension(nil), }} - require.NoError(t, pq.Start(context.Background(), host)) - ac := newAsyncConsumer(pq, numConsumers, consumeFunc) + require.NoError(t, ac.Start(context.Background(), host)) t.Cleanup(func() { - require.NoError(t, pq.Shutdown(context.Background())) assert.NoError(t, ac.Shutdown(context.Background())) }) return pq @@ -423,15 +424,15 @@ func TestPersistentBlockingQueue(t *testing.T) { unmarshaler: uint64Unmarshaler, set: exportertest.NewNopSettings(), }) + consumed := &atomic.Int64{} + ac := newConsumerQueue(pq, 10, func(_ context.Context, _ uint64, done DoneCallback) { + consumed.Add(1) + done(nil) + }) host := &mockHost{ext: map[component.ID]component.Component{ {}: storagetest.NewMockStorageExtension(nil), }} - require.NoError(t, pq.Start(context.Background(), host)) - consumed := &atomic.Int64{} - ac := newAsyncConsumer(pq, 10, func(context.Context, uint64) error { - consumed.Add(int64(1)) - return nil - }) + require.NoError(t, ac.Start(context.Background(), host)) td := uint64(10) wg := &sync.WaitGroup{} @@ -449,8 +450,7 @@ func TestPersistentBlockingQueue(t *testing.T) { assert.Eventually(t, func() bool { return 1_000_000 == int(consumed.Load()) }, 5*time.Second, 10*time.Millisecond) - assert.NoError(t, pq.Shutdown(context.Background())) - assert.NoError(t, ac.Shutdown(context.Background())) + require.NoError(t, ac.Shutdown(context.Background())) }) } } @@ -659,19 +659,19 @@ func TestPersistentQueue_CurrentlyProcessedItems(t *testing.T) { requireCurrentlyDispatchedItemsEqual(t, ps, []uint64{}) // Takes index 0 in process. - _, _, readReq, found := ps.Read(context.Background()) + _, readReq, _, found := ps.Read(context.Background()) require.True(t, found) assert.Equal(t, req, readReq) requireCurrentlyDispatchedItemsEqual(t, ps, []uint64{0}) // This takes item 1 to process. - secondIndex, _, secondReadReq, found := ps.Read(context.Background()) + _, secondReadReq, secondDone, found := ps.Read(context.Background()) require.True(t, found) assert.Equal(t, req, secondReadReq) requireCurrentlyDispatchedItemsEqual(t, ps, []uint64{0, 1}) // Lets mark item 1 as finished, it will remove it from the currently dispatched items list. - ps.OnProcessingFinished(secondIndex, nil) + secondDone(nil) requireCurrentlyDispatchedItemsEqual(t, ps, []uint64{0}) // Reload the storage. Since items 0 was not finished, this should be re-enqueued at the end. @@ -800,8 +800,8 @@ func TestPersistentQueue_PutCloseReadClose(t *testing.T) { assert.Equal(t, int64(0), ps.Size()) // Put two elements and close the extension - assert.NoError(t, ps.Offer(context.Background(), req)) - assert.NoError(t, ps.Offer(context.Background(), req)) + require.NoError(t, ps.Offer(context.Background(), req)) + require.NoError(t, ps.Offer(context.Background(), req)) assert.Equal(t, int64(2), ps.Size()) // TODO: Remove this, after the initialization writes the readIndex. _, _, _, _ = ps.Read(context.Background()) @@ -822,7 +822,7 @@ func TestPersistentQueue_PutCloseReadClose(t *testing.T) { return nil }) require.Equal(t, int64(0), newPs.Size()) - assert.NoError(t, newPs.Shutdown(context.Background())) + require.NoError(t, newPs.Shutdown(context.Background())) } func BenchmarkPersistentQueue(b *testing.B) { @@ -910,12 +910,12 @@ func TestPersistentQueue_ShutdownWhileConsuming(t *testing.T) { require.NoError(t, ps.Offer(context.Background(), uint64(50))) - index, _, _, ok := ps.Read(context.Background()) + _, _, done, ok := ps.Read(context.Background()) require.True(t, ok) assert.False(t, ps.client.(*storagetest.MockStorageClient).IsClosed()) require.NoError(t, ps.Shutdown(context.Background())) assert.False(t, ps.client.(*storagetest.MockStorageClient).IsClosed()) - ps.OnProcessingFinished(index, nil) + done(nil) assert.True(t, ps.client.(*storagetest.MockStorageClient).IsClosed()) } @@ -1018,9 +1018,9 @@ func TestPersistentQueue_ItemsCapacityUsageRestoredOnShutdown(t *testing.T) { assert.Equal(t, int64(0), pq.Size()) // Fill the queue up to the capacity. - assert.NoError(t, pq.Offer(context.Background(), uint64(40))) - assert.NoError(t, pq.Offer(context.Background(), uint64(40))) - assert.NoError(t, pq.Offer(context.Background(), uint64(20))) + require.NoError(t, pq.Offer(context.Background(), uint64(40))) + require.NoError(t, pq.Offer(context.Background(), uint64(40))) + require.NoError(t, pq.Offer(context.Background(), uint64(20))) assert.Equal(t, int64(100), pq.Size()) require.ErrorIs(t, pq.Offer(context.Background(), uint64(25)), ErrQueueIsFull) @@ -1056,7 +1056,7 @@ func TestPersistentQueue_ItemsCapacityUsageRestoredOnShutdown(t *testing.T) { })) assert.Equal(t, int64(10), newPQ.Size()) - assert.NoError(t, newPQ.Shutdown(context.Background())) + require.NoError(t, newPQ.Shutdown(context.Background())) } // This test covers the case when the items capacity queue is enabled for the first time. @@ -1066,9 +1066,9 @@ func TestPersistentQueue_ItemsCapacityUsageIsNotPreserved(t *testing.T) { assert.Equal(t, int64(0), pq.Size()) - assert.NoError(t, pq.Offer(context.Background(), uint64(40))) - assert.NoError(t, pq.Offer(context.Background(), uint64(20))) - assert.NoError(t, pq.Offer(context.Background(), uint64(25))) + require.NoError(t, pq.Offer(context.Background(), uint64(40))) + require.NoError(t, pq.Offer(context.Background(), uint64(20))) + require.NoError(t, pq.Offer(context.Background(), uint64(25))) assert.Equal(t, int64(3), pq.Size()) assert.True(t, consume(pq, func(_ context.Context, val uint64) error { @@ -1113,7 +1113,7 @@ func TestPersistentQueue_ItemsCapacityUsageIsNotPreserved(t *testing.T) { })) assert.Equal(t, int64(15), newPQ.Size()) - assert.NoError(t, newPQ.Shutdown(context.Background())) + require.NoError(t, newPQ.Shutdown(context.Background())) } // This test covers the case when the queue is restarted with the less capacity than needed to restore the queued items. @@ -1124,10 +1124,10 @@ func TestPersistentQueue_RequestCapacityLessAfterRestart(t *testing.T) { assert.Equal(t, int64(0), pq.Size()) - assert.NoError(t, pq.Offer(context.Background(), uint64(40))) - assert.NoError(t, pq.Offer(context.Background(), uint64(20))) - assert.NoError(t, pq.Offer(context.Background(), uint64(25))) - assert.NoError(t, pq.Offer(context.Background(), uint64(5))) + require.NoError(t, pq.Offer(context.Background(), uint64(40))) + require.NoError(t, pq.Offer(context.Background(), uint64(20))) + require.NoError(t, pq.Offer(context.Background(), uint64(25))) + require.NoError(t, pq.Offer(context.Background(), uint64(5))) // Read the first request just to populate the read index in the storage. // Otherwise, the write index won't be restored either. @@ -1165,9 +1165,9 @@ func TestPersistentQueue_RequestCapacityLessAfterRestart(t *testing.T) { assert.Equal(t, int64(1), newPQ.Size()) // Now it can accept new items - assert.NoError(t, newPQ.Offer(context.Background(), uint64(10))) + require.NoError(t, newPQ.Offer(context.Background(), uint64(10))) - assert.NoError(t, newPQ.Shutdown(context.Background())) + require.NoError(t, newPQ.Shutdown(context.Background())) } // This test covers the case when the persistent storage is recovered from a snapshot which has @@ -1205,8 +1205,8 @@ func TestPersistentQueue_RestoredUsedSizeIsCorrectedOnDrain(t *testing.T) { assert.True(t, consume(newPQ, func(context.Context, uint64) error { return nil })) assert.Equal(t, int64(0), newPQ.Size()) - assert.NoError(t, newPQ.Shutdown(context.Background())) - assert.NoError(t, pq.Shutdown(context.Background())) + require.NoError(t, newPQ.Shutdown(context.Background())) + require.NoError(t, pq.Shutdown(context.Background())) } func requireCurrentlyDispatchedItemsEqual(t *testing.T, pq *persistentQueue[uint64], compare []uint64) { diff --git a/exporter/exporterqueue/queue.go b/exporter/exporterqueue/queue.go index 549f1ce7635b..3a99906a1706 100644 --- a/exporter/exporterqueue/queue.go +++ b/exporter/exporterqueue/queue.go @@ -12,11 +12,20 @@ import ( "go.opentelemetry.io/collector/pipeline" ) -// ErrQueueIsFull is the error returned when an item is offered to the Queue and the queue is full. +// ErrQueueIsFull is the error returned when an item is offered to the Queue and the queue is full and setup to +// not block. // Experimental: 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. var ErrQueueIsFull = errors.New("sending queue is full") +// DoneCallback represents the callback that will be called when the read request is completely processed by the +// downstream components. +// Experimental: 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 DoneCallback func(processErr error) + +type ConsumeFunc[T any] func(context.Context, T, DoneCallback) + // Queue 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) // Experimental: This API is at the early stage of development and may change without backward compatibility @@ -31,13 +40,16 @@ type Queue[T any] interface { Size() int64 // Capacity returns the capacity of the queue. Capacity() int64 - // Read pulls the next available item from the queue along with its index. Once processing is - // finished, the index should be called with OnProcessingFinished to clean up the storage. +} + +// TODO: Investigate why linter "unused" fails if add a private "read" func on the Queue. +type readableQueue[T any] interface { + Queue[T] + // Read pulls the next available item from the queue along with its done callback. Once processing is + // finished, the done callback must be called to clean up the storage. // The function blocks until an item is available or if the queue is stopped. - // Returns false if reading failed or if the queue is stopped. - Read(context.Context) (uint64, context.Context, T, bool) - // OnProcessingFinished should be called to remove the item of the given index from the queue once processing is finished. - OnProcessingFinished(index uint64, consumeErr error) + // If the queue is stopped returns false, otherwise true. + Read(context.Context) (context.Context, T, DoneCallback, bool) } // Settings defines settings for creating a queue. @@ -59,18 +71,19 @@ type Unmarshaler[T any] func([]byte) (T, error) // Factory is a function that creates a new queue. // Experimental: 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 Factory[T any] func(context.Context, Settings, Config) Queue[T] +type Factory[T any] func(context.Context, Settings, Config, ConsumeFunc[T]) Queue[T] // NewMemoryQueueFactory returns a factory to create a new memory queue. // Experimental: 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 NewMemoryQueueFactory[T any]() Factory[T] { - return func(_ context.Context, _ Settings, cfg Config) Queue[T] { - return newBoundedMemoryQueue[T](memoryQueueSettings[T]{ + return func(_ context.Context, _ Settings, cfg Config, consume ConsumeFunc[T]) Queue[T] { + q := newBoundedMemoryQueue[T](memoryQueueSettings[T]{ sizer: &requestSizer[T]{}, capacity: int64(cfg.QueueSize), blocking: cfg.Blocking, }) + return newConsumerQueue(q, cfg.NumConsumers, consume) } } @@ -92,8 +105,8 @@ func NewPersistentQueueFactory[T any](storageID *component.ID, factorySettings P if storageID == nil { return NewMemoryQueueFactory[T]() } - return func(_ context.Context, set Settings, cfg Config) Queue[T] { - return newPersistentQueue[T](persistentQueueSettings[T]{ + return func(_ context.Context, set Settings, cfg Config, consume ConsumeFunc[T]) Queue[T] { + q := newPersistentQueue[T](persistentQueueSettings[T]{ sizer: &requestSizer[T]{}, capacity: int64(cfg.QueueSize), blocking: cfg.Blocking, @@ -103,5 +116,6 @@ func NewPersistentQueueFactory[T any](storageID *component.ID, factorySettings P unmarshaler: factorySettings.Unmarshaler, set: set.ExporterSettings, }) + return newConsumerQueue(q, cfg.NumConsumers, consume) } } diff --git a/exporter/exportertest/go.mod b/exporter/exportertest/go.mod index 9a9932b85dd7..d28e933fed0a 100644 --- a/exporter/exportertest/go.mod +++ b/exporter/exportertest/go.mod @@ -18,7 +18,7 @@ require ( go.opentelemetry.io/collector/pipeline v0.118.0 go.opentelemetry.io/collector/receiver v0.118.0 go.opentelemetry.io/collector/receiver/receivertest v0.118.0 - google.golang.org/grpc v1.69.4 + google.golang.org/grpc v1.70.0 ) require ( @@ -49,8 +49,8 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/exporter/exportertest/go.sum b/exporter/exportertest/go.sum index 14b49a682528..a3cacda0f2f6 100644 --- a/exporter/exportertest/go.sum +++ b/exporter/exportertest/go.sum @@ -91,12 +91,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/exporter/go.mod b/exporter/go.mod index 5f2fd91e5b81..99db7f06a476 100644 --- a/exporter/go.mod +++ b/exporter/go.mod @@ -51,9 +51,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/exporter/go.sum b/exporter/go.sum index 14b49a682528..a3cacda0f2f6 100644 --- a/exporter/go.sum +++ b/exporter/go.sum @@ -91,12 +91,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/exporter/internal/queue/batcher.go b/exporter/internal/queue/batcher.go index df45a7b97c91..7e71dd9f8269 100644 --- a/exporter/internal/queue/batcher.go +++ b/exporter/internal/queue/batcher.go @@ -5,7 +5,6 @@ package queue // import "go.opentelemetry.io/collector/exporter/internal/queue" import ( "context" - "sync" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/exporter/exporterbatcher" @@ -13,74 +12,18 @@ import ( "go.opentelemetry.io/collector/exporter/internal" ) -type batch struct { - ctx context.Context - req internal.Request - idxList []uint64 -} - // Batcher is in charge of reading items from the queue and send them out asynchronously. type Batcher interface { component.Component -} - -type BaseBatcher struct { - batchCfg exporterbatcher.Config - queue exporterqueue.Queue[internal.Request] - // TODO: Remove when the -1 hack for testing is removed. - maxWorkers int - workerPool chan bool - exportFunc func(ctx context.Context, req internal.Request) error - stopWG sync.WaitGroup + Consume(context.Context, internal.Request, exporterqueue.DoneCallback) } func NewBatcher(batchCfg exporterbatcher.Config, - queue exporterqueue.Queue[internal.Request], exportFunc func(ctx context.Context, req internal.Request) error, maxWorkers int, ) (Batcher, error) { if !batchCfg.Enabled { - return &DisabledBatcher{BaseBatcher: newBaseBatcher(batchCfg, queue, exportFunc, maxWorkers)}, nil - } - return &DefaultBatcher{BaseBatcher: newBaseBatcher(batchCfg, queue, exportFunc, maxWorkers)}, nil -} - -func newBaseBatcher(batchCfg exporterbatcher.Config, - queue exporterqueue.Queue[internal.Request], - exportFunc func(ctx context.Context, req internal.Request) error, - maxWorkers int, -) BaseBatcher { - var workerPool chan bool - if maxWorkers > 0 { - workerPool = make(chan bool, maxWorkers) - for i := 0; i < maxWorkers; i++ { - workerPool <- true - } - } - return BaseBatcher{ - batchCfg: batchCfg, - queue: queue, - maxWorkers: maxWorkers, - workerPool: workerPool, - exportFunc: exportFunc, - stopWG: sync.WaitGroup{}, - } -} - -// flush starts a goroutine that calls exportFunc. It blocks until a worker is available if necessary. -func (qb *BaseBatcher) flush(batchToFlush batch) { - qb.stopWG.Add(1) - if qb.workerPool != nil { - <-qb.workerPool + return newDisabledBatcher(exportFunc), nil } - go func() { - defer qb.stopWG.Done() - err := qb.exportFunc(batchToFlush.ctx, batchToFlush.req) - for _, idx := range batchToFlush.idxList { - qb.queue.OnProcessingFinished(idx, err) - } - if qb.workerPool != nil { - qb.workerPool <- true - } - }() + return newDefaultBatcher(batchCfg, exportFunc, maxWorkers), nil } diff --git a/exporter/internal/queue/consumers.go b/exporter/internal/queue/consumers.go deleted file mode 100644 index 4db4b830e3c4..000000000000 --- a/exporter/internal/queue/consumers.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package queue // import "go.opentelemetry.io/collector/exporter/internal/queue" - -import ( - "context" - "sync" - - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/exporter/exporterqueue" -) - -type Consumers[T any] struct { - queue exporterqueue.Queue[T] - numConsumers int - consumeFunc func(context.Context, T) error - stopWG sync.WaitGroup -} - -func NewQueueConsumers[T any](q exporterqueue.Queue[T], numConsumers int, consumeFunc func(context.Context, T) error) *Consumers[T] { - return &Consumers[T]{ - queue: q, - numConsumers: numConsumers, - consumeFunc: consumeFunc, - } -} - -// Start ensures that queue and all consumers are started. -func (qc *Consumers[T]) Start(_ context.Context, _ component.Host) error { - var startWG sync.WaitGroup - for i := 0; i < qc.numConsumers; i++ { - qc.stopWG.Add(1) - startWG.Add(1) - go func() { - startWG.Done() - defer qc.stopWG.Done() - for { - index, ctx, req, ok := qc.queue.Read(context.Background()) - if !ok { - return - } - consumeErr := qc.consumeFunc(ctx, req) - qc.queue.OnProcessingFinished(index, consumeErr) - } - }() - } - startWG.Wait() - - return nil -} - -// Shutdown ensures that queue and all consumers are stopped. -func (qc *Consumers[T]) Shutdown(_ context.Context) error { - qc.stopWG.Wait() - return nil -} diff --git a/exporter/internal/queue/default_batcher.go b/exporter/internal/queue/default_batcher.go index dced12e9e2bf..c625fc15a460 100644 --- a/exporter/internal/queue/default_batcher.go +++ b/exporter/internal/queue/default_batcher.go @@ -5,122 +5,130 @@ package queue // import "go.opentelemetry.io/collector/exporter/internal/queue" import ( "context" - "math" "sync" "time" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/exporter/exporterbatcher" + "go.opentelemetry.io/collector/exporter/exporterqueue" "go.opentelemetry.io/collector/exporter/internal" ) -// DefaultBatcher continuously reads from the queue and flushes asynchronously if size limit is met or on timeout. -type DefaultBatcher struct { - BaseBatcher +type batch struct { + ctx context.Context + req internal.Request + dones []exporterqueue.DoneCallback +} + +// defaultBatcher continuously batch incoming requests and flushes asynchronously if minimum size limit is met or on timeout. +type defaultBatcher struct { + batchCfg exporterbatcher.Config + workerPool chan struct{} + exportFunc func(ctx context.Context, req internal.Request) error + stopWG sync.WaitGroup currentBatchMu sync.Mutex currentBatch *batch timer *time.Timer - shutdownCh chan bool + shutdownCh chan struct{} +} + +func newDefaultBatcher(batchCfg exporterbatcher.Config, + exportFunc func(ctx context.Context, req internal.Request) error, + maxWorkers int, +) *defaultBatcher { + workerPool := make(chan struct{}, maxWorkers) + for i := 0; i < maxWorkers; i++ { + workerPool <- struct{}{} + } + return &defaultBatcher{ + batchCfg: batchCfg, + workerPool: workerPool, + exportFunc: exportFunc, + stopWG: sync.WaitGroup{}, + shutdownCh: make(chan struct{}, 1), + } } -func (qb *DefaultBatcher) resetTimer() { +func (qb *defaultBatcher) resetTimer() { if qb.batchCfg.FlushTimeout != 0 { qb.timer.Reset(qb.batchCfg.FlushTimeout) } } -// startReadingFlushingGoroutine starts a goroutine that reads and then flushes. -func (qb *DefaultBatcher) startReadingFlushingGoroutine() { - qb.stopWG.Add(1) - go func() { - defer qb.stopWG.Done() - for { - // Read() blocks until the queue is non-empty or until the queue is stopped. - idx, ctx, req, ok := qb.queue.Read(context.Background()) - if !ok { - qb.shutdownCh <- true +func (qb *defaultBatcher) Consume(ctx context.Context, req internal.Request, done exporterqueue.DoneCallback) { + qb.currentBatchMu.Lock() + if qb.batchCfg.MaxSizeItems > 0 { + var reqList []internal.Request + var mergeSplitErr error + if qb.currentBatch == nil || qb.currentBatch.req == nil { + qb.resetTimer() + reqList, mergeSplitErr = req.MergeSplit(ctx, qb.batchCfg.MaxSizeConfig, nil) + } else { + reqList, mergeSplitErr = qb.currentBatch.req.MergeSplit(ctx, qb.batchCfg.MaxSizeConfig, req) + } + + if mergeSplitErr != nil || reqList == nil { + done(mergeSplitErr) + qb.currentBatchMu.Unlock() + return + } + + // If there was a split, we flush everything immediately. + if reqList[0].ItemsCount() >= qb.batchCfg.MinSizeItems || len(reqList) > 1 { + qb.currentBatch = nil + qb.currentBatchMu.Unlock() + for i := 0; i < len(reqList); i++ { + qb.flush(ctx, reqList[i], []exporterqueue.DoneCallback{done}) + // TODO: handle partial failure + } + qb.resetTimer() + } else { + qb.currentBatch = &batch{ + req: reqList[0], + ctx: ctx, + dones: []exporterqueue.DoneCallback{done}, + } + qb.currentBatchMu.Unlock() + } + } else { + if qb.currentBatch == nil || qb.currentBatch.req == nil { + qb.resetTimer() + qb.currentBatch = &batch{ + req: req, + ctx: ctx, + dones: []exporterqueue.DoneCallback{done}, + } + } else { + // TODO: consolidate implementation for the cases where MaxSizeConfig is specified and the case where it is not specified + mergedReq, mergeErr := qb.currentBatch.req.MergeSplit(qb.currentBatch.ctx, qb.batchCfg.MaxSizeConfig, req) + if mergeErr != nil { + done(mergeErr) + qb.currentBatchMu.Unlock() return } - - qb.currentBatchMu.Lock() - - if qb.batchCfg.MaxSizeItems > 0 { - var reqList []internal.Request - var mergeSplitErr error - if qb.currentBatch == nil || qb.currentBatch.req == nil { - qb.resetTimer() - reqList, mergeSplitErr = req.MergeSplit(ctx, qb.batchCfg.MaxSizeConfig, nil) - } else { - reqList, mergeSplitErr = qb.currentBatch.req.MergeSplit(ctx, qb.batchCfg.MaxSizeConfig, req) - } - - if mergeSplitErr != nil || reqList == nil { - qb.queue.OnProcessingFinished(idx, mergeSplitErr) - qb.currentBatchMu.Unlock() - continue - } - - // If there was a split, we flush everything immediately. - if reqList[0].ItemsCount() >= qb.batchCfg.MinSizeItems || len(reqList) > 1 { - qb.currentBatch = nil - qb.currentBatchMu.Unlock() - for i := 0; i < len(reqList); i++ { - qb.flush(batch{ - req: reqList[i], - ctx: ctx, - idxList: []uint64{idx}, - }) - // TODO: handle partial failure - } - qb.resetTimer() - } else { - qb.currentBatch = &batch{ - req: reqList[0], - ctx: ctx, - idxList: []uint64{idx}, - } - qb.currentBatchMu.Unlock() - } - } else { - if qb.currentBatch == nil || qb.currentBatch.req == nil { - qb.resetTimer() - qb.currentBatch = &batch{ - req: req, - ctx: ctx, - idxList: []uint64{idx}, - } - } else { - // TODO: consolidate implementation for the cases where MaxSizeConfig is specified and the case where it is not specified - mergedReq, mergeErr := qb.currentBatch.req.MergeSplit(qb.currentBatch.ctx, qb.batchCfg.MaxSizeConfig, req) - if mergeErr != nil { - qb.queue.OnProcessingFinished(idx, mergeErr) - qb.currentBatchMu.Unlock() - continue - } - qb.currentBatch = &batch{ - req: mergedReq[0], - ctx: qb.currentBatch.ctx, - idxList: append(qb.currentBatch.idxList, idx), - } - } - - if qb.currentBatch.req.ItemsCount() >= qb.batchCfg.MinSizeItems { - batchToFlush := *qb.currentBatch - qb.currentBatch = nil - qb.currentBatchMu.Unlock() - - // flush() blocks until successfully started a goroutine for flushing. - qb.flush(batchToFlush) - qb.resetTimer() - } else { - qb.currentBatchMu.Unlock() - } + qb.currentBatch = &batch{ + req: mergedReq[0], + ctx: qb.currentBatch.ctx, + dones: append(qb.currentBatch.dones, done), } } - }() + + if qb.currentBatch.req.ItemsCount() >= qb.batchCfg.MinSizeItems { + batchToFlush := *qb.currentBatch + qb.currentBatch = nil + qb.currentBatchMu.Unlock() + + // flush() blocks until successfully started a goroutine for flushing. + qb.flush(batchToFlush.ctx, batchToFlush.req, batchToFlush.dones) + qb.resetTimer() + } else { + qb.currentBatchMu.Unlock() + } + } } // startTimeBasedFlushingGoroutine starts a goroutine that flushes on timeout. -func (qb *DefaultBatcher) startTimeBasedFlushingGoroutine() { +func (qb *defaultBatcher) startTimeBasedFlushingGoroutine() { qb.stopWG.Add(1) go func() { defer qb.stopWG.Done() @@ -136,28 +144,17 @@ func (qb *DefaultBatcher) startTimeBasedFlushingGoroutine() { } // Start starts the goroutine that reads from the queue and flushes asynchronously. -func (qb *DefaultBatcher) Start(_ context.Context, _ component.Host) error { - // maxWorker being -1 means batcher is disabled. This is for testing queue sender metrics. - if qb.maxWorkers == -1 { - return nil - } - - qb.shutdownCh = make(chan bool, 1) - - if qb.batchCfg.FlushTimeout == 0 { - qb.timer = time.NewTimer(math.MaxInt) - qb.timer.Stop() - } else { +func (qb *defaultBatcher) Start(_ context.Context, _ component.Host) error { + if qb.batchCfg.FlushTimeout != 0 { qb.timer = time.NewTimer(qb.batchCfg.FlushTimeout) + qb.startTimeBasedFlushingGoroutine() } - qb.startReadingFlushingGoroutine() - qb.startTimeBasedFlushingGoroutine() return nil } // flushCurrentBatchIfNecessary sends out the current request batch if it is not nil -func (qb *DefaultBatcher) flushCurrentBatchIfNecessary() { +func (qb *defaultBatcher) flushCurrentBatchIfNecessary() { qb.currentBatchMu.Lock() if qb.currentBatch == nil || qb.currentBatch.req == nil { qb.currentBatchMu.Unlock() @@ -168,12 +165,28 @@ func (qb *DefaultBatcher) flushCurrentBatchIfNecessary() { qb.currentBatchMu.Unlock() // flush() blocks until successfully started a goroutine for flushing. - qb.flush(batchToFlush) + qb.flush(batchToFlush.ctx, batchToFlush.req, batchToFlush.dones) qb.resetTimer() } +// flush starts a goroutine that calls exportFunc. It blocks until a worker is available if necessary. +func (qb *defaultBatcher) flush(ctx context.Context, req internal.Request, dones []exporterqueue.DoneCallback) { + qb.stopWG.Add(1) + <-qb.workerPool + go func() { + defer qb.stopWG.Done() + err := qb.exportFunc(ctx, req) + for _, done := range dones { + done(err) + } + qb.workerPool <- struct{}{} + }() +} + // Shutdown ensures that queue and all Batcher are stopped. -func (qb *DefaultBatcher) Shutdown(_ context.Context) error { +func (qb *defaultBatcher) Shutdown(_ context.Context) error { + close(qb.shutdownCh) + // Make sure execute one last flush if necessary. qb.flushCurrentBatchIfNecessary() qb.stopWG.Wait() return nil diff --git a/exporter/internal/queue/default_batcher_test.go b/exporter/internal/queue/default_batcher_test.go index 7d9f97d1f530..a46649e0b802 100644 --- a/exporter/internal/queue/default_batcher_test.go +++ b/exporter/internal/queue/default_batcher_test.go @@ -27,10 +27,6 @@ func TestDefaultBatcher_NoSplit_MinThresholdZero_TimeoutDisabled(t *testing.T) { name string maxWorkers int }{ - { - name: "infinate_workers", - maxWorkers: 0, - }, { name: "one_worker", maxWorkers: 1, @@ -49,18 +45,22 @@ func TestDefaultBatcher_NoSplit_MinThresholdZero_TimeoutDisabled(t *testing.T) { MinSizeItems: 0, } + ba, err := NewBatcher(cfg, + func(ctx context.Context, req internal.Request) error { return req.Export(ctx) }, + tt.maxWorkers) + require.NoError(t, err) + + // TODO: https://github.com/open-telemetry/opentelemetry-collector/issues/12244 + qCfg := exporterqueue.NewDefaultConfig() + qCfg.NumConsumers = 1 q := exporterqueue.NewMemoryQueueFactory[internal.Request]()( context.Background(), exporterqueue.Settings{ Signal: pipeline.SignalTraces, ExporterSettings: exportertest.NewNopSettings(), }, - exporterqueue.NewDefaultConfig()) - - ba, err := NewBatcher(cfg, q, - func(ctx context.Context, req internal.Request) error { return req.Export(ctx) }, - tt.maxWorkers) - require.NoError(t, err) + qCfg, + ba.Consume) require.NoError(t, q.Start(context.Background(), componenttest.NewNopHost())) require.NoError(t, ba.Start(context.Background(), componenttest.NewNopHost())) @@ -89,10 +89,6 @@ func TestDefaultBatcher_NoSplit_TimeoutDisabled(t *testing.T) { name string maxWorkers int }{ - { - name: "infinate_workers", - maxWorkers: 0, - }, { name: "one_worker", maxWorkers: 1, @@ -111,18 +107,22 @@ func TestDefaultBatcher_NoSplit_TimeoutDisabled(t *testing.T) { MinSizeItems: 10, } + ba, err := NewBatcher(cfg, + func(ctx context.Context, req internal.Request) error { return req.Export(ctx) }, + tt.maxWorkers) + require.NoError(t, err) + + // TODO: https://github.com/open-telemetry/opentelemetry-collector/issues/12244 + qCfg := exporterqueue.NewDefaultConfig() + qCfg.NumConsumers = 1 q := exporterqueue.NewMemoryQueueFactory[internal.Request]()( context.Background(), exporterqueue.Settings{ Signal: pipeline.SignalTraces, ExporterSettings: exportertest.NewNopSettings(), }, - exporterqueue.NewDefaultConfig()) - - ba, err := NewBatcher(cfg, q, - func(ctx context.Context, req internal.Request) error { return req.Export(ctx) }, - tt.maxWorkers) - require.NoError(t, err) + qCfg, + ba.Consume) require.NoError(t, q.Start(context.Background(), componenttest.NewNopHost())) require.NoError(t, ba.Start(context.Background(), componenttest.NewNopHost())) @@ -161,10 +161,6 @@ func TestDefaultBatcher_NoSplit_WithTimeout(t *testing.T) { name string maxWorkers int }{ - { - name: "infinate_workers", - maxWorkers: 0, - }, { name: "one_worker", maxWorkers: 1, @@ -183,18 +179,22 @@ func TestDefaultBatcher_NoSplit_WithTimeout(t *testing.T) { MinSizeItems: 100, } + ba, err := NewBatcher(cfg, + func(ctx context.Context, req internal.Request) error { return req.Export(ctx) }, + tt.maxWorkers) + require.NoError(t, err) + + // TODO: https://github.com/open-telemetry/opentelemetry-collector/issues/12244 + qCfg := exporterqueue.NewDefaultConfig() + qCfg.NumConsumers = 1 q := exporterqueue.NewMemoryQueueFactory[internal.Request]()( context.Background(), exporterqueue.Settings{ Signal: pipeline.SignalTraces, ExporterSettings: exportertest.NewNopSettings(), }, - exporterqueue.NewDefaultConfig()) - - ba, err := NewBatcher(cfg, q, - func(ctx context.Context, req internal.Request) error { return req.Export(ctx) }, - tt.maxWorkers) - require.NoError(t, err) + qCfg, + ba.Consume) require.NoError(t, q.Start(context.Background(), componenttest.NewNopHost())) require.NoError(t, ba.Start(context.Background(), componenttest.NewNopHost())) @@ -230,10 +230,6 @@ func TestDefaultBatcher_Split_TimeoutDisabled(t *testing.T) { name string maxWorkers int }{ - { - name: "infinate_workers", - maxWorkers: 0, - }, { name: "one_worker", maxWorkers: 1, @@ -255,18 +251,22 @@ func TestDefaultBatcher_Split_TimeoutDisabled(t *testing.T) { MaxSizeItems: 100, } + ba, err := NewBatcher(cfg, + func(ctx context.Context, req internal.Request) error { return req.Export(ctx) }, + tt.maxWorkers) + require.NoError(t, err) + + // TODO: https://github.com/open-telemetry/opentelemetry-collector/issues/12244 + qCfg := exporterqueue.NewDefaultConfig() + qCfg.NumConsumers = 1 q := exporterqueue.NewMemoryQueueFactory[internal.Request]()( context.Background(), exporterqueue.Settings{ Signal: pipeline.SignalTraces, ExporterSettings: exportertest.NewNopSettings(), }, - exporterqueue.NewDefaultConfig()) - - ba, err := NewBatcher(cfg, q, - func(ctx context.Context, req internal.Request) error { return req.Export(ctx) }, - tt.maxWorkers) - require.NoError(t, err) + qCfg, + ba.Consume) require.NoError(t, q.Start(context.Background(), componenttest.NewNopHost())) require.NoError(t, ba.Start(context.Background(), componenttest.NewNopHost())) @@ -304,18 +304,22 @@ func TestDefaultBatcher_Shutdown(t *testing.T) { batchCfg.MinSizeItems = 10 batchCfg.FlushTimeout = 100 * time.Second + ba, err := NewBatcher(batchCfg, + func(ctx context.Context, req internal.Request) error { return req.Export(ctx) }, + 2) + require.NoError(t, err) + + // TODO: https://github.com/open-telemetry/opentelemetry-collector/issues/12244 + qCfg := exporterqueue.NewDefaultConfig() + qCfg.NumConsumers = 1 q := exporterqueue.NewMemoryQueueFactory[internal.Request]()( context.Background(), exporterqueue.Settings{ Signal: pipeline.SignalTraces, ExporterSettings: exportertest.NewNopSettings(), }, - exporterqueue.NewDefaultConfig()) - - ba, err := NewBatcher(batchCfg, q, - func(ctx context.Context, req internal.Request) error { return req.Export(ctx) }, - 2) - require.NoError(t, err) + qCfg, + ba.Consume) require.NoError(t, q.Start(context.Background(), componenttest.NewNopHost())) require.NoError(t, ba.Start(context.Background(), componenttest.NewNopHost())) diff --git a/exporter/internal/queue/disabled_batcher.go b/exporter/internal/queue/disabled_batcher.go index be89f58e0113..9408aa34ce37 100644 --- a/exporter/internal/queue/disabled_batcher.go +++ b/exporter/internal/queue/disabled_batcher.go @@ -7,44 +7,22 @@ import ( "context" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/exporter/exporterqueue" + "go.opentelemetry.io/collector/exporter/internal" ) -// DisabledBatcher is a special-case of Batcher that has no size limit for sending. Any items read from the queue will +// disabledBatcher is a special-case of Batcher that has no size limit for sending. Any items read from the queue will // be sent out (asynchronously) immediately regardless of the size. -type DisabledBatcher struct { - BaseBatcher +type disabledBatcher[T any] struct { + component.StartFunc + component.ShutdownFunc + exportFunc func(context.Context, T) error } -// Start starts the goroutine that reads from the queue and flushes asynchronously. -func (qb *DisabledBatcher) Start(_ context.Context, _ component.Host) error { - // maxWorker being -1 means batcher is disabled. This is for testing queue sender metrics. - if qb.maxWorkers == -1 { - return nil - } - - // This goroutine reads and then flushes. - // 1. Reading from the queue is blocked until the queue is non-empty or until the queue is stopped. - // 2. flush() blocks until there are idle workers in the worker pool. - qb.stopWG.Add(1) - go func() { - defer qb.stopWG.Done() - for { - idx, _, req, ok := qb.queue.Read(context.Background()) - if !ok { - return - } - qb.flush(batch{ - req: req, - ctx: context.Background(), - idxList: []uint64{idx}, - }) - } - }() - return nil +func (db *disabledBatcher[T]) Consume(ctx context.Context, req T, done exporterqueue.DoneCallback) { + done(db.exportFunc(ctx, req)) } -// Shutdown ensures that queue and all Batcher are stopped. -func (qb *DisabledBatcher) Shutdown(_ context.Context) error { - qb.stopWG.Wait() - return nil +func newDisabledBatcher(exportFunc func(ctx context.Context, req internal.Request) error) Batcher { + return &disabledBatcher[internal.Request]{exportFunc: exportFunc} } diff --git a/exporter/internal/queue/disabled_batcher_test.go b/exporter/internal/queue/disabled_batcher_test.go index 10bede060ed1..dffa77fafebd 100644 --- a/exporter/internal/queue/disabled_batcher_test.go +++ b/exporter/internal/queue/disabled_batcher_test.go @@ -26,10 +26,6 @@ func TestDisabledBatcher_Basic(t *testing.T) { name string maxWorkers int }{ - { - name: "infinate_workers", - maxWorkers: 0, - }, { name: "one_worker", maxWorkers: 1, @@ -44,18 +40,19 @@ func TestDisabledBatcher_Basic(t *testing.T) { cfg := exporterbatcher.NewDefaultConfig() cfg.Enabled = false + ba, err := NewBatcher(cfg, + func(ctx context.Context, req internal.Request) error { return req.Export(ctx) }, + tt.maxWorkers) + require.NoError(t, err) + q := exporterqueue.NewMemoryQueueFactory[internal.Request]()( context.Background(), exporterqueue.Settings{ Signal: pipeline.SignalTraces, ExporterSettings: exportertest.NewNopSettings(), }, - exporterqueue.NewDefaultConfig()) - - ba, err := NewBatcher(cfg, q, - func(ctx context.Context, req internal.Request) error { return req.Export(ctx) }, - tt.maxWorkers) - require.NoError(t, err) + exporterqueue.NewDefaultConfig(), + ba.Consume) require.NoError(t, q.Start(context.Background(), componenttest.NewNopHost())) require.NoError(t, ba.Start(context.Background(), componenttest.NewNopHost())) diff --git a/exporter/internal/requesttest/fake_request.go b/exporter/internal/requesttest/fake_request.go index 2219c0014a20..864533f2ef17 100644 --- a/exporter/internal/requesttest/fake_request.go +++ b/exporter/internal/requesttest/fake_request.go @@ -5,11 +5,16 @@ package requesttest // import "go.opentelemetry.io/collector/exporter/internal/r import ( "context" + "errors" + "fmt" "sync/atomic" "time" "go.opentelemetry.io/collector/exporter/exporterbatcher" "go.opentelemetry.io/collector/exporter/internal" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" ) type Sink struct { @@ -36,10 +41,19 @@ func NewSink() *Sink { } } +type errorPartial struct { + fr *FakeRequest +} + +func (e errorPartial) Error() string { + return fmt.Sprintf("items: %d", e.fr.Items) +} + type FakeRequest struct { Items int Sink *Sink ExportErr error + Partial int MergeErr error Delay time.Duration } @@ -51,7 +65,23 @@ func (r *FakeRequest) Export(ctx context.Context) error { case <-time.After(r.Delay): } if r.ExportErr != nil { - return r.ExportErr + err := r.ExportErr + r.ExportErr = nil + return err + } + if r.Partial > 0 { + if r.Sink != nil { + r.Sink.requestsCount.Add(1) + r.Sink.itemsCount.Add(int64(r.Items - r.Partial)) + } + return errorPartial{fr: &FakeRequest{ + Items: r.Partial, + Sink: r.Sink, + ExportErr: r.ExportErr, + Partial: 0, + MergeErr: r.MergeErr, + Delay: r.Delay, + }} } if r.Sink != nil { r.Sink.requestsCount.Add(1) @@ -60,6 +90,14 @@ func (r *FakeRequest) Export(ctx context.Context) error { return nil } +func (r *FakeRequest) OnError(err error) internal.Request { + var pErr errorPartial + if errors.As(err, &pErr) { + return pErr.fr + } + return r +} + func (r *FakeRequest) ItemsCount() int { return r.Items } @@ -128,3 +166,21 @@ func (r *FakeRequest) MergeSplit(_ context.Context, cfg exporterbatcher.MaxSizeC return res, nil } + +func RequestFromMetricsFunc(reqErr error) func(context.Context, pmetric.Metrics) (internal.Request, error) { + return func(_ context.Context, md pmetric.Metrics) (internal.Request, error) { + return &FakeRequest{Items: md.DataPointCount(), ExportErr: reqErr}, nil + } +} + +func RequestFromTracesFunc(reqErr error) func(context.Context, ptrace.Traces) (internal.Request, error) { + return func(_ context.Context, td ptrace.Traces) (internal.Request, error) { + return &FakeRequest{Items: td.SpanCount(), ExportErr: reqErr}, nil + } +} + +func RequestFromLogsFunc(reqErr error) func(context.Context, plog.Logs) (internal.Request, error) { + return func(_ context.Context, ld plog.Logs) (internal.Request, error) { + return &FakeRequest{Items: ld.LogRecordCount(), ExportErr: reqErr}, nil + } +} diff --git a/exporter/nopexporter/go.mod b/exporter/nopexporter/go.mod index e0210f92733c..7b111738b564 100644 --- a/exporter/nopexporter/go.mod +++ b/exporter/nopexporter/go.mod @@ -51,9 +51,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/exporter/nopexporter/go.sum b/exporter/nopexporter/go.sum index e50ba545ebed..47db8db1b392 100644 --- a/exporter/nopexporter/go.sum +++ b/exporter/nopexporter/go.sum @@ -103,12 +103,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/exporter/otlpexporter/go.mod b/exporter/otlpexporter/go.mod index a14adc4382d2..30cd9bd16437 100644 --- a/exporter/otlpexporter/go.mod +++ b/exporter/otlpexporter/go.mod @@ -26,8 +26,8 @@ require ( go.uber.org/goleak v1.3.0 go.uber.org/zap v1.27.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f - google.golang.org/grpc v1.69.4 - google.golang.org/protobuf v1.36.3 + google.golang.org/grpc v1.70.0 + google.golang.org/protobuf v1.36.4 ) require ( diff --git a/exporter/otlpexporter/go.sum b/exporter/otlpexporter/go.sum index e24b90a99e81..c11f1c8454f3 100644 --- a/exporter/otlpexporter/go.sum +++ b/exporter/otlpexporter/go.sum @@ -115,10 +115,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/exporter/otlphttpexporter/go.mod b/exporter/otlphttpexporter/go.mod index 7a4de9d1a4b1..c293568c0507 100644 --- a/exporter/otlphttpexporter/go.mod +++ b/exporter/otlphttpexporter/go.mod @@ -23,9 +23,9 @@ require ( go.opentelemetry.io/collector/pdata/pprofile v0.118.0 go.uber.org/goleak v1.3.0 go.uber.org/zap v1.27.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 - google.golang.org/grpc v1.69.4 - google.golang.org/protobuf v1.36.3 + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a + google.golang.org/grpc v1.70.0 + google.golang.org/protobuf v1.36.4 ) require ( diff --git a/exporter/otlphttpexporter/go.sum b/exporter/otlphttpexporter/go.sum index 701555046235..8297a8a23c16 100644 --- a/exporter/otlphttpexporter/go.sum +++ b/exporter/otlphttpexporter/go.sum @@ -117,12 +117,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/exporter/xexporter/go.mod b/exporter/xexporter/go.mod index c0939d5ab991..0d0964e5f510 100644 --- a/exporter/xexporter/go.mod +++ b/exporter/xexporter/go.mod @@ -30,9 +30,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/exporter/xexporter/go.sum b/exporter/xexporter/go.sum index 2037f2362e72..19674bfc86ed 100644 --- a/exporter/xexporter/go.sum +++ b/exporter/xexporter/go.sum @@ -86,12 +86,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/extension/auth/authtest/go.mod b/extension/auth/authtest/go.mod index 809aa0e41047..ae47845de49d 100644 --- a/extension/auth/authtest/go.mod +++ b/extension/auth/authtest/go.mod @@ -7,7 +7,7 @@ require ( go.opentelemetry.io/collector/component v0.118.0 go.opentelemetry.io/collector/extension/auth v0.118.0 go.uber.org/goleak v1.3.0 - google.golang.org/grpc v1.69.4 + google.golang.org/grpc v1.70.0 ) require ( @@ -25,8 +25,8 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/extension/auth/authtest/go.sum b/extension/auth/authtest/go.sum index e7b3f1f53225..ac84fbc4cf94 100644 --- a/extension/auth/authtest/go.sum +++ b/extension/auth/authtest/go.sum @@ -75,12 +75,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/extension/auth/go.mod b/extension/auth/go.mod index 1a81d2eba31c..882d3af937e1 100644 --- a/extension/auth/go.mod +++ b/extension/auth/go.mod @@ -8,7 +8,7 @@ require ( go.opentelemetry.io/collector/component/componenttest v0.118.0 go.opentelemetry.io/collector/extension v0.118.0 go.uber.org/goleak v1.3.0 - google.golang.org/grpc v1.69.4 + google.golang.org/grpc v1.70.0 ) require ( @@ -31,8 +31,8 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/extension/auth/go.sum b/extension/auth/go.sum index ab41a28dad03..889137715630 100644 --- a/extension/auth/go.sum +++ b/extension/auth/go.sum @@ -76,12 +76,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/extension/extension.go b/extension/extension.go index 5bc630a9e4da..41c5a76000f1 100644 --- a/extension/extension.go +++ b/extension/extension.go @@ -13,7 +13,9 @@ import ( // Extension is the interface for objects hosted by the OpenTelemetry Collector that // don't participate directly on data pipelines but provide some functionality // to the service, examples: health check endpoint, z-pages, etc. -type Extension = component.Component +type Extension interface { + component.Component +} // ModuleInfo describes the go module for each component. type ModuleInfo struct { diff --git a/extension/extensioncapabilities/go.mod b/extension/extensioncapabilities/go.mod index 34548860ead6..3caf86eed163 100644 --- a/extension/extensioncapabilities/go.mod +++ b/extension/extensioncapabilities/go.mod @@ -26,9 +26,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/extension/extensioncapabilities/go.sum b/extension/extensioncapabilities/go.sum index 42ac6fdf08d8..fd1e0ed46d6a 100644 --- a/extension/extensioncapabilities/go.sum +++ b/extension/extensioncapabilities/go.sum @@ -44,10 +44,10 @@ go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -87,12 +87,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/extension/extensiontest/go.mod b/extension/extensiontest/go.mod index 972100adbd60..94437c661ba3 100644 --- a/extension/extensiontest/go.mod +++ b/extension/extensiontest/go.mod @@ -31,9 +31,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/extension/extensiontest/go.sum b/extension/extensiontest/go.sum index ab41a28dad03..889137715630 100644 --- a/extension/extensiontest/go.sum +++ b/extension/extensiontest/go.sum @@ -76,12 +76,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/extension/go.mod b/extension/go.mod index 3eea2050d8f5..0d9bafa3fa5b 100644 --- a/extension/go.mod +++ b/extension/go.mod @@ -22,9 +22,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/extension/go.sum b/extension/go.sum index a7bf2c27469f..68c5d74f9162 100644 --- a/extension/go.sum +++ b/extension/go.sum @@ -32,10 +32,10 @@ go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -75,12 +75,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/extension/memorylimiterextension/go.mod b/extension/memorylimiterextension/go.mod index 1033f266a201..6c88aed16ee3 100644 --- a/extension/memorylimiterextension/go.mod +++ b/extension/memorylimiterextension/go.mod @@ -47,9 +47,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/extension/memorylimiterextension/go.sum b/extension/memorylimiterextension/go.sum index 763122bb9a07..404e6d09a908 100644 --- a/extension/memorylimiterextension/go.sum +++ b/extension/memorylimiterextension/go.sum @@ -109,12 +109,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/extension/xextension/go.mod b/extension/xextension/go.mod index 6e7e299d9186..39ffbbaaf4bd 100644 --- a/extension/xextension/go.mod +++ b/extension/xextension/go.mod @@ -19,9 +19,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect ) replace go.opentelemetry.io/collector/extension => ../ diff --git a/extension/xextension/go.sum b/extension/xextension/go.sum index 5755d8809c77..0921e31e9397 100644 --- a/extension/xextension/go.sum +++ b/extension/xextension/go.sum @@ -26,10 +26,10 @@ go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -69,11 +69,11 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/extension/zpagesextension/go.mod b/extension/zpagesextension/go.mod index ba360d477200..65f0d0f38465 100644 --- a/extension/zpagesextension/go.mod +++ b/extension/zpagesextension/go.mod @@ -56,9 +56,9 @@ require ( golang.org/x/net v0.34.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/extension/zpagesextension/go.sum b/extension/zpagesextension/go.sum index 1f399894284b..b8b14b7439a7 100644 --- a/extension/zpagesextension/go.sum +++ b/extension/zpagesextension/go.sum @@ -110,12 +110,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/go.mod b/go.mod index a227981aa361..b729ce52eaf7 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ go 1.22.0 require ( github.com/stretchr/testify v1.10.0 go.uber.org/goleak v1.3.0 - google.golang.org/grpc v1.69.4 + google.golang.org/grpc v1.70.0 ) require ( @@ -21,9 +21,9 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - golang.org/x/sys v0.26.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/protobuf v1.35.1 // indirect + golang.org/x/sys v0.28.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/protobuf v1.35.2 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 90560d8ede14..11838a8a59ca 100644 --- a/go.sum +++ b/go.sum @@ -22,18 +22,18 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/e2e/go.mod b/internal/e2e/go.mod index 57cff5b6aecc..b7120b059c8f 100644 --- a/internal/e2e/go.mod +++ b/internal/e2e/go.mod @@ -102,25 +102,26 @@ require ( go.opentelemetry.io/collector/receiver/xreceiver v0.118.0 // indirect go.opentelemetry.io/collector/semconv v0.118.0 // indirect go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 // indirect - go.opentelemetry.io/contrib/config v0.10.0 // indirect + go.opentelemetry.io/contrib/config v0.14.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.34.0 // indirect go.opentelemetry.io/otel v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect go.opentelemetry.io/otel/exporters/prometheus v0.56.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 // indirect go.opentelemetry.io/otel/log v0.10.0 // indirect go.opentelemetry.io/otel/metric v1.34.0 // indirect go.opentelemetry.io/otel/sdk v1.34.0 // indirect - go.opentelemetry.io/otel/sdk/log v0.7.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.10.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect go.opentelemetry.io/otel/trace v1.34.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect @@ -131,8 +132,8 @@ require ( gonum.org/v1/gonum v0.15.1 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/internal/e2e/go.sum b/internal/e2e/go.sum index f8a516e44366..d3bfe583c97b 100644 --- a/internal/e2e/go.sum +++ b/internal/e2e/go.sum @@ -107,8 +107,8 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 h1:f+xpAfhQTjR8beiSMe1bnT/25PkeyWmOcI+SjXWguNw= go.opentelemetry.io/contrib/bridges/otelzap v0.9.0/go.mod h1:T1Z1jyS5FttgQoF6UcGhnM+gF9wU32B4lHO69nXw4FE= -go.opentelemetry.io/contrib/config v0.10.0 h1:2JknAzMaYjxrHkTnZh3eOme/Y2P5eHE2SWfhfV6Xd6c= -go.opentelemetry.io/contrib/config v0.10.0/go.mod h1:aND2M6/KfNkntI5cyvHriR/zvZgPf8j9yETdSmvpfmc= +go.opentelemetry.io/contrib/config v0.14.0 h1:QAG8uHNp5ZiCkpT7XggSmg5AyW1sA0LgypMoXgBB1+4= +go.opentelemetry.io/contrib/config v0.14.0/go.mod h1:77rDmFPqBae5jtQ2C78RuDTHz4P27C8LzoN0MZyumYQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= @@ -119,34 +119,36 @@ go.opentelemetry.io/contrib/zpages v0.59.0 h1:t0H5zUy8fifIhRuVwm2FrA/D70Kk10SSpA go.opentelemetry.io/contrib/zpages v0.59.0/go.mod h1:9wo+yUPvHnBQEzoHJ8R3nA/Q5rkef7HjtLlSFI0Tgrc= go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 h1:mMOmtYie9Fx6TSVzw4W+NTpvoaS1JWWga37oI1a/4qQ= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0/go.mod h1:yy7nDsMMBUkD+jeekJ36ur5f3jJIrmCwUrY67VFhNpA= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 h1:5dTKu4I5Dn4P2hxyW3l3jTaZx9ACgg0ECos1eAVrheY= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0/go.mod h1:P5HcUI8obLrCCmM3sbVBohZFH34iszk/+CPWuakZWL8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 h1:q/heq5Zh8xV1+7GoMGJpTxM2Lhq5+bFxB29tshuRuw0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0/go.mod h1:leO2CSTg0Y+LyvmR7Wm4pUxE8KAmaM2GCVx7O+RATLA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 h1:ajl4QczuJVA2TU9W9AGw++86Xga/RKt//16z/yxPgdk= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0/go.mod h1:Vn3/rlOJ3ntf/Q3zAI0V5lDnTbHGaUsNUeF6nZmm7pA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 h1:opwv08VbCZ8iecIWs+McMdHRcAXzjAeda3uG2kI/hcA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0/go.mod h1:oOP3ABpW7vFHulLpE8aYtNBodrHhMTrvfxUXGvqm7Ac= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4= go.opentelemetry.io/otel/exporters/prometheus v0.56.0 h1:GnCIi0QyG0yy2MrJLzVrIM7laaJstj//flf1zEJCG+E= go.opentelemetry.io/otel/exporters/prometheus v0.56.0/go.mod h1:JQcVZtbIIPM+7SWBB+T6FK+xunlyidwLp++fN0sUaOk= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0 h1:TwmL3O3fRR80m8EshBrd8YydEZMcUCsZXzOUlnFohwM= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0/go.mod h1:tH98dDv5KPmPThswbXA0fr0Lwfs+OhK8HgaCo7PjRrk= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 h1:GKCEAZLEpEf78cUvudQdTg0aET2ObOZRB2HtXA0qPAI= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0/go.mod h1:9/zqSWLCmHT/9Jo6fYeUDRRogOLL60ABLsHWS99lF8s= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 h1:czJDQwFrMbOr9Kk+BPo1y8WZIIFIK58SA1kykuVeiOU= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0/go.mod h1:lT7bmsxOe58Tq+JIOkTQMCGXdu47oA+VJKLZHbaBKbs= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 h1:UGZ1QwZWY67Z6BmckTU+9Rxn04m2bD3gD6Mk0OIOCPk= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0/go.mod h1:fcwWuDuaObkkChiDlhEpSq9+X1C0omv+s5mBtToAQ64= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 h1:jBpDk4HAUsrnVO1FsfCfCOTEc/MkInJmvfCHYLFiT80= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0/go.mod h1:H9LUIM1daaeZaz91vZcfeM0fejXPmgCYE8ZhzqfJuiU= go.opentelemetry.io/otel/log v0.10.0 h1:1CXmspaRITvFcjA4kyVszuG4HjA61fPDxMb7q3BuyF0= go.opentelemetry.io/otel/log v0.10.0/go.mod h1:PbVdm9bXKku/gL0oFfUF4wwsQsOPlpo4VEqjvxih+FM= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/sdk/log v0.7.0 h1:dXkeI2S0MLc5g0/AwxTZv6EUEjctiH8aG14Am56NTmQ= -go.opentelemetry.io/otel/sdk/log v0.7.0/go.mod h1:oIRXpW+WD6M8BuGj5rtS0aRu/86cbDV/dAfNaZBIjYM= +go.opentelemetry.io/otel/sdk/log v0.10.0 h1:lR4teQGWfeDVGoute6l0Ou+RpFqQ9vaPdrNJlST0bvw= +go.opentelemetry.io/otel/sdk/log v0.10.0/go.mod h1:A+V1UTWREhWAittaQEG4bYm4gAZa6xnvVu+xKrIRkzo= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= @@ -202,10 +204,10 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1: google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/fanoutconsumer/go.mod b/internal/fanoutconsumer/go.mod index 7b03ccf922b8..1127e157f83e 100644 --- a/internal/fanoutconsumer/go.mod +++ b/internal/fanoutconsumer/go.mod @@ -24,9 +24,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/internal/fanoutconsumer/go.sum b/internal/fanoutconsumer/go.sum index a325492a9929..edc81fe738b9 100644 --- a/internal/fanoutconsumer/go.sum +++ b/internal/fanoutconsumer/go.sum @@ -37,16 +37,16 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -82,12 +82,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/memorylimiter/go.mod b/internal/memorylimiter/go.mod index 341946d8fab8..b0afafbfcb20 100644 --- a/internal/memorylimiter/go.mod +++ b/internal/memorylimiter/go.mod @@ -37,9 +37,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/internal/memorylimiter/go.sum b/internal/memorylimiter/go.sum index 098276cc4f99..471d39c37f1a 100644 --- a/internal/memorylimiter/go.sum +++ b/internal/memorylimiter/go.sum @@ -61,10 +61,10 @@ go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -108,12 +108,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/sharedcomponent/go.mod b/internal/sharedcomponent/go.mod index 5dbfd25e041b..3dfde3e723e3 100644 --- a/internal/sharedcomponent/go.mod +++ b/internal/sharedcomponent/go.mod @@ -31,9 +31,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/internal/sharedcomponent/go.sum b/internal/sharedcomponent/go.sum index ab41a28dad03..889137715630 100644 --- a/internal/sharedcomponent/go.sum +++ b/internal/sharedcomponent/go.sum @@ -76,12 +76,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/tools/go.mod b/internal/tools/go.mod index dfb00ac1b82f..b8de37269883 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -11,11 +11,11 @@ require ( github.com/google/addlicense v1.1.1 github.com/jcchavezs/porto v0.7.0 github.com/pavius/impi v0.0.3 - go.opentelemetry.io/build-tools/checkfile v0.16.0 - go.opentelemetry.io/build-tools/chloggen v0.16.0 - go.opentelemetry.io/build-tools/crosslink v0.16.0 - go.opentelemetry.io/build-tools/multimod v0.16.0 - go.opentelemetry.io/build-tools/semconvgen v0.16.0 + go.opentelemetry.io/build-tools/checkfile v0.17.0 + go.opentelemetry.io/build-tools/chloggen v0.17.0 + go.opentelemetry.io/build-tools/crosslink v0.17.0 + go.opentelemetry.io/build-tools/multimod v0.17.0 + go.opentelemetry.io/build-tools/semconvgen v0.17.0 golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 golang.org/x/tools v0.29.0 golang.org/x/vuln v1.1.4 @@ -213,7 +213,7 @@ require ( gitlab.com/bosi/decorder v0.4.2 // indirect go-simpler.org/musttag v0.13.0 // indirect go-simpler.org/sloglint v0.7.2 // indirect - go.opentelemetry.io/build-tools v0.16.0 // indirect + go.opentelemetry.io/build-tools v0.17.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect diff --git a/internal/tools/go.sum b/internal/tools/go.sum index 5e877290ce18..de48b5887cbc 100644 --- a/internal/tools/go.sum +++ b/internal/tools/go.sum @@ -334,12 +334,14 @@ github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5co github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= -github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= -github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= +github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8= +github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs= +github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= github.com/pavius/impi v0.0.3 h1:DND6MzU+BLABhOZXbELR3FU8b+zDgcq4dOCNLhiTYuI= github.com/pavius/impi v0.0.3/go.mod h1:x/hU0bfdWIhuOT1SKwiJg++yvkk6EuOtJk8WtDZqgr8= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= @@ -500,18 +502,18 @@ go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= go-simpler.org/sloglint v0.7.2 h1:Wc9Em/Zeuu7JYpl+oKoYOsQSy2X560aVueCW/m6IijY= go-simpler.org/sloglint v0.7.2/go.mod h1:US+9C80ppl7VsThQclkM7BkCHQAzuz8kHLsW3ppuluo= -go.opentelemetry.io/build-tools v0.16.0 h1:KxKRH+jOSNbRDRESkibfpaKmaVb1GsXhf0pQfPZE5zI= -go.opentelemetry.io/build-tools v0.16.0/go.mod h1:ZhuNyO/aAkGEFTfNhH7Nhv7fIWpxIOp8t7XshpPWiOU= -go.opentelemetry.io/build-tools/checkfile v0.16.0 h1:mPtin68T3sE8C6PpVoS7XDTku+RW5PiFtxN25dYKbLA= -go.opentelemetry.io/build-tools/checkfile v0.16.0/go.mod h1:hfIirAs3HMoLBhOkruPiz0HCKDGMlRW12nOMkQ0hrOI= -go.opentelemetry.io/build-tools/chloggen v0.16.0 h1:iuotHxlcK46JJtQLdwQPsC5dcAygeOL116d2akCv8M8= -go.opentelemetry.io/build-tools/chloggen v0.16.0/go.mod h1:Wk92v9Wsv36sXYi7hOg3ndeeLKmKBu0/kgB7wcaeqJg= -go.opentelemetry.io/build-tools/crosslink v0.16.0 h1:7Y5QPt5TR3qpiW5bwIOnsCJdt1yjZSFDPKtjt2g2zHw= -go.opentelemetry.io/build-tools/crosslink v0.16.0/go.mod h1:xogE6iWmt53bsDazb81dQrZw9TQ30+9hc4D8QfVG9aA= -go.opentelemetry.io/build-tools/multimod v0.16.0 h1:o205mGH61VXebXeiIPXwxeHRCm332TZqRb8gmypI6po= -go.opentelemetry.io/build-tools/multimod v0.16.0/go.mod h1:dDZzMmgPYCVJOHbWDZP29DH/aLFiKdPclisVLylTIH0= -go.opentelemetry.io/build-tools/semconvgen v0.16.0 h1:6ow53MkS63h99CqXPlXOZ3XhFsg8t2dqclwRdEKGHM4= -go.opentelemetry.io/build-tools/semconvgen v0.16.0/go.mod h1:gqVlv0wP6WmnqEcxKgTTNdblgxWJojmr+jvGTRZ0DcE= +go.opentelemetry.io/build-tools v0.17.0 h1:mCOZ3YQswjcetUeoMTijn2QPVzwx02Gk1WD200g99lg= +go.opentelemetry.io/build-tools v0.17.0/go.mod h1:ZhuNyO/aAkGEFTfNhH7Nhv7fIWpxIOp8t7XshpPWiOU= +go.opentelemetry.io/build-tools/checkfile v0.17.0 h1:lTlK2Q4KKoC4QIv12UtIN+akgaWlPHB5HVVxgJZ2/xE= +go.opentelemetry.io/build-tools/checkfile v0.17.0/go.mod h1:hfIirAs3HMoLBhOkruPiz0HCKDGMlRW12nOMkQ0hrOI= +go.opentelemetry.io/build-tools/chloggen v0.17.0 h1:aOtA6MW67VoB1HYxcqYIlVxfiBypI/ZTxSb7SU/Jw8g= +go.opentelemetry.io/build-tools/chloggen v0.17.0/go.mod h1:Wk92v9Wsv36sXYi7hOg3ndeeLKmKBu0/kgB7wcaeqJg= +go.opentelemetry.io/build-tools/crosslink v0.17.0 h1:Ivjwh4qp4L+ivRccBOMPIXAVESBMbhbJFEJUGwKsiCM= +go.opentelemetry.io/build-tools/crosslink v0.17.0/go.mod h1:rZRgZZ9uBe2IvR4fJY1kGIWIwiSLm+IvjFsSiPXGq4Q= +go.opentelemetry.io/build-tools/multimod v0.17.0 h1:z0TWbNLcKu1eLx0Pgour/WFA0m+trsRkJ0llM5MsTug= +go.opentelemetry.io/build-tools/multimod v0.17.0/go.mod h1:ImevmVCDyVInTn7L9lN+qVtGs/6cOMQA/Cf3jX1miQA= +go.opentelemetry.io/build-tools/semconvgen v0.17.0 h1:vQk8RJPj9yOCe0cITb+WKMit1Mq9lK72Ws5tuq/KqzU= +go.opentelemetry.io/build-tools/semconvgen v0.17.0/go.mod h1:xkneSVamzk5HpHLB7870NyveeaxpA3Z9BwoMqGxYOBE= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= diff --git a/otelcol/collector.go b/otelcol/collector.go index cbad6f56e47a..a0b191053a15 100644 --- a/otelcol/collector.go +++ b/otelcol/collector.go @@ -171,7 +171,7 @@ func (col *Collector) setupConfigurationComponents(ctx context.Context) error { return fmt.Errorf("failed to get config: %w", err) } - if err = cfg.Validate(); err != nil { + if err = component.ValidateConfig(cfg); err != nil { return fmt.Errorf("invalid configuration: %w", err) } @@ -261,7 +261,7 @@ func (col *Collector) DryRun(ctx context.Context) error { return fmt.Errorf("failed to get config: %w", err) } - return cfg.Validate() + return component.ValidateConfig(cfg) } func newFallbackLogger(options []zap.Option) (*zap.Logger, error) { diff --git a/otelcol/collector_test.go b/otelcol/collector_test.go index 3f0c2f7ceb21..b2b5641b5f9e 100644 --- a/otelcol/collector_test.go +++ b/otelcol/collector_test.go @@ -145,7 +145,7 @@ func NewStatusWatcherExtensionFactory( func() component.Config { return &struct{}{} }, - func(context.Context, extension.Settings, component.Config) (component.Component, error) { + func(context.Context, extension.Settings, component.Config) (extension.Extension, error) { return &statusWatcherExtension{onStatusChanged: onStatusChanged}, nil }, component.StabilityLevelStable) diff --git a/otelcol/config.go b/otelcol/config.go index 339759572828..2bfd863e2f2d 100644 --- a/otelcol/config.go +++ b/otelcol/config.go @@ -54,39 +54,14 @@ func (cfg *Config) Validate() error { return errMissingReceivers } - // Validate the receiver configuration. - for recvID, recvCfg := range cfg.Receivers { - if err := component.ValidateConfig(recvCfg); err != nil { - return fmt.Errorf("receivers::%s: %w", recvID, err) - } - } - // Currently, there is no default exporter enabled. // The configuration must specify at least one exporter to be valid. if len(cfg.Exporters) == 0 { return errMissingExporters } - // Validate the exporter configuration. - for expID, expCfg := range cfg.Exporters { - if err := component.ValidateConfig(expCfg); err != nil { - return fmt.Errorf("exporters::%s: %w", expID, err) - } - } - - // Validate the processor configuration. - for procID, procCfg := range cfg.Processors { - if err := component.ValidateConfig(procCfg); err != nil { - return fmt.Errorf("processors::%s: %w", procID, err) - } - } - // Validate the connector configuration. - for connID, connCfg := range cfg.Connectors { - if err := component.ValidateConfig(connCfg); err != nil { - return fmt.Errorf("connectors::%s: %w", connID, err) - } - + for connID := range cfg.Connectors { if _, ok := cfg.Exporters[connID]; ok { return fmt.Errorf("connectors::%s: ambiguous ID: Found both %q exporter and %q connector. "+ "Change one of the components' IDs to eliminate ambiguity (e.g. rename %q connector to %q)", @@ -99,17 +74,6 @@ func (cfg *Config) Validate() error { } } - // Validate the extension configuration. - for extID, extCfg := range cfg.Extensions { - if err := component.ValidateConfig(extCfg); err != nil { - return fmt.Errorf("extensions::%s: %w", extID, err) - } - } - - if err := cfg.Service.Validate(); err != nil { - return err - } - // Check that all enabled extensions in the service are configured. for _, ref := range cfg.Service.Extensions { // Check that the name referenced in the Service extensions exists in the top-level extensions. diff --git a/otelcol/config_test.go b/otelcol/config_test.go index adcf0eca4c12..e9c766fca0a7 100644 --- a/otelcol/config_test.go +++ b/otelcol/config_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "go.opentelemetry.io/contrib/config" + config "go.opentelemetry.io/contrib/config/v0.3.0" "go.uber.org/zap/zapcore" "go.opentelemetry.io/collector/component" @@ -234,14 +234,19 @@ func TestConfigValidate(t *testing.T) { cfg.Service.Pipelines = nil return cfg }, - expected: fmt.Errorf(`service::pipelines config validation failed: %w`, errors.New(`service must have at least one pipeline`)), + expected: fmt.Errorf(`service::pipelines: %w`, errors.New(`service must have at least one pipeline`)), }, } for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { cfg := tt.cfgFn() - assert.Equal(t, tt.expected, cfg.Validate()) + err := component.ValidateConfig(cfg) + if tt.expected != nil { + assert.EqualError(t, err, tt.expected.Error()) + } else { + assert.NoError(t, err) + } }) } } @@ -279,7 +284,7 @@ func generateConfig() *Config { Level: configtelemetry.LevelNormal, Readers: []config.MetricReader{ { - Pull: &config.PullMetricReader{Exporter: config.MetricExporter{ + Pull: &config.PullMetricReader{Exporter: config.PullMetricExporter{ Prometheus: &config.Prometheus{ Host: newPtr("localhost"), Port: newPtr(8080), diff --git a/otelcol/go.mod b/otelcol/go.mod index 4aa01ec19694..699eed63d9fa 100644 --- a/otelcol/go.mod +++ b/otelcol/go.mod @@ -22,13 +22,13 @@ require ( go.opentelemetry.io/collector/receiver v0.118.0 go.opentelemetry.io/collector/receiver/receivertest v0.118.0 go.opentelemetry.io/collector/service v0.118.0 - go.opentelemetry.io/contrib/config v0.10.0 + go.opentelemetry.io/contrib/config v0.14.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 golang.org/x/sys v0.29.0 - google.golang.org/grpc v1.69.4 + google.golang.org/grpc v1.70.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -38,7 +38,6 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/ebitengine/purego v0.8.1 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect @@ -88,24 +87,23 @@ require ( go.opentelemetry.io/collector/receiver/xreceiver v0.118.0 // indirect go.opentelemetry.io/collector/semconv v0.118.0 // indirect go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.34.0 // indirect go.opentelemetry.io/otel v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect go.opentelemetry.io/otel/exporters/prometheus v0.56.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 // indirect go.opentelemetry.io/otel/log v0.10.0 // indirect go.opentelemetry.io/otel/metric v1.34.0 // indirect go.opentelemetry.io/otel/sdk v1.34.0 // indirect - go.opentelemetry.io/otel/sdk/log v0.7.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.10.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect go.opentelemetry.io/otel/trace v1.34.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect @@ -114,7 +112,7 @@ require ( gonum.org/v1/gonum v0.15.1 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/protobuf v1.36.4 // indirect ) replace go.opentelemetry.io/collector => ../ diff --git a/otelcol/go.sum b/otelcol/go.sum index a8e4a21bc28c..696da84f942b 100644 --- a/otelcol/go.sum +++ b/otelcol/go.sum @@ -113,10 +113,8 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 h1:f+xpAfhQTjR8beiSMe1bnT/25PkeyWmOcI+SjXWguNw= go.opentelemetry.io/contrib/bridges/otelzap v0.9.0/go.mod h1:T1Z1jyS5FttgQoF6UcGhnM+gF9wU32B4lHO69nXw4FE= -go.opentelemetry.io/contrib/config v0.10.0 h1:2JknAzMaYjxrHkTnZh3eOme/Y2P5eHE2SWfhfV6Xd6c= -go.opentelemetry.io/contrib/config v0.10.0/go.mod h1:aND2M6/KfNkntI5cyvHriR/zvZgPf8j9yETdSmvpfmc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= +go.opentelemetry.io/contrib/config v0.14.0 h1:QAG8uHNp5ZiCkpT7XggSmg5AyW1sA0LgypMoXgBB1+4= +go.opentelemetry.io/contrib/config v0.14.0/go.mod h1:77rDmFPqBae5jtQ2C78RuDTHz4P27C8LzoN0MZyumYQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= go.opentelemetry.io/contrib/propagators/b3 v1.34.0 h1:9pQdCEvV/6RWQmag94D6rhU+A4rzUhYBEJ8bpscx5p8= @@ -125,34 +123,36 @@ go.opentelemetry.io/contrib/zpages v0.59.0 h1:t0H5zUy8fifIhRuVwm2FrA/D70Kk10SSpA go.opentelemetry.io/contrib/zpages v0.59.0/go.mod h1:9wo+yUPvHnBQEzoHJ8R3nA/Q5rkef7HjtLlSFI0Tgrc= go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 h1:mMOmtYie9Fx6TSVzw4W+NTpvoaS1JWWga37oI1a/4qQ= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0/go.mod h1:yy7nDsMMBUkD+jeekJ36ur5f3jJIrmCwUrY67VFhNpA= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 h1:5dTKu4I5Dn4P2hxyW3l3jTaZx9ACgg0ECos1eAVrheY= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0/go.mod h1:P5HcUI8obLrCCmM3sbVBohZFH34iszk/+CPWuakZWL8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 h1:q/heq5Zh8xV1+7GoMGJpTxM2Lhq5+bFxB29tshuRuw0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0/go.mod h1:leO2CSTg0Y+LyvmR7Wm4pUxE8KAmaM2GCVx7O+RATLA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 h1:ajl4QczuJVA2TU9W9AGw++86Xga/RKt//16z/yxPgdk= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0/go.mod h1:Vn3/rlOJ3ntf/Q3zAI0V5lDnTbHGaUsNUeF6nZmm7pA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 h1:opwv08VbCZ8iecIWs+McMdHRcAXzjAeda3uG2kI/hcA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0/go.mod h1:oOP3ABpW7vFHulLpE8aYtNBodrHhMTrvfxUXGvqm7Ac= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4= go.opentelemetry.io/otel/exporters/prometheus v0.56.0 h1:GnCIi0QyG0yy2MrJLzVrIM7laaJstj//flf1zEJCG+E= go.opentelemetry.io/otel/exporters/prometheus v0.56.0/go.mod h1:JQcVZtbIIPM+7SWBB+T6FK+xunlyidwLp++fN0sUaOk= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0 h1:TwmL3O3fRR80m8EshBrd8YydEZMcUCsZXzOUlnFohwM= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0/go.mod h1:tH98dDv5KPmPThswbXA0fr0Lwfs+OhK8HgaCo7PjRrk= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 h1:GKCEAZLEpEf78cUvudQdTg0aET2ObOZRB2HtXA0qPAI= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0/go.mod h1:9/zqSWLCmHT/9Jo6fYeUDRRogOLL60ABLsHWS99lF8s= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 h1:czJDQwFrMbOr9Kk+BPo1y8WZIIFIK58SA1kykuVeiOU= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0/go.mod h1:lT7bmsxOe58Tq+JIOkTQMCGXdu47oA+VJKLZHbaBKbs= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 h1:UGZ1QwZWY67Z6BmckTU+9Rxn04m2bD3gD6Mk0OIOCPk= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0/go.mod h1:fcwWuDuaObkkChiDlhEpSq9+X1C0omv+s5mBtToAQ64= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 h1:jBpDk4HAUsrnVO1FsfCfCOTEc/MkInJmvfCHYLFiT80= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0/go.mod h1:H9LUIM1daaeZaz91vZcfeM0fejXPmgCYE8ZhzqfJuiU= go.opentelemetry.io/otel/log v0.10.0 h1:1CXmspaRITvFcjA4kyVszuG4HjA61fPDxMb7q3BuyF0= go.opentelemetry.io/otel/log v0.10.0/go.mod h1:PbVdm9bXKku/gL0oFfUF4wwsQsOPlpo4VEqjvxih+FM= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/sdk/log v0.7.0 h1:dXkeI2S0MLc5g0/AwxTZv6EUEjctiH8aG14Am56NTmQ= -go.opentelemetry.io/otel/sdk/log v0.7.0/go.mod h1:oIRXpW+WD6M8BuGj5rtS0aRu/86cbDV/dAfNaZBIjYM= +go.opentelemetry.io/otel/sdk/log v0.10.0 h1:lR4teQGWfeDVGoute6l0Ou+RpFqQ9vaPdrNJlST0bvw= +go.opentelemetry.io/otel/sdk/log v0.10.0/go.mod h1:A+V1UTWREhWAittaQEG4bYm4gAZa6xnvVu+xKrIRkzo= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= @@ -208,10 +208,10 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1: google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/otelcol/otelcoltest/config.go b/otelcol/otelcoltest/config.go index 9b7e7a0c60dc..8e414829266e 100644 --- a/otelcol/otelcoltest/config.go +++ b/otelcol/otelcoltest/config.go @@ -6,6 +6,7 @@ package otelcoltest // import "go.opentelemetry.io/collector/otelcol/otelcoltest import ( "context" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/confmap" "go.opentelemetry.io/collector/confmap/provider/envprovider" "go.opentelemetry.io/collector/confmap/provider/fileprovider" @@ -40,5 +41,5 @@ func LoadConfigAndValidate(fileName string, factories otelcol.Factories) (*otelc if err != nil { return nil, err } - return cfg, cfg.Validate() + return cfg, component.ValidateConfig(cfg) } diff --git a/otelcol/otelcoltest/go.mod b/otelcol/otelcoltest/go.mod index 2cf6e5f68416..3e6d08f8ea7e 100644 --- a/otelcol/otelcoltest/go.mod +++ b/otelcol/otelcoltest/go.mod @@ -32,7 +32,6 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/ebitengine/purego v0.8.1 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect @@ -86,25 +85,24 @@ require ( go.opentelemetry.io/collector/receiver/xreceiver v0.118.0 // indirect go.opentelemetry.io/collector/semconv v0.118.0 // indirect go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 // indirect - go.opentelemetry.io/contrib/config v0.10.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect + go.opentelemetry.io/contrib/config v0.14.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.34.0 // indirect go.opentelemetry.io/otel v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect go.opentelemetry.io/otel/exporters/prometheus v0.56.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 // indirect go.opentelemetry.io/otel/log v0.10.0 // indirect go.opentelemetry.io/otel/metric v1.34.0 // indirect go.opentelemetry.io/otel/sdk v1.34.0 // indirect - go.opentelemetry.io/otel/sdk/log v0.7.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.10.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect go.opentelemetry.io/otel/trace v1.34.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect @@ -117,8 +115,8 @@ require ( gonum.org/v1/gonum v0.15.1 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -138,12 +136,6 @@ replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/con replace go.opentelemetry.io/collector/processor => ../../processor -replace go.opentelemetry.io/collector/processor/processortest => ../../processor/processortest - -replace go.opentelemetry.io/collector/confmap => ../../confmap - -replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata - replace go.opentelemetry.io/collector/pdata => ../../pdata replace go.opentelemetry.io/collector/pdata/pprofile => ../../pdata/pprofile @@ -221,3 +213,9 @@ replace go.opentelemetry.io/collector/extension/extensiontest => ../../extension replace go.opentelemetry.io/collector/extension/auth/authtest => ../../extension/auth/authtest replace go.opentelemetry.io/collector/extension/xextension => ../../extension/xextension + +replace go.opentelemetry.io/collector/confmap => ../../confmap + +replace go.opentelemetry.io/collector/processor/processortest => ../../processor/processortest + +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata diff --git a/otelcol/otelcoltest/go.sum b/otelcol/otelcoltest/go.sum index a8e4a21bc28c..696da84f942b 100644 --- a/otelcol/otelcoltest/go.sum +++ b/otelcol/otelcoltest/go.sum @@ -113,10 +113,8 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 h1:f+xpAfhQTjR8beiSMe1bnT/25PkeyWmOcI+SjXWguNw= go.opentelemetry.io/contrib/bridges/otelzap v0.9.0/go.mod h1:T1Z1jyS5FttgQoF6UcGhnM+gF9wU32B4lHO69nXw4FE= -go.opentelemetry.io/contrib/config v0.10.0 h1:2JknAzMaYjxrHkTnZh3eOme/Y2P5eHE2SWfhfV6Xd6c= -go.opentelemetry.io/contrib/config v0.10.0/go.mod h1:aND2M6/KfNkntI5cyvHriR/zvZgPf8j9yETdSmvpfmc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= +go.opentelemetry.io/contrib/config v0.14.0 h1:QAG8uHNp5ZiCkpT7XggSmg5AyW1sA0LgypMoXgBB1+4= +go.opentelemetry.io/contrib/config v0.14.0/go.mod h1:77rDmFPqBae5jtQ2C78RuDTHz4P27C8LzoN0MZyumYQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= go.opentelemetry.io/contrib/propagators/b3 v1.34.0 h1:9pQdCEvV/6RWQmag94D6rhU+A4rzUhYBEJ8bpscx5p8= @@ -125,34 +123,36 @@ go.opentelemetry.io/contrib/zpages v0.59.0 h1:t0H5zUy8fifIhRuVwm2FrA/D70Kk10SSpA go.opentelemetry.io/contrib/zpages v0.59.0/go.mod h1:9wo+yUPvHnBQEzoHJ8R3nA/Q5rkef7HjtLlSFI0Tgrc= go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 h1:mMOmtYie9Fx6TSVzw4W+NTpvoaS1JWWga37oI1a/4qQ= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0/go.mod h1:yy7nDsMMBUkD+jeekJ36ur5f3jJIrmCwUrY67VFhNpA= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 h1:5dTKu4I5Dn4P2hxyW3l3jTaZx9ACgg0ECos1eAVrheY= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0/go.mod h1:P5HcUI8obLrCCmM3sbVBohZFH34iszk/+CPWuakZWL8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 h1:q/heq5Zh8xV1+7GoMGJpTxM2Lhq5+bFxB29tshuRuw0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0/go.mod h1:leO2CSTg0Y+LyvmR7Wm4pUxE8KAmaM2GCVx7O+RATLA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 h1:ajl4QczuJVA2TU9W9AGw++86Xga/RKt//16z/yxPgdk= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0/go.mod h1:Vn3/rlOJ3ntf/Q3zAI0V5lDnTbHGaUsNUeF6nZmm7pA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 h1:opwv08VbCZ8iecIWs+McMdHRcAXzjAeda3uG2kI/hcA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0/go.mod h1:oOP3ABpW7vFHulLpE8aYtNBodrHhMTrvfxUXGvqm7Ac= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4= go.opentelemetry.io/otel/exporters/prometheus v0.56.0 h1:GnCIi0QyG0yy2MrJLzVrIM7laaJstj//flf1zEJCG+E= go.opentelemetry.io/otel/exporters/prometheus v0.56.0/go.mod h1:JQcVZtbIIPM+7SWBB+T6FK+xunlyidwLp++fN0sUaOk= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0 h1:TwmL3O3fRR80m8EshBrd8YydEZMcUCsZXzOUlnFohwM= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0/go.mod h1:tH98dDv5KPmPThswbXA0fr0Lwfs+OhK8HgaCo7PjRrk= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 h1:GKCEAZLEpEf78cUvudQdTg0aET2ObOZRB2HtXA0qPAI= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0/go.mod h1:9/zqSWLCmHT/9Jo6fYeUDRRogOLL60ABLsHWS99lF8s= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 h1:czJDQwFrMbOr9Kk+BPo1y8WZIIFIK58SA1kykuVeiOU= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0/go.mod h1:lT7bmsxOe58Tq+JIOkTQMCGXdu47oA+VJKLZHbaBKbs= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 h1:UGZ1QwZWY67Z6BmckTU+9Rxn04m2bD3gD6Mk0OIOCPk= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0/go.mod h1:fcwWuDuaObkkChiDlhEpSq9+X1C0omv+s5mBtToAQ64= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 h1:jBpDk4HAUsrnVO1FsfCfCOTEc/MkInJmvfCHYLFiT80= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0/go.mod h1:H9LUIM1daaeZaz91vZcfeM0fejXPmgCYE8ZhzqfJuiU= go.opentelemetry.io/otel/log v0.10.0 h1:1CXmspaRITvFcjA4kyVszuG4HjA61fPDxMb7q3BuyF0= go.opentelemetry.io/otel/log v0.10.0/go.mod h1:PbVdm9bXKku/gL0oFfUF4wwsQsOPlpo4VEqjvxih+FM= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/sdk/log v0.7.0 h1:dXkeI2S0MLc5g0/AwxTZv6EUEjctiH8aG14Am56NTmQ= -go.opentelemetry.io/otel/sdk/log v0.7.0/go.mod h1:oIRXpW+WD6M8BuGj5rtS0aRu/86cbDV/dAfNaZBIjYM= +go.opentelemetry.io/otel/sdk/log v0.10.0 h1:lR4teQGWfeDVGoute6l0Ou+RpFqQ9vaPdrNJlST0bvw= +go.opentelemetry.io/otel/sdk/log v0.10.0/go.mod h1:A+V1UTWREhWAittaQEG4bYm4gAZa6xnvVu+xKrIRkzo= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= @@ -208,10 +208,10 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1: google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/otelcol/testdata/otelcol-emptyreaders.yaml b/otelcol/testdata/otelcol-emptyreaders.yaml index 3a71b541f1a0..f8f78dc7ba6a 100644 --- a/otelcol/testdata/otelcol-emptyreaders.yaml +++ b/otelcol/testdata/otelcol-emptyreaders.yaml @@ -7,6 +7,7 @@ exporters: service: telemetry: metrics: + level: none readers: [] pipelines: metrics: diff --git a/otelcol/unmarshaler_test.go b/otelcol/unmarshaler_test.go index 7e0e34ac5bad..8849235d30a5 100644 --- a/otelcol/unmarshaler_test.go +++ b/otelcol/unmarshaler_test.go @@ -157,7 +157,7 @@ func TestServiceUnmarshalError(t *testing.T) { }, }, }), - expectError: "error decoding 'telemetry': decoding failed due to the following error(s):\n\nerror decoding 'logs.level': unrecognized level: \"UNKNOWN\"", + expectError: "error decoding 'telemetry': decoding failed due to the following error(s):\n\nerror decoding 'logs': decoding failed due to the following error(s):\n\nerror decoding 'level': unrecognized level: \"UNKNOWN\"", }, { name: "invalid-metrics-level", @@ -168,7 +168,7 @@ func TestServiceUnmarshalError(t *testing.T) { }, }, }), - expectError: "error decoding 'telemetry': decoding failed due to the following error(s):\n\nerror decoding 'metrics.level': unknown metrics level \"unknown\"", + expectError: "error decoding 'telemetry': decoding failed due to the following error(s):\n\nerror decoding 'metrics': decoding failed due to the following error(s):\n\nerror decoding 'level': unknown metrics level \"unknown\"", }, { name: "invalid-service-extensions-section", diff --git a/pdata/go.mod b/pdata/go.mod index 192daa0ecabf..c9d8523a8968 100644 --- a/pdata/go.mod +++ b/pdata/go.mod @@ -8,8 +8,8 @@ require ( github.com/stretchr/testify v1.10.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 - google.golang.org/grpc v1.69.4 - google.golang.org/protobuf v1.36.3 + google.golang.org/grpc v1.70.0 + google.golang.org/protobuf v1.36.4 ) require ( @@ -22,7 +22,7 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/pdata/go.sum b/pdata/go.sum index 8172eac94ad7..dbf9feedf0c2 100644 --- a/pdata/go.sum +++ b/pdata/go.sum @@ -43,16 +43,16 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -88,12 +88,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/pdata/pprofile/attributes.go b/pdata/pprofile/attributes.go new file mode 100644 index 000000000000..beeb002e0797 --- /dev/null +++ b/pdata/pprofile/attributes.go @@ -0,0 +1,28 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package pprofile // import "go.opentelemetry.io/collector/pdata/pprofile" + +import ( + "go.opentelemetry.io/collector/pdata/pcommon" +) + +type attributable interface { + AttributeIndices() pcommon.Int32Slice +} + +// FromAttributeIndices builds a [pcommon.Map] containing the attributes of a +// record. +// The record can by any struct that implements an `AttributeIndices` method. +// Updates made to the return map will not be applied back to the record. +func FromAttributeIndices(table AttributeTableSlice, record attributable) pcommon.Map { + m := pcommon.NewMap() + m.EnsureCapacity(record.AttributeIndices().Len()) + + for i := 0; i < record.AttributeIndices().Len(); i++ { + kv := table.At(int(record.AttributeIndices().At(i))) + kv.Value().CopyTo(m.PutEmpty(kv.Key())) + } + + return m +} diff --git a/pdata/pprofile/attributes_test.go b/pdata/pprofile/attributes_test.go new file mode 100644 index 000000000000..9a198f8e8872 --- /dev/null +++ b/pdata/pprofile/attributes_test.go @@ -0,0 +1,64 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package pprofile + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/pdata/pcommon" +) + +func TestFromAttributeIndices(t *testing.T) { + table := NewAttributeTableSlice() + att := table.AppendEmpty() + att.SetKey("hello") + att.Value().SetStr("world") + att2 := table.AppendEmpty() + att2.SetKey("bonjour") + att2.Value().SetStr("monde") + + attrs := FromAttributeIndices(table, NewProfile()) + assert.Equal(t, attrs, pcommon.NewMap()) + + // A Location with a single attribute + loc := NewLocation() + loc.AttributeIndices().Append(0) + + attrs = FromAttributeIndices(table, loc) + + m := map[string]any{"hello": "world"} + assert.Equal(t, attrs.AsRaw(), m) + + // A Mapping with two attributes + mapp := NewLocation() + mapp.AttributeIndices().Append(0, 1) + + attrs = FromAttributeIndices(table, mapp) + + m = map[string]any{"hello": "world", "bonjour": "monde"} + assert.Equal(t, attrs.AsRaw(), m) +} + +func BenchmarkFromAttributeIndices(b *testing.B) { + table := NewAttributeTableSlice() + + for i := range 10 { + att := table.AppendEmpty() + att.SetKey(fmt.Sprintf("key_%d", i)) + att.Value().SetStr(fmt.Sprintf("value_%d", i)) + } + + obj := NewLocation() + obj.AttributeIndices().Append(1, 3, 7) + + b.ResetTimer() + b.ReportAllocs() + + for n := 0; n < b.N; n++ { + _ = FromAttributeIndices(table, obj) + } +} diff --git a/pdata/pprofile/go.mod b/pdata/pprofile/go.mod index 4171118b5a95..2f40411b6930 100644 --- a/pdata/pprofile/go.mod +++ b/pdata/pprofile/go.mod @@ -7,7 +7,7 @@ require ( github.com/stretchr/testify v1.10.0 go.opentelemetry.io/collector/pdata v1.24.0 go.uber.org/goleak v1.3.0 - google.golang.org/grpc v1.69.4 + google.golang.org/grpc v1.70.0 ) require ( @@ -21,8 +21,8 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/pdata/pprofile/go.sum b/pdata/pprofile/go.sum index 1a6bba54854c..64ba821605e4 100644 --- a/pdata/pprofile/go.sum +++ b/pdata/pprofile/go.sum @@ -38,16 +38,16 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -83,12 +83,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/pdata/testdata/go.mod b/pdata/testdata/go.mod index b2ac35ca592a..dda13d70871d 100644 --- a/pdata/testdata/go.mod +++ b/pdata/testdata/go.mod @@ -16,9 +16,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect ) replace go.opentelemetry.io/collector/pdata => ../ diff --git a/pdata/testdata/go.sum b/pdata/testdata/go.sum index a10bb2143111..1895b70afcbe 100644 --- a/pdata/testdata/go.sum +++ b/pdata/testdata/go.sum @@ -31,16 +31,16 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -76,11 +76,11 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pipeline/pipeline.go b/pipeline/pipeline.go index aa2d3d0d0ad5..7ffb7ddf4ffb 100644 --- a/pipeline/pipeline.go +++ b/pipeline/pipeline.go @@ -72,23 +72,19 @@ func (i ID) MarshalText() (text []byte, err error) { // UnmarshalText implements the encoding.TextUnmarshaler interface. func (i *ID) UnmarshalText(text []byte) error { idStr := string(text) - items := strings.SplitN(idStr, typeAndNameSeparator, 2) - var signalStr, nameStr string - if len(items) >= 1 { - signalStr = strings.TrimSpace(items[0]) - } - - if len(items) == 1 && signalStr == "" { - return errors.New("id must not be empty") - } + signalStr, nameStr, hasName := strings.Cut(idStr, typeAndNameSeparator) + signalStr = strings.TrimSpace(signalStr) if signalStr == "" { - return fmt.Errorf("in %q id: the part before %s should not be empty", idStr, typeAndNameSeparator) + if hasName { + return fmt.Errorf("in %q id: the part before %s should not be empty", idStr, typeAndNameSeparator) + } + return errors.New("id must not be empty") } - if len(items) > 1 { + if hasName { // "name" part is present. - nameStr = strings.TrimSpace(items[1]) + nameStr = strings.TrimSpace(nameStr) if nameStr == "" { return fmt.Errorf("in %q id: the part after %s should not be empty", idStr, typeAndNameSeparator) } diff --git a/processor/batchprocessor/batch_processor.go b/processor/batchprocessor/batch_processor.go index 6dc5ed828eea..81dbd8e525fc 100644 --- a/processor/batchprocessor/batch_processor.go +++ b/processor/batchprocessor/batch_processor.go @@ -177,6 +177,7 @@ func (bp *batchProcessor[T]) Shutdown(context.Context) error { // Wait until all goroutines are done. bp.goroutines.Wait() + return nil } diff --git a/processor/batchprocessor/batch_processor_test.go b/processor/batchprocessor/batch_processor_test.go index dfa4430f0bfb..b253f09c19b9 100644 --- a/processor/batchprocessor/batch_processor_test.go +++ b/processor/batchprocessor/batch_processor_test.go @@ -173,14 +173,14 @@ func TestBatchProcessorSentBySize(t *testing.T) { expectedBatchingFactor = sendBatchSize / spansPerRequest ) - tel := metadatatest.SetupTelemetry() + tel := componenttest.NewTelemetry() sizer := &ptrace.ProtoMarshaler{} sink := new(consumertest.TracesSink) cfg := createDefaultConfig().(*Config) cfg.SendBatchSize = sendBatchSize cfg.Timeout = 500 * time.Millisecond - traces, err := NewFactory().CreateTraces(context.Background(), tel.NewSettings(), cfg, sink) + traces, err := NewFactory().CreateTraces(context.Background(), metadatatest.NewSettings(tel), cfg, sink) require.NoError(t, err) require.NoError(t, traces.Start(context.Background(), componenttest.NewNopHost())) @@ -209,80 +209,52 @@ func TestBatchProcessorSentBySize(t *testing.T) { } } - tel.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_processor_batch_batch_send_size_bytes", - Description: "Number of bytes in batch that was sent. Only available on detailed level.", - Unit: "By", - Data: metricdata.Histogram[int64]{ - Temporality: metricdata.CumulativeTemporality, - DataPoints: []metricdata.HistogramDataPoint[int64]{ - { - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - Count: uint64(expectedBatchesNum), - Bounds: []float64{ - 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, - 100_000, 200_000, 300_000, 400_000, 500_000, 600_000, 700_000, 800_000, 900_000, - 1000_000, 2000_000, 3000_000, 4000_000, 5000_000, 6000_000, 7000_000, 8000_000, 9000_000, - }, - BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uint64(expectedBatchesNum), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - Sum: int64(sizeSum), - Min: metricdata.NewExtrema(int64(sizeSum / expectedBatchesNum)), - Max: metricdata.NewExtrema(int64(sizeSum / expectedBatchesNum)), - }, + metadatatest.AssertEqualProcessorBatchBatchSendSizeBytes(t, tel, + []metricdata.HistogramDataPoint[int64]{ + { + Attributes: attribute.NewSet(attribute.String("processor", "batch")), + Count: uint64(expectedBatchesNum), + Bounds: []float64{ + 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, + 100_000, 200_000, 300_000, 400_000, 500_000, 600_000, 700_000, 800_000, 900_000, + 1000_000, 2000_000, 3000_000, 4000_000, 5000_000, 6000_000, 7000_000, 8000_000, 9000_000, }, + BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uint64(expectedBatchesNum), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + Sum: int64(sizeSum), + Min: metricdata.NewExtrema(int64(sizeSum / expectedBatchesNum)), + Max: metricdata.NewExtrema(int64(sizeSum / expectedBatchesNum)), }, - }, - { - Name: "otelcol_processor_batch_batch_send_size", - Description: "Number of units in the batch", - Unit: "{units}", - Data: metricdata.Histogram[int64]{ - Temporality: metricdata.CumulativeTemporality, - DataPoints: []metricdata.HistogramDataPoint[int64]{ - { - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - Count: uint64(expectedBatchesNum), - Bounds: []float64{10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, 100000}, - BucketCounts: []uint64{0, uint64(expectedBatchesNum), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - Sum: int64(sink.SpanCount()), - Min: metricdata.NewExtrema(int64(sendBatchSize)), - Max: metricdata.NewExtrema(int64(sendBatchSize)), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + + metadatatest.AssertEqualProcessorBatchBatchSendSize(t, tel, + []metricdata.HistogramDataPoint[int64]{ + { + Attributes: attribute.NewSet(attribute.String("processor", "batch")), + Count: uint64(expectedBatchesNum), + Bounds: []float64{10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, 100000}, + BucketCounts: []uint64{0, uint64(expectedBatchesNum), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + Sum: int64(sink.SpanCount()), + Min: metricdata.NewExtrema(int64(sendBatchSize)), + Max: metricdata.NewExtrema(int64(sendBatchSize)), }, - }, - { - Name: "otelcol_processor_batch_batch_size_trigger_send", - Description: "Number of times the batch was sent due to a size trigger", - Unit: "{times}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: int64(expectedBatchesNum), - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + + metadatatest.AssertEqualProcessorBatchBatchSizeTriggerSend(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: int64(expectedBatchesNum), + Attributes: attribute.NewSet(attribute.String("processor", "batch")), }, - }, - { - Name: "otelcol_processor_batch_metadata_cardinality", - Description: "Number of distinct metadata value combinations being processed", - Unit: "{combinations}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: false, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 1, - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + + metadatatest.AssertEqualProcessorBatchMetadataCardinality(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 1, + Attributes: attribute.NewSet(attribute.String("processor", "batch")), }, - }, - }, metricdatatest.IgnoreTimestamp()) + }, metricdatatest.IgnoreTimestamp()) + require.NoError(t, tel.Shutdown(context.Background())) } @@ -295,7 +267,7 @@ func TestBatchProcessorSentBySizeWithMaxSize(t *testing.T) { totalSpans = requestCount * spansPerRequest ) - tel := metadatatest.SetupTelemetry() + tel := componenttest.NewTelemetry() sizer := &ptrace.ProtoMarshaler{} sink := new(consumertest.TracesSink) cfg := createDefaultConfig().(*Config) @@ -303,7 +275,7 @@ func TestBatchProcessorSentBySizeWithMaxSize(t *testing.T) { cfg.SendBatchMaxSize = uint32(sendBatchMaxSize) cfg.Timeout = 500 * time.Millisecond - traces, err := NewFactory().CreateTraces(context.Background(), tel.NewSettings(), cfg, sink) + traces, err := NewFactory().CreateTraces(context.Background(), metadatatest.NewSettings(tel), cfg, sink) require.NoError(t, err) require.NoError(t, traces.Start(context.Background(), componenttest.NewNopHost())) @@ -336,95 +308,52 @@ func TestBatchProcessorSentBySizeWithMaxSize(t *testing.T) { sizeSum += sizer.TracesSize(td) } - tel.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_processor_batch_batch_send_size_bytes", - Description: "Number of bytes in batch that was sent. Only available on detailed level.", - Unit: "By", - Data: metricdata.Histogram[int64]{ - Temporality: metricdata.CumulativeTemporality, - DataPoints: []metricdata.HistogramDataPoint[int64]{ - { - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - Count: uint64(expectedBatchesNum), - Bounds: []float64{ - 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, - 100_000, 200_000, 300_000, 400_000, 500_000, 600_000, 700_000, 800_000, 900_000, - 1000_000, 2000_000, 3000_000, 4000_000, 5000_000, 6000_000, 7000_000, 8000_000, 9000_000, - }, - BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, uint64(expectedBatchesNum - 1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - Sum: int64(sizeSum), - Min: metricdata.NewExtrema(int64(minSize)), - Max: metricdata.NewExtrema(int64(maxSize)), - }, + metadatatest.AssertEqualProcessorBatchBatchSendSizeBytes(t, tel, + []metricdata.HistogramDataPoint[int64]{ + { + Attributes: attribute.NewSet(attribute.String("processor", "batch")), + Count: uint64(expectedBatchesNum), + Bounds: []float64{ + 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, + 100_000, 200_000, 300_000, 400_000, 500_000, 600_000, 700_000, 800_000, 900_000, + 1000_000, 2000_000, 3000_000, 4000_000, 5000_000, 6000_000, 7000_000, 8000_000, 9000_000, }, + BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, uint64(expectedBatchesNum - 1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + Sum: int64(sizeSum), + Min: metricdata.NewExtrema(int64(minSize)), + Max: metricdata.NewExtrema(int64(maxSize)), }, - }, - { - Name: "otelcol_processor_batch_batch_send_size", - Description: "Number of units in the batch", - Unit: "{units}", - Data: metricdata.Histogram[int64]{ - Temporality: metricdata.CumulativeTemporality, - DataPoints: []metricdata.HistogramDataPoint[int64]{ - { - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - Count: uint64(expectedBatchesNum), - Bounds: []float64{10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, 100000}, - BucketCounts: []uint64{0, 1, uint64(expectedBatchesNum - 1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - Sum: int64(sink.SpanCount()), - Min: metricdata.NewExtrema(int64(sendBatchSize - 1)), - Max: metricdata.NewExtrema(int64(cfg.SendBatchMaxSize)), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + + metadatatest.AssertEqualProcessorBatchBatchSendSize(t, tel, + []metricdata.HistogramDataPoint[int64]{ + { + Attributes: attribute.NewSet(attribute.String("processor", "batch")), + Count: uint64(expectedBatchesNum), + Bounds: []float64{10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, 100000}, + BucketCounts: []uint64{0, 1, uint64(expectedBatchesNum - 1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + Sum: int64(sink.SpanCount()), + Min: metricdata.NewExtrema(int64(sendBatchSize - 1)), + Max: metricdata.NewExtrema(int64(cfg.SendBatchMaxSize)), }, - }, - { - Name: "otelcol_processor_batch_batch_size_trigger_send", - Description: "Number of times the batch was sent due to a size trigger", - Unit: "{times}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: int64(expectedBatchesNum - 1), - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - }, - }, - }, - }, - { - Name: "otelcol_processor_batch_timeout_trigger_send", - Description: "Number of times the batch was sent due to a timeout trigger", - Unit: "{times}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 1, - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + + metadatatest.AssertEqualProcessorBatchBatchSizeTriggerSend(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: int64(expectedBatchesNum - 1), + Attributes: attribute.NewSet(attribute.String("processor", "batch")), }, - }, - { - Name: "otelcol_processor_batch_metadata_cardinality", - Description: "Number of distinct metadata value combinations being processed", - Unit: "{combinations}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: false, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 1, - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + + metadatatest.AssertEqualProcessorBatchMetadataCardinality(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 1, + Attributes: attribute.NewSet(attribute.String("processor", "batch")), }, - }, - }, metricdatatest.IgnoreTimestamp()) + }, metricdatatest.IgnoreTimestamp()) + require.NoError(t, tel.Shutdown(context.Background())) } @@ -549,7 +478,7 @@ func TestBatchMetricProcessor_ReceivingData(t *testing.T) { } func TestBatchMetricProcessorBatchSize(t *testing.T) { - tel := metadatatest.SetupTelemetry() + tel := componenttest.NewTelemetry() sizer := &pmetric.ProtoMarshaler{} // Instantiate the batch processor with low config values to test data @@ -567,7 +496,7 @@ func TestBatchMetricProcessorBatchSize(t *testing.T) { ) sink := new(consumertest.MetricsSink) - metrics, err := NewFactory().CreateMetrics(context.Background(), tel.NewSettings(), cfg, sink) + metrics, err := NewFactory().CreateMetrics(context.Background(), metadatatest.NewSettings(tel), cfg, sink) require.NoError(t, err) require.NoError(t, metrics.Start(context.Background(), componenttest.NewNopHost())) @@ -596,80 +525,52 @@ func TestBatchMetricProcessorBatchSize(t *testing.T) { } } - tel.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_processor_batch_batch_send_size_bytes", - Description: "Number of bytes in batch that was sent. Only available on detailed level.", - Unit: "By", - Data: metricdata.Histogram[int64]{ - Temporality: metricdata.CumulativeTemporality, - DataPoints: []metricdata.HistogramDataPoint[int64]{ - { - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - Count: uint64(expectedBatchesNum), - Bounds: []float64{ - 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, - 100_000, 200_000, 300_000, 400_000, 500_000, 600_000, 700_000, 800_000, 900_000, - 1000_000, 2000_000, 3000_000, 4000_000, 5000_000, 6000_000, 7000_000, 8000_000, 9000_000, - }, - BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uint64(expectedBatchesNum), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - Sum: int64(size), - Min: metricdata.NewExtrema(int64(size / int(expectedBatchesNum))), - Max: metricdata.NewExtrema(int64(size / int(expectedBatchesNum))), - }, + metadatatest.AssertEqualProcessorBatchBatchSendSizeBytes(t, tel, + []metricdata.HistogramDataPoint[int64]{ + { + Attributes: attribute.NewSet(attribute.String("processor", "batch")), + Count: uint64(expectedBatchesNum), + Bounds: []float64{ + 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, + 100_000, 200_000, 300_000, 400_000, 500_000, 600_000, 700_000, 800_000, 900_000, + 1000_000, 2000_000, 3000_000, 4000_000, 5000_000, 6000_000, 7000_000, 8000_000, 9000_000, }, + BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uint64(expectedBatchesNum), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + Sum: int64(size), + Min: metricdata.NewExtrema(int64(size / int(expectedBatchesNum))), + Max: metricdata.NewExtrema(int64(size / int(expectedBatchesNum))), }, - }, - { - Name: "otelcol_processor_batch_batch_send_size", - Description: "Number of units in the batch", - Unit: "{units}", - Data: metricdata.Histogram[int64]{ - Temporality: metricdata.CumulativeTemporality, - DataPoints: []metricdata.HistogramDataPoint[int64]{ - { - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - Count: uint64(expectedBatchesNum), - Bounds: []float64{10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, 100000}, - BucketCounts: []uint64{0, 0, uint64(expectedBatchesNum), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - Sum: int64(sink.DataPointCount()), - Min: metricdata.NewExtrema(int64(cfg.SendBatchSize)), - Max: metricdata.NewExtrema(int64(cfg.SendBatchSize)), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + + metadatatest.AssertEqualProcessorBatchBatchSendSize(t, tel, + []metricdata.HistogramDataPoint[int64]{ + { + Attributes: attribute.NewSet(attribute.String("processor", "batch")), + Count: uint64(expectedBatchesNum), + Bounds: []float64{10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, 100000}, + BucketCounts: []uint64{0, 0, uint64(expectedBatchesNum), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + Sum: int64(sink.DataPointCount()), + Min: metricdata.NewExtrema(int64(cfg.SendBatchSize)), + Max: metricdata.NewExtrema(int64(cfg.SendBatchSize)), }, - }, - { - Name: "otelcol_processor_batch_batch_size_trigger_send", - Description: "Number of times the batch was sent due to a size trigger", - Unit: "{times}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: int64(expectedBatchesNum), - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + + metadatatest.AssertEqualProcessorBatchBatchSizeTriggerSend(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: int64(expectedBatchesNum), + Attributes: attribute.NewSet(attribute.String("processor", "batch")), }, - }, - { - Name: "otelcol_processor_batch_metadata_cardinality", - Description: "Number of distinct metadata value combinations being processed", - Unit: "{combinations}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: false, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 1, - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + + metadatatest.AssertEqualProcessorBatchMetadataCardinality(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 1, + Attributes: attribute.NewSet(attribute.String("processor", "batch")), }, - }, - }, metricdatatest.IgnoreTimestamp()) + }, metricdatatest.IgnoreTimestamp()) + require.NoError(t, tel.Shutdown(context.Background())) } @@ -927,7 +828,7 @@ func TestBatchLogProcessor_ReceivingData(t *testing.T) { } func TestBatchLogProcessor_BatchSize(t *testing.T) { - tel := metadatatest.SetupTelemetry() + tel := componenttest.NewTelemetry() sizer := &plog.ProtoMarshaler{} // Instantiate the batch processor with low config values to test data @@ -943,7 +844,7 @@ func TestBatchLogProcessor_BatchSize(t *testing.T) { ) sink := new(consumertest.LogsSink) - logs, err := NewFactory().CreateLogs(context.Background(), tel.NewSettings(), cfg, sink) + logs, err := NewFactory().CreateLogs(context.Background(), metadatatest.NewSettings(tel), cfg, sink) require.NoError(t, err) require.NoError(t, logs.Start(context.Background(), componenttest.NewNopHost())) @@ -972,80 +873,52 @@ func TestBatchLogProcessor_BatchSize(t *testing.T) { } } - tel.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_processor_batch_batch_send_size_bytes", - Description: "Number of bytes in batch that was sent. Only available on detailed level.", - Unit: "By", - Data: metricdata.Histogram[int64]{ - Temporality: metricdata.CumulativeTemporality, - DataPoints: []metricdata.HistogramDataPoint[int64]{ - { - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - Count: uint64(expectedBatchesNum), - Bounds: []float64{ - 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, - 100_000, 200_000, 300_000, 400_000, 500_000, 600_000, 700_000, 800_000, 900_000, - 1000_000, 2000_000, 3000_000, 4000_000, 5000_000, 6000_000, 7000_000, 8000_000, 9000_000, - }, - BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uint64(expectedBatchesNum), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - Sum: int64(size), - Min: metricdata.NewExtrema(int64(size / int(expectedBatchesNum))), - Max: metricdata.NewExtrema(int64(size / int(expectedBatchesNum))), - }, + metadatatest.AssertEqualProcessorBatchBatchSendSizeBytes(t, tel, + []metricdata.HistogramDataPoint[int64]{ + { + Attributes: attribute.NewSet(attribute.String("processor", "batch")), + Count: uint64(expectedBatchesNum), + Bounds: []float64{ + 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, + 100_000, 200_000, 300_000, 400_000, 500_000, 600_000, 700_000, 800_000, 900_000, + 1000_000, 2000_000, 3000_000, 4000_000, 5000_000, 6000_000, 7000_000, 8000_000, 9000_000, }, + BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uint64(expectedBatchesNum), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + Sum: int64(size), + Min: metricdata.NewExtrema(int64(size / int(expectedBatchesNum))), + Max: metricdata.NewExtrema(int64(size / int(expectedBatchesNum))), }, - }, - { - Name: "otelcol_processor_batch_batch_send_size", - Description: "Number of units in the batch", - Unit: "{units}", - Data: metricdata.Histogram[int64]{ - Temporality: metricdata.CumulativeTemporality, - DataPoints: []metricdata.HistogramDataPoint[int64]{ - { - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - Count: uint64(expectedBatchesNum), - Bounds: []float64{10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, 100000}, - BucketCounts: []uint64{0, 0, uint64(expectedBatchesNum), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - Sum: int64(sink.LogRecordCount()), - Min: metricdata.NewExtrema(int64(cfg.SendBatchSize)), - Max: metricdata.NewExtrema(int64(cfg.SendBatchSize)), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + + metadatatest.AssertEqualProcessorBatchBatchSendSize(t, tel, + []metricdata.HistogramDataPoint[int64]{ + { + Attributes: attribute.NewSet(attribute.String("processor", "batch")), + Count: uint64(expectedBatchesNum), + Bounds: []float64{10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, 100000}, + BucketCounts: []uint64{0, 0, uint64(expectedBatchesNum), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + Sum: int64(sink.LogRecordCount()), + Min: metricdata.NewExtrema(int64(cfg.SendBatchSize)), + Max: metricdata.NewExtrema(int64(cfg.SendBatchSize)), }, - }, - { - Name: "otelcol_processor_batch_batch_size_trigger_send", - Description: "Number of times the batch was sent due to a size trigger", - Unit: "{times}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: int64(expectedBatchesNum), - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + + metadatatest.AssertEqualProcessorBatchBatchSizeTriggerSend(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: int64(expectedBatchesNum), + Attributes: attribute.NewSet(attribute.String("processor", "batch")), }, - }, - { - Name: "otelcol_processor_batch_metadata_cardinality", - Description: "Number of distinct metadata value combinations being processed", - Unit: "{combinations}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: false, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 1, - Attributes: attribute.NewSet(attribute.String("processor", "batch")), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + + metadatatest.AssertEqualProcessorBatchMetadataCardinality(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 1, + Attributes: attribute.NewSet(attribute.String("processor", "batch")), }, - }, - }, metricdatatest.IgnoreTimestamp()) + }, metricdatatest.IgnoreTimestamp()) + require.NoError(t, tel.Shutdown(context.Background())) } diff --git a/processor/batchprocessor/go.mod b/processor/batchprocessor/go.mod index b4874c40a546..981191bc77d1 100644 --- a/processor/batchprocessor/go.mod +++ b/processor/batchprocessor/go.mod @@ -51,9 +51,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/processor/batchprocessor/go.sum b/processor/batchprocessor/go.sum index 6686af8fbb16..8bd3034e9c01 100644 --- a/processor/batchprocessor/go.sum +++ b/processor/batchprocessor/go.sum @@ -99,12 +99,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/processor/batchprocessor/internal/metadata/generated_telemetry.go b/processor/batchprocessor/internal/metadata/generated_telemetry.go index 8fd883ed6f86..4df4a713d44d 100644 --- a/processor/batchprocessor/internal/metadata/generated_telemetry.go +++ b/processor/batchprocessor/internal/metadata/generated_telemetry.go @@ -5,8 +5,10 @@ package metadata import ( "context" "errors" + "sync" "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/embedded" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" @@ -23,11 +25,14 @@ func Tracer(settings component.TelemetrySettings) trace.Tracer { // TelemetryBuilder provides an interface for components to report telemetry // as defined in metadata and user config. type TelemetryBuilder struct { - meter metric.Meter - ProcessorBatchBatchSendSize metric.Int64Histogram - ProcessorBatchBatchSendSizeBytes metric.Int64Histogram - ProcessorBatchBatchSizeTriggerSend metric.Int64Counter - ProcessorBatchMetadataCardinality metric.Int64ObservableUpDownCounter + meter metric.Meter + mu sync.Mutex + registrations []metric.Registration + ProcessorBatchBatchSendSize metric.Int64Histogram + ProcessorBatchBatchSendSizeBytes metric.Int64Histogram + ProcessorBatchBatchSizeTriggerSend metric.Int64Counter + ProcessorBatchMetadataCardinality metric.Int64ObservableUpDownCounter + // TODO: Remove in v0.119.0 when remove deprecated funcs. observeProcessorBatchMetadataCardinality func(context.Context, metric.Observer) error ProcessorBatchTimeoutTriggerSend metric.Int64Counter } @@ -43,7 +48,7 @@ func (tbof telemetryBuilderOptionFunc) apply(mb *TelemetryBuilder) { tbof(mb) } -// WithProcessorBatchMetadataCardinalityCallback sets callback for observable ProcessorBatchMetadataCardinality metric. +// Deprecated: [v0.119.0] use RegisterProcessorBatchMetadataCardinalityCallback. func WithProcessorBatchMetadataCardinalityCallback(cb func() int64, opts ...metric.ObserveOption) TelemetryBuilderOption { return telemetryBuilderOptionFunc(func(builder *TelemetryBuilder) { builder.observeProcessorBatchMetadataCardinality = func(_ context.Context, o metric.Observer) error { @@ -53,6 +58,40 @@ func WithProcessorBatchMetadataCardinalityCallback(cb func() int64, opts ...metr }) } +// RegisterProcessorBatchMetadataCardinalityCallback sets callback for observable ProcessorBatchMetadataCardinality metric. +func (builder *TelemetryBuilder) RegisterProcessorBatchMetadataCardinalityCallback(cb metric.Int64Callback) error { + reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { + cb(ctx, &observerInt64{inst: builder.ProcessorBatchMetadataCardinality, obs: o}) + return nil + }, builder.ProcessorBatchMetadataCardinality) + if err != nil { + return err + } + builder.mu.Lock() + defer builder.mu.Unlock() + builder.registrations = append(builder.registrations, reg) + return nil +} + +type observerInt64 struct { + embedded.Int64Observer + inst metric.Int64Observable + obs metric.Observer +} + +func (oi *observerInt64) Observe(value int64, opts ...metric.ObserveOption) { + oi.obs.ObserveInt64(oi.inst, value, opts...) +} + +// Shutdown unregister all registered callbacks for async instruments. +func (builder *TelemetryBuilder) Shutdown() { + builder.mu.Lock() + defer builder.mu.Unlock() + for _, reg := range builder.registrations { + reg.Unregister() + } +} + // NewTelemetryBuilder provides a struct with methods to update all internal telemetry // for a component func NewTelemetryBuilder(settings component.TelemetrySettings, options ...TelemetryBuilderOption) (*TelemetryBuilder, error) { @@ -88,8 +127,13 @@ func NewTelemetryBuilder(settings component.TelemetrySettings, options ...Teleme metric.WithUnit("{combinations}"), ) errs = errors.Join(errs, err) - _, err = builder.meter.RegisterCallback(builder.observeProcessorBatchMetadataCardinality, builder.ProcessorBatchMetadataCardinality) - errs = errors.Join(errs, err) + if builder.observeProcessorBatchMetadataCardinality != nil { + reg, err := builder.meter.RegisterCallback(builder.observeProcessorBatchMetadataCardinality, builder.ProcessorBatchMetadataCardinality) + errs = errors.Join(errs, err) + if err == nil { + builder.registrations = append(builder.registrations, reg) + } + } builder.ProcessorBatchTimeoutTriggerSend, err = builder.meter.Int64Counter( "otelcol_processor_batch_timeout_trigger_send", metric.WithDescription("Number of times the batch was sent due to a timeout trigger"), diff --git a/processor/batchprocessor/internal/metadatatest/generated_telemetrytest.go b/processor/batchprocessor/internal/metadatatest/generated_telemetrytest.go index f7347a2e0ac9..cdd85b387d45 100644 --- a/processor/batchprocessor/internal/metadatatest/generated_telemetrytest.go +++ b/processor/batchprocessor/internal/metadatatest/generated_telemetrytest.go @@ -16,26 +16,35 @@ import ( "go.opentelemetry.io/collector/processor/processortest" ) +// Deprecated: [v0.119.0] Use componenttest.Telemetry type Telemetry struct { - componenttest.Telemetry + *componenttest.Telemetry } +// Deprecated: [v0.119.0] Use componenttest.NewTelemetry func SetupTelemetry(opts ...componenttest.TelemetryOption) Telemetry { return Telemetry{Telemetry: componenttest.NewTelemetry(opts...)} } + +// Deprecated: [v0.119.0] Use metadatatest.NewSettings func (tt *Telemetry) NewSettings() processor.Settings { + return NewSettings(tt.Telemetry) +} + +func NewSettings(tt *componenttest.Telemetry) processor.Settings { set := processortest.NewNopSettings() set.ID = component.NewID(component.MustNewType("batch")) set.TelemetrySettings = tt.NewTelemetrySettings() return set } +// Deprecated: [v0.119.0] Use metadatatest.AssertEqual* func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { var md metricdata.ResourceMetrics require.NoError(t, tt.Reader.Collect(context.Background(), &md)) // ensure all required metrics are present for _, want := range expected { - got := getMetric(want.Name, md) + got := getMetricFromResource(want.Name, md) metricdatatest.AssertEqual(t, want, got, opts...) } @@ -43,7 +52,85 @@ func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, require.Equal(t, len(expected), lenMetrics(md)) } -func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { +func AssertEqualProcessorBatchBatchSendSize(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.HistogramDataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_processor_batch_batch_send_size", + Description: "Number of units in the batch", + Unit: "{units}", + Data: metricdata.Histogram[int64]{ + Temporality: metricdata.CumulativeTemporality, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_processor_batch_batch_send_size") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessorBatchBatchSendSizeBytes(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.HistogramDataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_processor_batch_batch_send_size_bytes", + Description: "Number of bytes in batch that was sent. Only available on detailed level.", + Unit: "By", + Data: metricdata.Histogram[int64]{ + Temporality: metricdata.CumulativeTemporality, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_processor_batch_batch_send_size_bytes") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessorBatchBatchSizeTriggerSend(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_processor_batch_batch_size_trigger_send", + Description: "Number of times the batch was sent due to a size trigger", + Unit: "{times}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_processor_batch_batch_size_trigger_send") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessorBatchMetadataCardinality(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_processor_batch_metadata_cardinality", + Description: "Number of distinct metadata value combinations being processed", + Unit: "{combinations}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: false, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_processor_batch_metadata_cardinality") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessorBatchTimeoutTriggerSend(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_processor_batch_timeout_trigger_send", + Description: "Number of times the batch was sent due to a timeout trigger", + Unit: "{times}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_processor_batch_timeout_trigger_send") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func getMetricFromResource(name string, got metricdata.ResourceMetrics) metricdata.Metrics { for _, sm := range got.ScopeMetrics { for _, m := range sm.Metrics { if m.Name == name { diff --git a/processor/batchprocessor/internal/metadatatest/generated_telemetrytest_test.go b/processor/batchprocessor/internal/metadatatest/generated_telemetrytest_test.go index 8dc7ec902d91..c6e26145bbb9 100644 --- a/processor/batchprocessor/internal/metadatatest/generated_telemetrytest_test.go +++ b/processor/batchprocessor/internal/metadatatest/generated_telemetrytest_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/sdk/metric/metricdata" "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" @@ -15,12 +16,13 @@ import ( func TestSetupTelemetry(t *testing.T) { testTel := SetupTelemetry() - tb, err := metadata.NewTelemetryBuilder( - testTel.NewTelemetrySettings(), - metadata.WithProcessorBatchMetadataCardinalityCallback(func() int64 { return 1 }), - ) + tb, err := metadata.NewTelemetryBuilder(testTel.NewTelemetrySettings()) require.NoError(t, err) - require.NotNil(t, tb) + defer tb.Shutdown() + require.NoError(t, tb.RegisterProcessorBatchMetadataCardinalityCallback(func(_ context.Context, observer metric.Int64Observer) error { + observer.Observe(1) + return nil + })) tb.ProcessorBatchBatchSendSize.Record(context.Background(), 1) tb.ProcessorBatchBatchSendSizeBytes.Record(context.Background(), 1) tb.ProcessorBatchBatchSizeTriggerSend.Add(context.Background(), 1) @@ -86,5 +88,21 @@ func TestSetupTelemetry(t *testing.T) { }, }, }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + AssertEqualProcessorBatchBatchSendSize(t, testTel.Telemetry, + []metricdata.HistogramDataPoint[int64]{{}}, metricdatatest.IgnoreValue(), + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessorBatchBatchSendSizeBytes(t, testTel.Telemetry, + []metricdata.HistogramDataPoint[int64]{{}}, metricdatatest.IgnoreValue(), + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessorBatchBatchSizeTriggerSend(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessorBatchMetadataCardinality(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessorBatchTimeoutTriggerSend(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + require.NoError(t, testTel.Shutdown(context.Background())) } diff --git a/processor/batchprocessor/metrics.go b/processor/batchprocessor/metrics.go index 6ec1386faa83..e4e2c218e58f 100644 --- a/processor/batchprocessor/metrics.go +++ b/processor/batchprocessor/metrics.go @@ -31,10 +31,14 @@ type batchProcessorTelemetry struct { func newBatchProcessorTelemetry(set processor.Settings, currentMetadataCardinality func() int) (*batchProcessorTelemetry, error) { attrs := metric.WithAttributeSet(attribute.NewSet(attribute.String(internal.ProcessorKey, set.ID.String()))) - telemetryBuilder, err := metadata.NewTelemetryBuilder( - set.TelemetrySettings, - metadata.WithProcessorBatchMetadataCardinalityCallback(func() int64 { return int64(currentMetadataCardinality()) }, attrs), - ) + telemetryBuilder, err := metadata.NewTelemetryBuilder(set.TelemetrySettings) + if err != nil { + return nil, err + } + err = telemetryBuilder.RegisterProcessorBatchMetadataCardinalityCallback(func(_ context.Context, observer metric.Int64Observer) error { + observer.Observe(int64(currentMetadataCardinality()), attrs) + return nil + }) if err != nil { return nil, err } diff --git a/processor/go.mod b/processor/go.mod index dc6130d8b206..bfa27190ea24 100644 --- a/processor/go.mod +++ b/processor/go.mod @@ -41,9 +41,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/processor/go.sum b/processor/go.sum index 72d2e725c6a8..d47340448917 100644 --- a/processor/go.sum +++ b/processor/go.sum @@ -87,12 +87,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/processor/memorylimiterprocessor/go.mod b/processor/memorylimiterprocessor/go.mod index 7128f4dcf6f9..e29a0be3ec7e 100644 --- a/processor/memorylimiterprocessor/go.mod +++ b/processor/memorylimiterprocessor/go.mod @@ -59,9 +59,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/processor/memorylimiterprocessor/go.sum b/processor/memorylimiterprocessor/go.sum index b96fc9a3052b..f4e96d1f9d49 100644 --- a/processor/memorylimiterprocessor/go.sum +++ b/processor/memorylimiterprocessor/go.sum @@ -120,12 +120,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/processor/memorylimiterprocessor/internal/metadata/generated_telemetry.go b/processor/memorylimiterprocessor/internal/metadata/generated_telemetry.go index bae14bc7d997..a7fd18a058bf 100644 --- a/processor/memorylimiterprocessor/internal/metadata/generated_telemetry.go +++ b/processor/memorylimiterprocessor/internal/metadata/generated_telemetry.go @@ -4,6 +4,7 @@ package metadata import ( "errors" + "sync" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/trace" @@ -23,6 +24,8 @@ func Tracer(settings component.TelemetrySettings) trace.Tracer { // as defined in metadata and user config. type TelemetryBuilder struct { meter metric.Meter + mu sync.Mutex + registrations []metric.Registration ProcessorAcceptedLogRecords metric.Int64Counter ProcessorAcceptedMetricPoints metric.Int64Counter ProcessorAcceptedSpans metric.Int64Counter @@ -42,6 +45,15 @@ func (tbof telemetryBuilderOptionFunc) apply(mb *TelemetryBuilder) { tbof(mb) } +// Shutdown unregister all registered callbacks for async instruments. +func (builder *TelemetryBuilder) Shutdown() { + builder.mu.Lock() + defer builder.mu.Unlock() + for _, reg := range builder.registrations { + reg.Unregister() + } +} + // NewTelemetryBuilder provides a struct with methods to update all internal telemetry // for a component func NewTelemetryBuilder(settings component.TelemetrySettings, options ...TelemetryBuilderOption) (*TelemetryBuilder, error) { diff --git a/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest.go b/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest.go index 75969576b0b7..fd030bc55c98 100644 --- a/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest.go +++ b/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest.go @@ -16,26 +16,35 @@ import ( "go.opentelemetry.io/collector/processor/processortest" ) +// Deprecated: [v0.119.0] Use componenttest.Telemetry type Telemetry struct { - componenttest.Telemetry + *componenttest.Telemetry } +// Deprecated: [v0.119.0] Use componenttest.NewTelemetry func SetupTelemetry(opts ...componenttest.TelemetryOption) Telemetry { return Telemetry{Telemetry: componenttest.NewTelemetry(opts...)} } + +// Deprecated: [v0.119.0] Use metadatatest.NewSettings func (tt *Telemetry) NewSettings() processor.Settings { + return NewSettings(tt.Telemetry) +} + +func NewSettings(tt *componenttest.Telemetry) processor.Settings { set := processortest.NewNopSettings() set.ID = component.NewID(component.MustNewType("memory_limiter")) set.TelemetrySettings = tt.NewTelemetrySettings() return set } +// Deprecated: [v0.119.0] Use metadatatest.AssertEqual* func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { var md metricdata.ResourceMetrics require.NoError(t, tt.Reader.Collect(context.Background(), &md)) // ensure all required metrics are present for _, want := range expected { - got := getMetric(want.Name, md) + got := getMetricFromResource(want.Name, md) metricdatatest.AssertEqual(t, want, got, opts...) } @@ -43,7 +52,103 @@ func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, require.Equal(t, len(expected), lenMetrics(md)) } -func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { +func AssertEqualProcessorAcceptedLogRecords(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_processor_accepted_log_records", + Description: "Number of log records successfully pushed into the next component in the pipeline. [deprecated since v0.110.0]", + Unit: "{records}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_processor_accepted_log_records") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessorAcceptedMetricPoints(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_processor_accepted_metric_points", + Description: "Number of metric points successfully pushed into the next component in the pipeline. [deprecated since v0.110.0]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_processor_accepted_metric_points") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessorAcceptedSpans(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_processor_accepted_spans", + Description: "Number of spans successfully pushed into the next component in the pipeline. [deprecated since v0.110.0]", + Unit: "{spans}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_processor_accepted_spans") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessorRefusedLogRecords(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_processor_refused_log_records", + Description: "Number of log records that were rejected by the next component in the pipeline. [deprecated since v0.110.0]", + Unit: "{records}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_processor_refused_log_records") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessorRefusedMetricPoints(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_processor_refused_metric_points", + Description: "Number of metric points that were rejected by the next component in the pipeline. [deprecated since v0.110.0]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_processor_refused_metric_points") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessorRefusedSpans(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_processor_refused_spans", + Description: "Number of spans that were rejected by the next component in the pipeline. [deprecated since v0.110.0]", + Unit: "{spans}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_processor_refused_spans") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func getMetricFromResource(name string, got metricdata.ResourceMetrics) metricdata.Metrics { for _, sm := range got.ScopeMetrics { for _, m := range sm.Metrics { if m.Name == name { diff --git a/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest_test.go b/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest_test.go index 8e87e88ac5de..efd76cd6a7f7 100644 --- a/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest_test.go +++ b/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest_test.go @@ -15,11 +15,9 @@ import ( func TestSetupTelemetry(t *testing.T) { testTel := SetupTelemetry() - tb, err := metadata.NewTelemetryBuilder( - testTel.NewTelemetrySettings(), - ) + tb, err := metadata.NewTelemetryBuilder(testTel.NewTelemetrySettings()) require.NoError(t, err) - require.NotNil(t, tb) + defer tb.Shutdown() tb.ProcessorAcceptedLogRecords.Add(context.Background(), 1) tb.ProcessorAcceptedMetricPoints.Add(context.Background(), 1) tb.ProcessorAcceptedSpans.Add(context.Background(), 1) @@ -101,5 +99,24 @@ func TestSetupTelemetry(t *testing.T) { }, }, }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + AssertEqualProcessorAcceptedLogRecords(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessorAcceptedMetricPoints(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessorAcceptedSpans(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessorRefusedLogRecords(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessorRefusedMetricPoints(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessorRefusedSpans(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + require.NoError(t, testTel.Shutdown(context.Background())) } diff --git a/processor/memorylimiterprocessor/memorylimiter_test.go b/processor/memorylimiterprocessor/memorylimiter_test.go index d7c6af755ef6..a53238c9544c 100644 --- a/processor/memorylimiterprocessor/memorylimiter_test.go +++ b/processor/memorylimiterprocessor/memorylimiter_test.go @@ -210,13 +210,13 @@ func TestMetricsMemoryPressureResponse(t *testing.T) { } func TestMetricsTelemetry(t *testing.T) { - tel := metadatatest.SetupTelemetry() + tel := componenttest.NewTelemetry() cfg := &Config{ CheckInterval: time.Second, MemoryLimitPercentage: 50, MemorySpikePercentage: 10, } - metrics, err := NewFactory().CreateMetrics(context.Background(), tel.NewSettings(), cfg, consumertest.NewNop()) + metrics, err := NewFactory().CreateMetrics(context.Background(), metadatatest.NewSettings(tel), cfg, consumertest.NewNop()) require.NoError(t, err) require.NoError(t, metrics.Start(context.Background(), componenttest.NewNopHost())) @@ -227,53 +227,14 @@ func TestMetricsTelemetry(t *testing.T) { } require.NoError(t, metrics.Shutdown(context.Background())) - tel.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_processor_accepted_metric_points", - Description: "Number of metric points successfully pushed into the next component in the pipeline. [deprecated since v0.110.0]", - Unit: "{datapoints}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 10, - Attributes: attribute.NewSet(attribute.String("processor", "memory_limiter")), - }, - }, + metadatatest.AssertEqualProcessorAcceptedMetricPoints(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 10, + Attributes: attribute.NewSet(attribute.String("processor", "memory_limiter")), }, - }, - { - Name: "otelcol_processor_incoming_items", - Description: "Number of items passed to the processor. [alpha]", - Unit: "{items}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 10, - Attributes: attribute.NewSet(attribute.String("processor", "memory_limiter"), attribute.String("otel.signal", "metrics")), - }, - }, - }, - }, - { - Name: "otelcol_processor_outgoing_items", - Description: "Number of items emitted from the processor. [alpha]", - Unit: "{items}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 10, - Attributes: attribute.NewSet(attribute.String("processor", "memory_limiter"), attribute.String("otel.signal", "metrics")), - }, - }, - }, - }, - }, metricdatatest.IgnoreTimestamp()) + }, metricdatatest.IgnoreTimestamp()) + require.NoError(t, tel.Shutdown(context.Background())) } diff --git a/processor/processorhelper/internal/metadata/generated_telemetry.go b/processor/processorhelper/internal/metadata/generated_telemetry.go index 7bc101bc4bb6..dd60965bf911 100644 --- a/processor/processorhelper/internal/metadata/generated_telemetry.go +++ b/processor/processorhelper/internal/metadata/generated_telemetry.go @@ -4,6 +4,7 @@ package metadata import ( "errors" + "sync" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/trace" @@ -23,6 +24,8 @@ func Tracer(settings component.TelemetrySettings) trace.Tracer { // as defined in metadata and user config. type TelemetryBuilder struct { meter metric.Meter + mu sync.Mutex + registrations []metric.Registration ProcessorIncomingItems metric.Int64Counter ProcessorOutgoingItems metric.Int64Counter } @@ -38,6 +41,15 @@ func (tbof telemetryBuilderOptionFunc) apply(mb *TelemetryBuilder) { tbof(mb) } +// Shutdown unregister all registered callbacks for async instruments. +func (builder *TelemetryBuilder) Shutdown() { + builder.mu.Lock() + defer builder.mu.Unlock() + for _, reg := range builder.registrations { + reg.Unregister() + } +} + // NewTelemetryBuilder provides a struct with methods to update all internal telemetry // for a component func NewTelemetryBuilder(settings component.TelemetrySettings, options ...TelemetryBuilderOption) (*TelemetryBuilder, error) { diff --git a/processor/processorhelper/internal/metadatatest/generated_telemetrytest.go b/processor/processorhelper/internal/metadatatest/generated_telemetrytest.go index f7f8a377ed2a..7d16af7e4308 100644 --- a/processor/processorhelper/internal/metadatatest/generated_telemetrytest.go +++ b/processor/processorhelper/internal/metadatatest/generated_telemetrytest.go @@ -16,26 +16,35 @@ import ( "go.opentelemetry.io/collector/processor/processortest" ) +// Deprecated: [v0.119.0] Use componenttest.Telemetry type Telemetry struct { - componenttest.Telemetry + *componenttest.Telemetry } +// Deprecated: [v0.119.0] Use componenttest.NewTelemetry func SetupTelemetry(opts ...componenttest.TelemetryOption) Telemetry { return Telemetry{Telemetry: componenttest.NewTelemetry(opts...)} } + +// Deprecated: [v0.119.0] Use metadatatest.NewSettings func (tt *Telemetry) NewSettings() processor.Settings { + return NewSettings(tt.Telemetry) +} + +func NewSettings(tt *componenttest.Telemetry) processor.Settings { set := processortest.NewNopSettings() set.ID = component.NewID(component.MustNewType("processorhelper")) set.TelemetrySettings = tt.NewTelemetrySettings() return set } +// Deprecated: [v0.119.0] Use metadatatest.AssertEqual* func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { var md metricdata.ResourceMetrics require.NoError(t, tt.Reader.Collect(context.Background(), &md)) // ensure all required metrics are present for _, want := range expected { - got := getMetric(want.Name, md) + got := getMetricFromResource(want.Name, md) metricdatatest.AssertEqual(t, want, got, opts...) } @@ -43,7 +52,39 @@ func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, require.Equal(t, len(expected), lenMetrics(md)) } -func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { +func AssertEqualProcessorIncomingItems(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_processor_incoming_items", + Description: "Number of items passed to the processor. [alpha]", + Unit: "{items}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_processor_incoming_items") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessorOutgoingItems(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_processor_outgoing_items", + Description: "Number of items emitted from the processor. [alpha]", + Unit: "{items}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_processor_outgoing_items") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func getMetricFromResource(name string, got metricdata.ResourceMetrics) metricdata.Metrics { for _, sm := range got.ScopeMetrics { for _, m := range sm.Metrics { if m.Name == name { diff --git a/processor/processorhelper/internal/metadatatest/generated_telemetrytest_test.go b/processor/processorhelper/internal/metadatatest/generated_telemetrytest_test.go index 5279286a0e9f..af29892951b8 100644 --- a/processor/processorhelper/internal/metadatatest/generated_telemetrytest_test.go +++ b/processor/processorhelper/internal/metadatatest/generated_telemetrytest_test.go @@ -15,11 +15,9 @@ import ( func TestSetupTelemetry(t *testing.T) { testTel := SetupTelemetry() - tb, err := metadata.NewTelemetryBuilder( - testTel.NewTelemetrySettings(), - ) + tb, err := metadata.NewTelemetryBuilder(testTel.NewTelemetrySettings()) require.NoError(t, err) - require.NotNil(t, tb) + defer tb.Shutdown() tb.ProcessorIncomingItems.Add(context.Background(), 1) tb.ProcessorOutgoingItems.Add(context.Background(), 1) @@ -49,5 +47,12 @@ func TestSetupTelemetry(t *testing.T) { }, }, }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + AssertEqualProcessorIncomingItems(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessorOutgoingItems(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + require.NoError(t, testTel.Shutdown(context.Background())) } diff --git a/processor/processorhelper/logs_test.go b/processor/processorhelper/logs_test.go index 58ba972c6037..611c242e7a65 100644 --- a/processor/processorhelper/logs_test.go +++ b/processor/processorhelper/logs_test.go @@ -120,46 +120,28 @@ func TestLogs_RecordInOut(t *testing.T) { incomingLogRecords.AppendEmpty() incomingLogRecords.AppendEmpty() - testTelemetry := metadatatest.SetupTelemetry() - lp, err := NewLogs(context.Background(), testTelemetry.NewSettings(), &testLogsCfg, consumertest.NewNop(), mockAggregate) + tel := componenttest.NewTelemetry() + lp, err := NewLogs(context.Background(), metadatatest.NewSettings(tel), &testLogsCfg, consumertest.NewNop(), mockAggregate) require.NoError(t, err) assert.NoError(t, lp.Start(context.Background(), componenttest.NewNopHost())) assert.NoError(t, lp.ConsumeLogs(context.Background(), incomingLogs)) assert.NoError(t, lp.Shutdown(context.Background())) - testTelemetry.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_processor_incoming_items", - Description: "Number of items passed to the processor. [alpha]", - Unit: "{items}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 3, - Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "logs")), - }, - }, + metadatatest.AssertEqualProcessorIncomingItems(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 3, + Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "logs")), }, - }, - { - Name: "otelcol_processor_outgoing_items", - Description: "Number of items emitted from the processor. [alpha]", - Unit: "{items}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 1, - Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "logs")), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + metadatatest.AssertEqualProcessorOutgoingItems(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 1, + Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "logs")), }, - }, - }, metricdatatest.IgnoreTimestamp()) + }, metricdatatest.IgnoreTimestamp()) } func TestLogs_RecordIn_ErrorOut(t *testing.T) { @@ -176,44 +158,26 @@ func TestLogs_RecordIn_ErrorOut(t *testing.T) { incomingLogRecords.AppendEmpty() incomingLogRecords.AppendEmpty() - testTelemetry := metadatatest.SetupTelemetry() - lp, err := NewLogs(context.Background(), testTelemetry.NewSettings(), &testLogsCfg, consumertest.NewNop(), mockErr) + tel := componenttest.NewTelemetry() + lp, err := NewLogs(context.Background(), metadatatest.NewSettings(tel), &testLogsCfg, consumertest.NewNop(), mockErr) require.NoError(t, err) require.NoError(t, lp.Start(context.Background(), componenttest.NewNopHost())) require.Error(t, lp.ConsumeLogs(context.Background(), incomingLogs)) require.NoError(t, lp.Shutdown(context.Background())) - testTelemetry.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_processor_incoming_items", - Description: "Number of items passed to the processor. [alpha]", - Unit: "{items}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 3, - Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "logs")), - }, - }, + metadatatest.AssertEqualProcessorIncomingItems(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 3, + Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "logs")), }, - }, - { - Name: "otelcol_processor_outgoing_items", - Description: "Number of items emitted from the processor. [alpha]", - Unit: "{items}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 0, - Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "logs")), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + metadatatest.AssertEqualProcessorOutgoingItems(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 0, + Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "logs")), }, - }, - }, metricdatatest.IgnoreTimestamp()) + }, metricdatatest.IgnoreTimestamp()) } diff --git a/processor/processorhelper/metrics_test.go b/processor/processorhelper/metrics_test.go index 537c7c564f88..ddeceeaed80b 100644 --- a/processor/processorhelper/metrics_test.go +++ b/processor/processorhelper/metrics_test.go @@ -120,46 +120,28 @@ func TestMetrics_RecordInOut(t *testing.T) { dps.AppendEmpty() dps.AppendEmpty() - testTelemetry := metadatatest.SetupTelemetry() - mp, err := NewMetrics(context.Background(), testTelemetry.NewSettings(), &testMetricsCfg, consumertest.NewNop(), mockAggregate) + tel := componenttest.NewTelemetry() + mp, err := NewMetrics(context.Background(), metadatatest.NewSettings(tel), &testMetricsCfg, consumertest.NewNop(), mockAggregate) require.NoError(t, err) assert.NoError(t, mp.Start(context.Background(), componenttest.NewNopHost())) assert.NoError(t, mp.ConsumeMetrics(context.Background(), incomingMetrics)) assert.NoError(t, mp.Shutdown(context.Background())) - testTelemetry.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_processor_incoming_items", - Description: "Number of items passed to the processor. [alpha]", - Unit: "{items}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 2, - Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "metrics")), - }, - }, + metadatatest.AssertEqualProcessorIncomingItems(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 2, + Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "metrics")), }, - }, - { - Name: "otelcol_processor_outgoing_items", - Description: "Number of items emitted from the processor. [alpha]", - Unit: "{items}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 3, - Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "metrics")), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + metadatatest.AssertEqualProcessorOutgoingItems(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 3, + Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "metrics")), }, - }, - }, metricdatatest.IgnoreTimestamp()) + }, metricdatatest.IgnoreTimestamp()) } func TestMetrics_RecordIn_ErrorOut(t *testing.T) { @@ -175,44 +157,26 @@ func TestMetrics_RecordIn_ErrorOut(t *testing.T) { dps.AppendEmpty() dps.AppendEmpty() - testTelemetry := metadatatest.SetupTelemetry() - mp, err := NewMetrics(context.Background(), testTelemetry.NewSettings(), &testMetricsCfg, consumertest.NewNop(), mockErr) + tel := componenttest.NewTelemetry() + mp, err := NewMetrics(context.Background(), metadatatest.NewSettings(tel), &testMetricsCfg, consumertest.NewNop(), mockErr) require.NoError(t, err) require.NoError(t, mp.Start(context.Background(), componenttest.NewNopHost())) require.Error(t, mp.ConsumeMetrics(context.Background(), incomingMetrics)) require.NoError(t, mp.Shutdown(context.Background())) - testTelemetry.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_processor_incoming_items", - Description: "Number of items passed to the processor. [alpha]", - Unit: "{items}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 2, - Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "metrics")), - }, - }, + metadatatest.AssertEqualProcessorIncomingItems(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 2, + Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "metrics")), }, - }, - { - Name: "otelcol_processor_outgoing_items", - Description: "Number of items emitted from the processor. [alpha]", - Unit: "{items}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 0, - Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "metrics")), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + metadatatest.AssertEqualProcessorOutgoingItems(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 0, + Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "metrics")), }, - }, - }, metricdatatest.IgnoreTimestamp()) + }, metricdatatest.IgnoreTimestamp()) } diff --git a/processor/processorhelper/traces_test.go b/processor/processorhelper/traces_test.go index 00824aae1d39..e2fc49d2deff 100644 --- a/processor/processorhelper/traces_test.go +++ b/processor/processorhelper/traces_test.go @@ -122,46 +122,28 @@ func TestTraces_RecordInOut(t *testing.T) { incomingSpans.AppendEmpty() incomingSpans.AppendEmpty() - testTelemetry := metadatatest.SetupTelemetry() - tp, err := NewTraces(context.Background(), testTelemetry.NewSettings(), &testLogsCfg, consumertest.NewNop(), mockAggregate) + tel := componenttest.NewTelemetry() + tp, err := NewTraces(context.Background(), metadatatest.NewSettings(tel), &testLogsCfg, consumertest.NewNop(), mockAggregate) require.NoError(t, err) assert.NoError(t, tp.Start(context.Background(), componenttest.NewNopHost())) assert.NoError(t, tp.ConsumeTraces(context.Background(), incomingTraces)) assert.NoError(t, tp.Shutdown(context.Background())) - testTelemetry.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_processor_incoming_items", - Description: "Number of items passed to the processor. [alpha]", - Unit: "{items}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 4, - Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "traces")), - }, - }, + metadatatest.AssertEqualProcessorIncomingItems(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 4, + Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "traces")), }, - }, - { - Name: "otelcol_processor_outgoing_items", - Description: "Number of items emitted from the processor. [alpha]", - Unit: "{items}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 1, - Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "traces")), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + metadatatest.AssertEqualProcessorOutgoingItems(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 1, + Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "traces")), }, - }, - }, metricdatatest.IgnoreTimestamp()) + }, metricdatatest.IgnoreTimestamp()) } func TestTraces_RecordIn_ErrorOut(t *testing.T) { @@ -179,44 +161,26 @@ func TestTraces_RecordIn_ErrorOut(t *testing.T) { incomingSpans.AppendEmpty() incomingSpans.AppendEmpty() - testTelemetry := metadatatest.SetupTelemetry() - tp, err := NewTraces(context.Background(), testTelemetry.NewSettings(), &testLogsCfg, consumertest.NewNop(), mockErr) + tel := componenttest.NewTelemetry() + tp, err := NewTraces(context.Background(), metadatatest.NewSettings(tel), &testLogsCfg, consumertest.NewNop(), mockErr) require.NoError(t, err) require.NoError(t, tp.Start(context.Background(), componenttest.NewNopHost())) require.Error(t, tp.ConsumeTraces(context.Background(), incomingTraces)) require.NoError(t, tp.Shutdown(context.Background())) - testTelemetry.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_processor_incoming_items", - Description: "Number of items passed to the processor. [alpha]", - Unit: "{items}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 4, - Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "traces")), - }, - }, + metadatatest.AssertEqualProcessorIncomingItems(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 4, + Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "traces")), }, - }, - { - Name: "otelcol_processor_outgoing_items", - Description: "Number of items emitted from the processor. [alpha]", - Unit: "{items}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Value: 0, - Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "traces")), - }, - }, + }, metricdatatest.IgnoreTimestamp()) + metadatatest.AssertEqualProcessorOutgoingItems(t, tel, + []metricdata.DataPoint[int64]{ + { + Value: 0, + Attributes: attribute.NewSet(attribute.String("processor", "processorhelper"), attribute.String("otel.signal", "traces")), }, - }, - }, metricdatatest.IgnoreTimestamp()) + }, metricdatatest.IgnoreTimestamp()) } diff --git a/processor/processorhelper/xprocessorhelper/go.mod b/processor/processorhelper/xprocessorhelper/go.mod index 3281419e0d18..d53b8354bd53 100644 --- a/processor/processorhelper/xprocessorhelper/go.mod +++ b/processor/processorhelper/xprocessorhelper/go.mod @@ -41,9 +41,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/processor/processorhelper/xprocessorhelper/go.sum b/processor/processorhelper/xprocessorhelper/go.sum index 72d2e725c6a8..d47340448917 100644 --- a/processor/processorhelper/xprocessorhelper/go.sum +++ b/processor/processorhelper/xprocessorhelper/go.sum @@ -87,12 +87,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/processor/processortest/go.mod b/processor/processortest/go.mod index 84cf061465cc..0af796cfc904 100644 --- a/processor/processortest/go.mod +++ b/processor/processortest/go.mod @@ -41,9 +41,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/processor/processortest/go.sum b/processor/processortest/go.sum index 72d2e725c6a8..d47340448917 100644 --- a/processor/processortest/go.sum +++ b/processor/processortest/go.sum @@ -87,12 +87,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/processor/xprocessor/go.mod b/processor/xprocessor/go.mod index a4f297d25ca5..fe2168c5261c 100644 --- a/processor/xprocessor/go.mod +++ b/processor/xprocessor/go.mod @@ -30,9 +30,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/processor/xprocessor/go.sum b/processor/xprocessor/go.sum index dbd9e37fa33f..19674bfc86ed 100644 --- a/processor/xprocessor/go.sum +++ b/processor/xprocessor/go.sum @@ -86,12 +86,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/receiver/go.mod b/receiver/go.mod index 48322e45f914..fed37345533d 100644 --- a/receiver/go.mod +++ b/receiver/go.mod @@ -40,9 +40,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/receiver/go.sum b/receiver/go.sum index 4c3709f22234..d47340448917 100644 --- a/receiver/go.sum +++ b/receiver/go.sum @@ -87,12 +87,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/receiver/nopreceiver/go.mod b/receiver/nopreceiver/go.mod index edc91ad223bd..09619482fd4f 100644 --- a/receiver/nopreceiver/go.mod +++ b/receiver/nopreceiver/go.mod @@ -48,9 +48,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/receiver/nopreceiver/go.sum b/receiver/nopreceiver/go.sum index 10733a666e51..8bd3034e9c01 100644 --- a/receiver/nopreceiver/go.sum +++ b/receiver/nopreceiver/go.sum @@ -99,12 +99,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/receiver/otlpreceiver/go.mod b/receiver/otlpreceiver/go.mod index ebd2a52d48f4..14ea1094abdc 100644 --- a/receiver/otlpreceiver/go.mod +++ b/receiver/otlpreceiver/go.mod @@ -30,8 +30,8 @@ require ( go.uber.org/goleak v1.3.0 go.uber.org/zap v1.27.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f - google.golang.org/grpc v1.69.4 - google.golang.org/protobuf v1.36.3 + google.golang.org/grpc v1.70.0 + google.golang.org/protobuf v1.36.4 ) require ( diff --git a/receiver/otlpreceiver/go.sum b/receiver/otlpreceiver/go.sum index c59d17e5648f..f539c5a3a79f 100644 --- a/receiver/otlpreceiver/go.sum +++ b/receiver/otlpreceiver/go.sum @@ -119,10 +119,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/receiver/receiverhelper/internal/metadata/generated_telemetry.go b/receiver/receiverhelper/internal/metadata/generated_telemetry.go index 6607f8f5464f..e3db30b5089e 100644 --- a/receiver/receiverhelper/internal/metadata/generated_telemetry.go +++ b/receiver/receiverhelper/internal/metadata/generated_telemetry.go @@ -4,6 +4,7 @@ package metadata import ( "errors" + "sync" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/trace" @@ -23,6 +24,8 @@ func Tracer(settings component.TelemetrySettings) trace.Tracer { // as defined in metadata and user config. type TelemetryBuilder struct { meter metric.Meter + mu sync.Mutex + registrations []metric.Registration ReceiverAcceptedLogRecords metric.Int64Counter ReceiverAcceptedMetricPoints metric.Int64Counter ReceiverAcceptedSpans metric.Int64Counter @@ -42,6 +45,15 @@ func (tbof telemetryBuilderOptionFunc) apply(mb *TelemetryBuilder) { tbof(mb) } +// Shutdown unregister all registered callbacks for async instruments. +func (builder *TelemetryBuilder) Shutdown() { + builder.mu.Lock() + defer builder.mu.Unlock() + for _, reg := range builder.registrations { + reg.Unregister() + } +} + // NewTelemetryBuilder provides a struct with methods to update all internal telemetry // for a component func NewTelemetryBuilder(settings component.TelemetrySettings, options ...TelemetryBuilderOption) (*TelemetryBuilder, error) { diff --git a/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest.go b/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest.go index b1ff3f106391..b234cc79d478 100644 --- a/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest.go +++ b/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest.go @@ -16,26 +16,35 @@ import ( "go.opentelemetry.io/collector/receiver/receivertest" ) +// Deprecated: [v0.119.0] Use componenttest.Telemetry type Telemetry struct { - componenttest.Telemetry + *componenttest.Telemetry } +// Deprecated: [v0.119.0] Use componenttest.NewTelemetry func SetupTelemetry(opts ...componenttest.TelemetryOption) Telemetry { return Telemetry{Telemetry: componenttest.NewTelemetry(opts...)} } + +// Deprecated: [v0.119.0] Use metadatatest.NewSettings func (tt *Telemetry) NewSettings() receiver.Settings { + return NewSettings(tt.Telemetry) +} + +func NewSettings(tt *componenttest.Telemetry) receiver.Settings { set := receivertest.NewNopSettings() set.ID = component.NewID(component.MustNewType("receiverhelper")) set.TelemetrySettings = tt.NewTelemetrySettings() return set } +// Deprecated: [v0.119.0] Use metadatatest.AssertEqual* func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { var md metricdata.ResourceMetrics require.NoError(t, tt.Reader.Collect(context.Background(), &md)) // ensure all required metrics are present for _, want := range expected { - got := getMetric(want.Name, md) + got := getMetricFromResource(want.Name, md) metricdatatest.AssertEqual(t, want, got, opts...) } @@ -43,7 +52,103 @@ func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, require.Equal(t, len(expected), lenMetrics(md)) } -func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { +func AssertEqualReceiverAcceptedLogRecords(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_receiver_accepted_log_records", + Description: "Number of log records successfully pushed into the pipeline. [alpha]", + Unit: "{records}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_receiver_accepted_log_records") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualReceiverAcceptedMetricPoints(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_receiver_accepted_metric_points", + Description: "Number of metric points successfully pushed into the pipeline. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_receiver_accepted_metric_points") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualReceiverAcceptedSpans(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_receiver_accepted_spans", + Description: "Number of spans successfully pushed into the pipeline. [alpha]", + Unit: "{spans}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_receiver_accepted_spans") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualReceiverRefusedLogRecords(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_receiver_refused_log_records", + Description: "Number of log records that could not be pushed into the pipeline. [alpha]", + Unit: "{records}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_receiver_refused_log_records") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualReceiverRefusedMetricPoints(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_receiver_refused_metric_points", + Description: "Number of metric points that could not be pushed into the pipeline. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_receiver_refused_metric_points") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualReceiverRefusedSpans(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_receiver_refused_spans", + Description: "Number of spans that could not be pushed into the pipeline. [alpha]", + Unit: "{spans}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_receiver_refused_spans") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func getMetricFromResource(name string, got metricdata.ResourceMetrics) metricdata.Metrics { for _, sm := range got.ScopeMetrics { for _, m := range sm.Metrics { if m.Name == name { diff --git a/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest_test.go b/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest_test.go index 96eb0b1956a9..f7691662e630 100644 --- a/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest_test.go +++ b/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest_test.go @@ -15,11 +15,9 @@ import ( func TestSetupTelemetry(t *testing.T) { testTel := SetupTelemetry() - tb, err := metadata.NewTelemetryBuilder( - testTel.NewTelemetrySettings(), - ) + tb, err := metadata.NewTelemetryBuilder(testTel.NewTelemetrySettings()) require.NoError(t, err) - require.NotNil(t, tb) + defer tb.Shutdown() tb.ReceiverAcceptedLogRecords.Add(context.Background(), 1) tb.ReceiverAcceptedMetricPoints.Add(context.Background(), 1) tb.ReceiverAcceptedSpans.Add(context.Background(), 1) @@ -101,5 +99,24 @@ func TestSetupTelemetry(t *testing.T) { }, }, }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + AssertEqualReceiverAcceptedLogRecords(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualReceiverAcceptedMetricPoints(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualReceiverAcceptedSpans(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualReceiverRefusedLogRecords(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualReceiverRefusedMetricPoints(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualReceiverRefusedSpans(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + require.NoError(t, testTel.Shutdown(context.Background())) } diff --git a/receiver/receiverhelper/obsreport_test.go b/receiver/receiverhelper/obsreport_test.go index b6ae6da7b682..02ffc5943ac5 100644 --- a/receiver/receiverhelper/obsreport_test.go +++ b/receiver/receiverhelper/obsreport_test.go @@ -12,11 +12,14 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/receiver" "go.opentelemetry.io/collector/receiver/receiverhelper/internal" + "go.opentelemetry.io/collector/receiver/receiverhelper/internal/metadatatest" ) const ( @@ -126,7 +129,24 @@ func TestReceiveLogsOp(t *testing.T) { t.Fatalf("unexpected param: %v", params[i]) } } - require.NoError(t, tt.CheckReceiverLogs(transport, int64(acceptedLogRecords), int64(refusedLogRecords))) + metadatatest.AssertEqualReceiverAcceptedLogRecords(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("receiver", receiverID.String()), + attribute.String("transport", transport)), + Value: int64(acceptedLogRecords), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + metadatatest.AssertEqualReceiverRefusedLogRecords(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("receiver", receiverID.String()), + attribute.String("transport", transport)), + Value: int64(refusedLogRecords), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) }) } @@ -290,10 +310,24 @@ func TestCheckReceiverLogsViews(t *testing.T) { require.NotNil(t, ctx) rec.EndLogsOp(ctx, format, 7, nil) - require.NoError(t, tt.CheckReceiverLogs(transport, 7, 0)) - require.Error(t, tt.CheckReceiverLogs(transport, 7, 7)) - require.Error(t, tt.CheckReceiverLogs(transport, 0, 0)) - assert.Error(t, tt.CheckReceiverLogs(transport, 0, 7)) + metadatatest.AssertEqualReceiverAcceptedLogRecords(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("receiver", receiverID.String()), + attribute.String("transport", transport)), + Value: int64(7), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + metadatatest.AssertEqualReceiverRefusedLogRecords(t, tt.Telemetry, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String("receiver", receiverID.String()), + attribute.String("transport", transport)), + Value: int64(0), + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) } func testTelemetry(t *testing.T, id component.ID, testFunc func(t *testing.T, tt componenttest.TestTelemetry)) { diff --git a/receiver/receivertest/go.mod b/receiver/receivertest/go.mod index 0af882bebfb8..51ed84e0a82c 100644 --- a/receiver/receivertest/go.mod +++ b/receiver/receivertest/go.mod @@ -40,9 +40,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/receiver/receivertest/go.sum b/receiver/receivertest/go.sum index 4c3709f22234..d47340448917 100644 --- a/receiver/receivertest/go.sum +++ b/receiver/receivertest/go.sum @@ -87,12 +87,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/receiver/xreceiver/go.mod b/receiver/xreceiver/go.mod index d8150136b05c..a8f4dfe32856 100644 --- a/receiver/xreceiver/go.mod +++ b/receiver/xreceiver/go.mod @@ -30,9 +30,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/receiver/xreceiver/go.sum b/receiver/xreceiver/go.sum index 2037f2362e72..19674bfc86ed 100644 --- a/receiver/xreceiver/go.sum +++ b/receiver/xreceiver/go.sum @@ -86,12 +86,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/scraper/go.mod b/scraper/go.mod index 645c57b3c5e6..ebb61d839675 100644 --- a/scraper/go.mod +++ b/scraper/go.mod @@ -33,9 +33,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/scraper/go.sum b/scraper/go.sum index 72d2e725c6a8..d47340448917 100644 --- a/scraper/go.sum +++ b/scraper/go.sum @@ -87,12 +87,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/scraper/scraperhelper/controller_test.go b/scraper/scraperhelper/controller_test.go index 4519f96d2c9d..5264093c3774 100644 --- a/scraper/scraperhelper/controller_test.go +++ b/scraper/scraperhelper/controller_test.go @@ -30,8 +30,6 @@ import ( "go.opentelemetry.io/collector/scraper/scraperhelper/internal/metadatatest" ) -const transportTag = "transport" - type testInitialize struct { ch chan bool err error @@ -140,12 +138,12 @@ func TestLogsScrapeController(t *testing.T) { for _, test := range testCases { t.Run(test.name, func(t *testing.T) { receiverID := component.MustNewID("receiver") - tt := metadatatest.SetupTelemetry() - tel := tt.NewTelemetrySettings() + tel := componenttest.NewTelemetry() + t.Cleanup(func() { require.NoError(t, tel.Shutdown(context.Background())) }) - _, parentSpan := tel.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) + set := tel.NewTelemetrySettings() + _, parentSpan := set.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) defer parentSpan.End() - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) initializeChs := make([]chan bool, test.scrapers) scrapeLogsChs := make([]chan int, test.scrapers) @@ -161,7 +159,7 @@ func TestLogsScrapeController(t *testing.T) { cfg = test.scraperControllerSettings } - mr, err := NewLogsController(cfg, receiver.Settings{ID: receiverID, TelemetrySettings: tel, BuildInfo: component.NewDefaultBuildInfo()}, sink, options...) + mr, err := NewLogsController(cfg, receiver.Settings{ID: receiverID, TelemetrySettings: set, BuildInfo: component.NewDefaultBuildInfo()}, sink, options...) require.NoError(t, err) err = mr.Start(context.Background(), componenttest.NewNopHost()) @@ -199,10 +197,10 @@ func TestLogsScrapeController(t *testing.T) { assert.GreaterOrEqual(t, sink.LogRecordCount(), iterations) } - spans := tt.SpanRecorder.Ended() + spans := tel.SpanRecorder.Ended() assertReceiverSpan(t, spans) assertScraperSpan(t, test.scrapeErr, spans, "scraper/scraper/ScrapeLogs") - assertLogsScraperObsMetrics(t, tt, receiverID, component.MustNewID("scraper"), test.scrapeErr, sink) + assertLogsScraperObsMetrics(t, tel, receiverID, component.MustNewID("scraper"), test.scrapeErr, sink) } err = mr.Shutdown(context.Background()) @@ -251,12 +249,12 @@ func TestMetricsScrapeController(t *testing.T) { for _, test := range testCases { t.Run(test.name, func(t *testing.T) { receiverID := component.MustNewID("receiver") - tt := metadatatest.SetupTelemetry() - tel := tt.NewTelemetrySettings() + tel := componenttest.NewTelemetry() + t.Cleanup(func() { require.NoError(t, tel.Shutdown(context.Background())) }) - _, parentSpan := tel.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) + set := tel.NewTelemetrySettings() + _, parentSpan := set.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) defer parentSpan.End() - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) initializeChs := make([]chan bool, test.scrapers) scrapeMetricsChs := make([]chan int, test.scrapers) @@ -272,7 +270,7 @@ func TestMetricsScrapeController(t *testing.T) { cfg = test.scraperControllerSettings } - mr, err := NewMetricsController(cfg, receiver.Settings{ID: receiverID, TelemetrySettings: tel, BuildInfo: component.NewDefaultBuildInfo()}, sink, options...) + mr, err := NewMetricsController(cfg, receiver.Settings{ID: receiverID, TelemetrySettings: set, BuildInfo: component.NewDefaultBuildInfo()}, sink, options...) require.NoError(t, err) err = mr.Start(context.Background(), componenttest.NewNopHost()) @@ -310,10 +308,10 @@ func TestMetricsScrapeController(t *testing.T) { assert.GreaterOrEqual(t, sink.DataPointCount(), iterations) } - spans := tt.SpanRecorder.Ended() + spans := tel.SpanRecorder.Ended() assertReceiverSpan(t, spans) assertScraperSpan(t, test.scrapeErr, spans, "scraper/scraper/ScrapeMetrics") - assertMetricsScraperObsMetrics(t, tt, receiverID, component.MustNewID("scraper"), test.scrapeErr, sink) + assertMetricsScraperObsMetrics(t, tel, receiverID, component.MustNewID("scraper"), test.scrapeErr, sink) } err = mr.Shutdown(context.Background()) @@ -442,7 +440,7 @@ func assertScraperSpan(t *testing.T, expectedErr error, spans []sdktrace.ReadOnl assert.True(t, scraperSpan) } -func assertLogsScraperObsMetrics(t *testing.T, tt metadatatest.Telemetry, receiver component.ID, scraper component.ID, expectedErr error, sink *consumertest.LogsSink) { +func assertLogsScraperObsMetrics(t *testing.T, tel *componenttest.Telemetry, receiver component.ID, scraper component.ID, expectedErr error, sink *consumertest.LogsSink) { logRecordCounts := 0 for _, md := range sink.AllLogs() { logRecordCounts += md.LogRecordCount() @@ -460,79 +458,28 @@ func assertLogsScraperObsMetrics(t *testing.T, tt metadatatest.Telemetry, receiv } } - tt.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_receiver_accepted_metric_points", - Description: "Number of metric points successfully pushed into the pipeline. [alpha]", - Unit: "{datapoints}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet( - attribute.String(receiverKey, receiver.String()), - attribute.String(transportTag, "")), - Value: int64(logRecordCounts), - }, - }, + metadatatest.AssertEqualScraperScrapedLogRecords(t, tel, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String(receiverKey, receiver.String()), + attribute.String(scraperKey, scraper.String())), + Value: expectedScraped, }, - }, - { - Name: "otelcol_receiver_refused_metric_points", - Description: "Number of metric points that could not be pushed into the pipeline. [alpha]", - Unit: "{datapoints}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet( - attribute.String(receiverKey, receiver.String()), - attribute.String(transportTag, "")), - Value: 0, - }, - }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + + metadatatest.AssertEqualScraperErroredLogRecords(t, tel, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String(receiverKey, receiver.String()), + attribute.String(scraperKey, scraper.String())), + Value: expectedErrored, }, - }, - { - Name: "otelcol_scraper_scraped_log_records", - Description: "Number of log records successfully scraped. [alpha]", - Unit: "{datapoints}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet( - attribute.String(receiverKey, receiver.String()), - attribute.String(scraperKey, scraper.String())), - Value: expectedScraped, - }, - }, - }, - }, - { - Name: "otelcol_scraper_errored_log_records", - Description: "Number of log records that were unable to be scraped. [alpha]", - Unit: "{datapoints}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet( - attribute.String(receiverKey, receiver.String()), - attribute.String(scraperKey, scraper.String())), - Value: expectedErrored, - }, - }, - }, - }, - }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) } -func assertMetricsScraperObsMetrics(t *testing.T, tt metadatatest.Telemetry, receiver component.ID, scraper component.ID, expectedErr error, sink *consumertest.MetricsSink) { +func assertMetricsScraperObsMetrics(t *testing.T, tel *componenttest.Telemetry, receiver component.ID, scraper component.ID, expectedErr error, sink *consumertest.MetricsSink) { dataPointCounts := 0 for _, md := range sink.AllMetrics() { dataPointCounts += md.DataPointCount() @@ -550,76 +497,24 @@ func assertMetricsScraperObsMetrics(t *testing.T, tt metadatatest.Telemetry, rec } } - tt.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_receiver_accepted_metric_points", - Description: "Number of metric points successfully pushed into the pipeline. [alpha]", - Unit: "{datapoints}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet( - attribute.String(receiverKey, receiver.String()), - attribute.String(transportTag, "")), - Value: int64(dataPointCounts), - }, - }, - }, - }, - { - Name: "otelcol_receiver_refused_metric_points", - Description: "Number of metric points that could not be pushed into the pipeline. [alpha]", - Unit: "{datapoints}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet( - attribute.String(receiverKey, receiver.String()), - attribute.String(transportTag, "")), - Value: 0, - }, - }, - }, - }, - { - Name: "otelcol_scraper_scraped_metric_points", - Description: "Number of metric points successfully scraped. [alpha]", - Unit: "{datapoints}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet( - attribute.String(receiverKey, receiver.String()), - attribute.String(scraperKey, scraper.String())), - Value: expectedScraped, - }, - }, + metadatatest.AssertEqualScraperScrapedMetricPoints(t, tel, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String(receiverKey, receiver.String()), + attribute.String(scraperKey, scraper.String())), + Value: expectedScraped, }, - }, - { - Name: "otelcol_scraper_errored_metric_points", - Description: "Number of metric points that were unable to be scraped. [alpha]", - Unit: "{datapoints}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet( - attribute.String(receiverKey, receiver.String()), - attribute.String(scraperKey, scraper.String())), - Value: expectedErrored, - }, - }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + metadatatest.AssertEqualScraperErroredMetricPoints(t, tel, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String(receiverKey, receiver.String()), + attribute.String(scraperKey, scraper.String())), + Value: expectedErrored, }, - }, - }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) } func TestSingleLogsScraperPerInterval(t *testing.T) { diff --git a/scraper/scraperhelper/go.mod b/scraper/scraperhelper/go.mod index d1b55a7f615f..34a0bd7bac7a 100644 --- a/scraper/scraperhelper/go.mod +++ b/scraper/scraperhelper/go.mod @@ -43,9 +43,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/scraper/scraperhelper/go.sum b/scraper/scraperhelper/go.sum index 4c3709f22234..d47340448917 100644 --- a/scraper/scraperhelper/go.sum +++ b/scraper/scraperhelper/go.sum @@ -87,12 +87,12 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/scraper/scraperhelper/internal/metadata/generated_telemetry.go b/scraper/scraperhelper/internal/metadata/generated_telemetry.go index fcdb6b4028fc..035ff8fe8420 100644 --- a/scraper/scraperhelper/internal/metadata/generated_telemetry.go +++ b/scraper/scraperhelper/internal/metadata/generated_telemetry.go @@ -4,6 +4,7 @@ package metadata import ( "errors" + "sync" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/trace" @@ -23,6 +24,8 @@ func Tracer(settings component.TelemetrySettings) trace.Tracer { // as defined in metadata and user config. type TelemetryBuilder struct { meter metric.Meter + mu sync.Mutex + registrations []metric.Registration ScraperErroredLogRecords metric.Int64Counter ScraperErroredMetricPoints metric.Int64Counter ScraperScrapedLogRecords metric.Int64Counter @@ -40,6 +43,15 @@ func (tbof telemetryBuilderOptionFunc) apply(mb *TelemetryBuilder) { tbof(mb) } +// Shutdown unregister all registered callbacks for async instruments. +func (builder *TelemetryBuilder) Shutdown() { + builder.mu.Lock() + defer builder.mu.Unlock() + for _, reg := range builder.registrations { + reg.Unregister() + } +} + // NewTelemetryBuilder provides a struct with methods to update all internal telemetry // for a component func NewTelemetryBuilder(settings component.TelemetrySettings, options ...TelemetryBuilderOption) (*TelemetryBuilder, error) { diff --git a/scraper/scraperhelper/internal/metadatatest/generated_telemetrytest.go b/scraper/scraperhelper/internal/metadatatest/generated_telemetrytest.go index bda59ab3ea5c..f015a380c034 100644 --- a/scraper/scraperhelper/internal/metadatatest/generated_telemetrytest.go +++ b/scraper/scraperhelper/internal/metadatatest/generated_telemetrytest.go @@ -13,20 +13,23 @@ import ( "go.opentelemetry.io/collector/component/componenttest" ) +// Deprecated: [v0.119.0] Use componenttest.Telemetry type Telemetry struct { - componenttest.Telemetry + *componenttest.Telemetry } +// Deprecated: [v0.119.0] Use componenttest.NewTelemetry func SetupTelemetry(opts ...componenttest.TelemetryOption) Telemetry { return Telemetry{Telemetry: componenttest.NewTelemetry(opts...)} } +// Deprecated: [v0.119.0] Use metadatatest.AssertEqual* func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { var md metricdata.ResourceMetrics require.NoError(t, tt.Reader.Collect(context.Background(), &md)) // ensure all required metrics are present for _, want := range expected { - got := getMetric(want.Name, md) + got := getMetricFromResource(want.Name, md) metricdatatest.AssertEqual(t, want, got, opts...) } @@ -34,7 +37,71 @@ func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, require.Equal(t, len(expected), lenMetrics(md)) } -func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { +func AssertEqualScraperErroredLogRecords(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_scraper_errored_log_records", + Description: "Number of log records that were unable to be scraped. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_scraper_errored_log_records") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualScraperErroredMetricPoints(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_scraper_errored_metric_points", + Description: "Number of metric points that were unable to be scraped. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_scraper_errored_metric_points") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualScraperScrapedLogRecords(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_scraper_scraped_log_records", + Description: "Number of log records successfully scraped. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_scraper_scraped_log_records") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualScraperScrapedMetricPoints(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_scraper_scraped_metric_points", + Description: "Number of metric points successfully scraped. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_scraper_scraped_metric_points") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func getMetricFromResource(name string, got metricdata.ResourceMetrics) metricdata.Metrics { for _, sm := range got.ScopeMetrics { for _, m := range sm.Metrics { if m.Name == name { diff --git a/scraper/scraperhelper/internal/metadatatest/generated_telemetrytest_test.go b/scraper/scraperhelper/internal/metadatatest/generated_telemetrytest_test.go index 4e483c71387d..4432376c25e0 100644 --- a/scraper/scraperhelper/internal/metadatatest/generated_telemetrytest_test.go +++ b/scraper/scraperhelper/internal/metadatatest/generated_telemetrytest_test.go @@ -15,11 +15,9 @@ import ( func TestSetupTelemetry(t *testing.T) { testTel := SetupTelemetry() - tb, err := metadata.NewTelemetryBuilder( - testTel.NewTelemetrySettings(), - ) + tb, err := metadata.NewTelemetryBuilder(testTel.NewTelemetrySettings()) require.NoError(t, err) - require.NotNil(t, tb) + defer tb.Shutdown() tb.ScraperErroredLogRecords.Add(context.Background(), 1) tb.ScraperErroredMetricPoints.Add(context.Background(), 1) tb.ScraperScrapedLogRecords.Add(context.Background(), 1) @@ -75,5 +73,18 @@ func TestSetupTelemetry(t *testing.T) { }, }, }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + AssertEqualScraperErroredLogRecords(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualScraperErroredMetricPoints(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualScraperScrapedLogRecords(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualScraperScrapedMetricPoints(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + require.NoError(t, testTel.Shutdown(context.Background())) } diff --git a/scraper/scraperhelper/obs_logs_test.go b/scraper/scraperhelper/obs_logs_test.go index 4b689db8a859..854d7058ec66 100644 --- a/scraper/scraperhelper/obs_logs_test.go +++ b/scraper/scraperhelper/obs_logs_test.go @@ -16,6 +16,7 @@ import ( "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/testdata" "go.opentelemetry.io/collector/scraper" @@ -23,12 +24,12 @@ import ( ) func TestScrapeLogsDataOp(t *testing.T) { - tt := metadatatest.SetupTelemetry() - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + tel := componenttest.NewTelemetry() + t.Cleanup(func() { require.NoError(t, tel.Shutdown(context.Background())) }) - tel := tt.NewTelemetrySettings() + set := tel.NewTelemetrySettings() - parentCtx, parentSpan := tel.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) + parentCtx, parentSpan := set.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) defer parentSpan.End() params := []testParams{ @@ -41,13 +42,13 @@ func TestScrapeLogsDataOp(t *testing.T) { return testdata.GenerateLogs(params[i].items), params[i].err }) require.NoError(t, err) - sf, err := wrapObsLogs(sm, receiverID, scraperID, tel) + sf, err := wrapObsLogs(sm, receiverID, scraperID, set) require.NoError(t, err) _, err = sf.ScrapeLogs(parentCtx) require.ErrorIs(t, err, params[i].err) } - spans := tt.SpanRecorder.Ended() + spans := tel.SpanRecorder.Ended() require.Equal(t, len(params), len(spans)) var scrapedLogRecords, erroredLogRecords int @@ -77,60 +78,43 @@ func TestScrapeLogsDataOp(t *testing.T) { } } - checkScraperLogs(t, tt, receiverID, scraperID, int64(scrapedLogRecords), int64(erroredLogRecords)) + checkScraperLogs(t, tel, receiverID, scraperID, int64(scrapedLogRecords), int64(erroredLogRecords)) } func TestCheckScraperLogs(t *testing.T) { - tt := metadatatest.SetupTelemetry() - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + tel := componenttest.NewTelemetry() + t.Cleanup(func() { require.NoError(t, tel.Shutdown(context.Background())) }) sm, err := scraper.NewLogs(func(context.Context) (plog.Logs, error) { return testdata.GenerateLogs(7), nil }) require.NoError(t, err) - sf, err := wrapObsLogs(sm, receiverID, scraperID, tt.NewTelemetrySettings()) + sf, err := wrapObsLogs(sm, receiverID, scraperID, tel.NewTelemetrySettings()) require.NoError(t, err) _, err = sf.ScrapeLogs(context.Background()) require.NoError(t, err) - checkScraperLogs(t, tt, receiverID, scraperID, 7, 0) + checkScraperLogs(t, tel, receiverID, scraperID, 7, 0) } -func checkScraperLogs(t *testing.T, tt metadatatest.Telemetry, receiver component.ID, scraper component.ID, scrapedLogRecords int64, erroredLogRecords int64) { - tt.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_scraper_scraped_log_records", - Description: "Number of log records successfully scraped. [alpha]", - Unit: "{datapoints}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet( - attribute.String(receiverKey, receiver.String()), - attribute.String(scraperKey, scraper.String())), - Value: scrapedLogRecords, - }, - }, +func checkScraperLogs(t *testing.T, tel *componenttest.Telemetry, receiver component.ID, scraper component.ID, scrapedLogRecords int64, erroredLogRecords int64) { + metadatatest.AssertEqualScraperScrapedLogRecords(t, tel, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String(receiverKey, receiver.String()), + attribute.String(scraperKey, scraper.String())), + Value: scrapedLogRecords, }, - }, - { - Name: "otelcol_scraper_errored_log_records", - Description: "Number of log records that were unable to be scraped. [alpha]", - Unit: "{datapoints}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet( - attribute.String(receiverKey, receiver.String()), - attribute.String(scraperKey, scraper.String())), - Value: erroredLogRecords, - }, - }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + + metadatatest.AssertEqualScraperErroredLogRecords(t, tel, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String(receiverKey, receiver.String()), + attribute.String(scraperKey, scraper.String())), + Value: erroredLogRecords, }, - }, - }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) } diff --git a/scraper/scraperhelper/obs_metrics_test.go b/scraper/scraperhelper/obs_metrics_test.go index 7216b5a61dfb..3d72fcb74b09 100644 --- a/scraper/scraperhelper/obs_metrics_test.go +++ b/scraper/scraperhelper/obs_metrics_test.go @@ -14,10 +14,9 @@ import ( "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/sdk/metric/metricdata" "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" - sdktrace "go.opentelemetry.io/otel/sdk/trace" - "go.opentelemetry.io/otel/sdk/trace/tracetest" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/testdata" "go.opentelemetry.io/collector/scraper" @@ -39,15 +38,11 @@ type testParams struct { } func TestScrapeMetricsDataOp(t *testing.T) { - tt := metadatatest.SetupTelemetry() - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + tel := componenttest.NewTelemetry() + t.Cleanup(func() { require.NoError(t, tel.Shutdown(context.Background())) }) - tel := tt.NewTelemetrySettings() - // TODO: Add capability for tracing testing in metadatatest. - spanRecorder := new(tracetest.SpanRecorder) - tel.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(spanRecorder)) - - parentCtx, parentSpan := tel.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) + set := tel.NewTelemetrySettings() + parentCtx, parentSpan := set.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) defer parentSpan.End() params := []testParams{ @@ -60,13 +55,13 @@ func TestScrapeMetricsDataOp(t *testing.T) { return testdata.GenerateMetrics(params[i].items), params[i].err }) require.NoError(t, err) - sf, err := wrapObsMetrics(sm, receiverID, scraperID, tel) + sf, err := wrapObsMetrics(sm, receiverID, scraperID, set) require.NoError(t, err) _, err = sf.ScrapeMetrics(parentCtx) require.ErrorIs(t, err, params[i].err) } - spans := spanRecorder.Ended() + spans := tel.SpanRecorder.Ended() require.Equal(t, len(params), len(spans)) var scrapedMetricPoints, erroredMetricPoints int @@ -96,60 +91,42 @@ func TestScrapeMetricsDataOp(t *testing.T) { } } - checkScraperMetrics(t, tt, receiverID, scraperID, int64(scrapedMetricPoints), int64(erroredMetricPoints)) + checkScraperMetrics(t, tel, receiverID, scraperID, int64(scrapedMetricPoints), int64(erroredMetricPoints)) } func TestCheckScraperMetrics(t *testing.T) { - tt := metadatatest.SetupTelemetry() - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + tel := componenttest.NewTelemetry() + t.Cleanup(func() { require.NoError(t, tel.Shutdown(context.Background())) }) sm, err := scraper.NewMetrics(func(context.Context) (pmetric.Metrics, error) { return testdata.GenerateMetrics(7), nil }) require.NoError(t, err) - sf, err := wrapObsMetrics(sm, receiverID, scraperID, tt.NewTelemetrySettings()) + sf, err := wrapObsMetrics(sm, receiverID, scraperID, tel.NewTelemetrySettings()) require.NoError(t, err) _, err = sf.ScrapeMetrics(context.Background()) require.NoError(t, err) - checkScraperMetrics(t, tt, receiverID, scraperID, 7, 0) + checkScraperMetrics(t, tel, receiverID, scraperID, 7, 0) } -func checkScraperMetrics(t *testing.T, tt metadatatest.Telemetry, receiver component.ID, scraper component.ID, scrapedMetricPoints, erroredMetricPoints int64) { - tt.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_scraper_scraped_metric_points", - Description: "Number of metric points successfully scraped. [alpha]", - Unit: "{datapoints}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet( - attribute.String(receiverKey, receiver.String()), - attribute.String(scraperKey, scraper.String())), - Value: scrapedMetricPoints, - }, - }, +func checkScraperMetrics(t *testing.T, tt *componenttest.Telemetry, receiver component.ID, scraper component.ID, scrapedMetricPoints, erroredMetricPoints int64) { + metadatatest.AssertEqualScraperScrapedMetricPoints(t, tt, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String(receiverKey, receiver.String()), + attribute.String(scraperKey, scraper.String())), + Value: scrapedMetricPoints, }, - }, - { - Name: "otelcol_scraper_errored_metric_points", - Description: "Number of metric points that were unable to be scraped. [alpha]", - Unit: "{datapoints}", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet( - attribute.String(receiverKey, receiver.String()), - attribute.String(scraperKey, scraper.String())), - Value: erroredMetricPoints, - }, - }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + metadatatest.AssertEqualScraperErroredMetricPoints(t, tt, + []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + attribute.String(receiverKey, receiver.String()), + attribute.String(scraperKey, scraper.String())), + Value: erroredMetricPoints, }, - }, - }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreExemplars()) } diff --git a/scraper/scrapertest/go.mod b/scraper/scrapertest/go.mod index b13a5953c815..9c6b2e8839b3 100644 --- a/scraper/scrapertest/go.mod +++ b/scraper/scrapertest/go.mod @@ -30,9 +30,9 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect ) replace go.opentelemetry.io/collector/component/componenttest => ../../component/componenttest diff --git a/scraper/scrapertest/go.sum b/scraper/scrapertest/go.sum index 8f7c2d100559..fe8cdaf80bc3 100644 --- a/scraper/scrapertest/go.sum +++ b/scraper/scrapertest/go.sum @@ -81,11 +81,11 @@ 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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/service/attributes.go b/service/attributes.go index f2587b331308..65c57b1b5cf0 100644 --- a/service/attributes.go +++ b/service/attributes.go @@ -4,24 +4,31 @@ package service // import "go.opentelemetry.io/collector/service" import ( + config "go.opentelemetry.io/contrib/config/v0.3.0" sdkresource "go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/collector/service/telemetry" ) -func attributes(res *sdkresource.Resource, cfg telemetry.Config) map[string]any { - attrs := map[string]any{} +func attributes(res *sdkresource.Resource, cfg telemetry.Config) []config.AttributeNameValue { + attrsMap := map[string]any{} for _, r := range res.Attributes() { - attrs[string(r.Key)] = r.Value.AsString() + attrsMap[string(r.Key)] = r.Value.AsString() } for k, v := range cfg.Resource { if v != nil { - attrs[k] = *v + attrsMap[k] = *v } else { // the new value is nil, delete the existing key - delete(attrs, k) + delete(attrsMap, k) } } + + var attrs []config.AttributeNameValue + for k, v := range attrsMap { + attrs = append(attrs, config.AttributeNameValue{Name: k, Value: v}) + } + return attrs } diff --git a/service/attributes_test.go b/service/attributes_test.go index b9205ba84817..c463917b3ef0 100644 --- a/service/attributes_test.go +++ b/service/attributes_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/require" + config "go.opentelemetry.io/contrib/config/v0.3.0" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/service/internal/resource" @@ -18,46 +19,50 @@ func TestAttributes(t *testing.T) { name string cfg telemetry.Config buildInfo component.BuildInfo - wantAttributes map[string]any + wantAttributes []config.AttributeNameValue }{ { name: "no build info and no resource config", cfg: telemetry.Config{}, - wantAttributes: map[string]any{"service.name": "", "service.version": "", "service.instance.id": ""}, + wantAttributes: []config.AttributeNameValue{{Name: "service.name", Value: ""}, {Name: "service.version", Value: ""}, {Name: "service.instance.id", Value: ""}}, }, { name: "build info and no resource config", cfg: telemetry.Config{}, buildInfo: component.BuildInfo{Command: "otelcoltest", Version: "0.0.0-test"}, - wantAttributes: map[string]any{"service.name": "otelcoltest", "service.version": "0.0.0-test", "service.instance.id": ""}, + wantAttributes: []config.AttributeNameValue{{Name: "service.name", Value: "otelcoltest"}, {Name: "service.version", Value: "0.0.0-test"}, {Name: "service.instance.id", Value: ""}}, }, { name: "no build info and resource config", - cfg: telemetry.Config{Resource: map[string]*string{"service.name": newPtr("resource.name"), "service.version": newPtr("resource.version"), "test": newPtr("test")}}, - wantAttributes: map[string]any{"service.name": "resource.name", "service.version": "resource.version", "test": "test", "service.instance.id": ""}, + cfg: telemetry.Config{Resource: map[string]*string{"service.name": ptr("resource.name"), "service.version": ptr("resource.version"), "test": ptr("test")}}, + wantAttributes: []config.AttributeNameValue{{Name: "service.name", Value: "resource.name"}, {Name: "service.version", Value: "resource.version"}, {Name: "test", Value: "test"}, {Name: "service.instance.id", Value: ""}}, }, { name: "build info and resource config", buildInfo: component.BuildInfo{Command: "otelcoltest", Version: "0.0.0-test"}, - cfg: telemetry.Config{Resource: map[string]*string{"service.name": newPtr("resource.name"), "service.version": newPtr("resource.version"), "test": newPtr("test")}}, - wantAttributes: map[string]any{"service.name": "resource.name", "service.version": "resource.version", "test": "test", "service.instance.id": ""}, + cfg: telemetry.Config{Resource: map[string]*string{"service.name": ptr("resource.name"), "service.version": ptr("resource.version"), "test": ptr("test")}}, + wantAttributes: []config.AttributeNameValue{{Name: "service.name", Value: "resource.name"}, {Name: "service.version", Value: "resource.version"}, {Name: "test", Value: "test"}, {Name: "service.instance.id", Value: ""}}, }, { name: "deleting a nil value", buildInfo: component.BuildInfo{Command: "otelcoltest", Version: "0.0.0-test"}, - cfg: telemetry.Config{Resource: map[string]*string{"service.name": nil, "service.version": newPtr("resource.version"), "test": newPtr("test")}}, - wantAttributes: map[string]any{"service.version": "resource.version", "test": "test", "service.instance.id": ""}, + cfg: telemetry.Config{Resource: map[string]*string{"service.name": nil, "service.version": ptr("resource.version"), "test": ptr("test")}}, + wantAttributes: []config.AttributeNameValue{{Name: "service.version", Value: "resource.version"}, {Name: "test", Value: "test"}, {Name: "service.instance.id", Value: ""}}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { attrs := attributes(resource.New(tt.buildInfo, tt.cfg.Resource), tt.cfg) require.Len(t, attrs, len(tt.wantAttributes)) - for k, v := range tt.wantAttributes { - if k == "service.instance.id" { - require.NotNil(t, attrs[k]) + gotMap := map[string]any{} + for _, v := range attrs { + gotMap[v.Name] = v.Value + } + for _, v := range tt.wantAttributes { + if v.Name == "service.instance.id" { + require.NotNil(t, gotMap[v.Name]) } else { - require.Equal(t, v, attrs[k]) + require.Equal(t, v.Value, gotMap[v.Name]) } } }) diff --git a/service/config.go b/service/config.go index 9c3eb4d7d74a..3104faaebd4d 100644 --- a/service/config.go +++ b/service/config.go @@ -4,8 +4,6 @@ package service // import "go.opentelemetry.io/collector/service" import ( - "fmt" - "go.opentelemetry.io/collector/service/extensions" "go.opentelemetry.io/collector/service/pipelines" "go.opentelemetry.io/collector/service/telemetry" @@ -22,15 +20,3 @@ type Config struct { // Pipelines are the set of data pipelines configured for the service. Pipelines pipelines.Config `mapstructure:"pipelines"` } - -func (cfg *Config) Validate() error { - if err := cfg.Pipelines.Validate(); err != nil { - return fmt.Errorf("service::pipelines config validation failed: %w", err) - } - - if err := cfg.Telemetry.Validate(); err != nil { - fmt.Printf("service::telemetry config validation failed: %v\n", err) - } - - return nil -} diff --git a/service/config_test.go b/service/config_test.go index ab292a2665de..8ce13a7ec338 100644 --- a/service/config_test.go +++ b/service/config_test.go @@ -5,11 +5,10 @@ package service import ( "errors" - "fmt" "testing" "github.com/stretchr/testify/assert" - "go.opentelemetry.io/contrib/config" + config "go.opentelemetry.io/contrib/config/v0.3.0" "go.uber.org/zap/zapcore" "go.opentelemetry.io/collector/component" @@ -48,7 +47,7 @@ func TestConfigValidate(t *testing.T) { pipe.Processors = append(pipe.Processors, pipe.Processors...) return cfg }, - expected: fmt.Errorf(`service::pipelines config validation failed: %w`, fmt.Errorf(`pipeline "traces": %w`, errors.New(`references processor "nop" multiple times`))), + expected: errors.New(`references processor "nop" multiple times`), }, { name: "invalid-service-pipeline-type", @@ -61,7 +60,7 @@ func TestConfigValidate(t *testing.T) { } return cfg }, - expected: fmt.Errorf(`service::pipelines config validation failed: %w`, errors.New(`pipeline "wrongtype": unknown signal "wrongtype"`)), + expected: errors.New(`pipeline "wrongtype": unknown signal "wrongtype"`), }, { name: "invalid-telemetry-metric-config", @@ -71,14 +70,19 @@ func TestConfigValidate(t *testing.T) { cfg.Telemetry.Metrics.Readers = nil return cfg }, - expected: nil, + expected: errors.New("collector telemetry metrics reader should exist when metric level is not none"), }, } for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { cfg := tt.cfgFn() - assert.Equal(t, tt.expected, cfg.Validate()) + err := component.ValidateConfig(cfg) + if tt.expected != nil { + assert.ErrorContains(t, err, tt.expected.Error()) + } else { + assert.NoError(t, err) + } }) } } @@ -100,7 +104,7 @@ func generateConfig() *Config { Level: configtelemetry.LevelNormal, Readers: []config.MetricReader{ { - Pull: &config.PullMetricReader{Exporter: config.MetricExporter{Prometheus: &config.Prometheus{ + Pull: &config.PullMetricReader{Exporter: config.PullMetricExporter{Prometheus: &config.Prometheus{ Host: newPtr("localhost"), Port: newPtr(8080), }}}, diff --git a/service/go.mod b/service/go.mod index 7bdfc98c5c29..a35f4e6d3ee4 100644 --- a/service/go.mod +++ b/service/go.mod @@ -4,7 +4,6 @@ go 1.22.0 require ( github.com/google/uuid v1.6.0 - github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_model v0.6.1 github.com/prometheus/common v0.62.0 github.com/shirou/gopsutil/v4 v4.24.12 @@ -44,15 +43,9 @@ require ( go.opentelemetry.io/collector/receiver/xreceiver v0.118.0 go.opentelemetry.io/collector/semconv v0.118.0 go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 - go.opentelemetry.io/contrib/config v0.10.0 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 + go.opentelemetry.io/contrib/config v0.14.0 go.opentelemetry.io/contrib/propagators/b3 v1.34.0 go.opentelemetry.io/otel v1.34.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 - go.opentelemetry.io/otel/exporters/prometheus v0.56.0 - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 go.opentelemetry.io/otel/log v0.10.0 go.opentelemetry.io/otel/metric v1.34.0 go.opentelemetry.io/otel/sdk v1.34.0 @@ -62,7 +55,6 @@ require ( go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 gonum.org/v1/gonum v0.15.1 - google.golang.org/grpc v1.69.4 ) require ( @@ -95,6 +87,7 @@ require ( github.com/pierrec/lz4/v4 v4.1.22 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rs/cors v1.11.1 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect @@ -108,21 +101,28 @@ require ( go.opentelemetry.io/collector/config/configtls v1.24.0 // indirect go.opentelemetry.io/collector/consumer/consumererror v0.118.0 // indirect go.opentelemetry.io/collector/extension/auth v0.118.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect go.opentelemetry.io/contrib/zpages v0.59.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 // indirect - go.opentelemetry.io/otel/sdk/log v0.7.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.56.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.10.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect golang.org/x/net v0.34.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/grpc v1.70.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/service/go.sum b/service/go.sum index 45648f9eb572..85c80f75f53d 100644 --- a/service/go.sum +++ b/service/go.sum @@ -105,10 +105,8 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/bridges/otelzap v0.9.0 h1:f+xpAfhQTjR8beiSMe1bnT/25PkeyWmOcI+SjXWguNw= go.opentelemetry.io/contrib/bridges/otelzap v0.9.0/go.mod h1:T1Z1jyS5FttgQoF6UcGhnM+gF9wU32B4lHO69nXw4FE= -go.opentelemetry.io/contrib/config v0.10.0 h1:2JknAzMaYjxrHkTnZh3eOme/Y2P5eHE2SWfhfV6Xd6c= -go.opentelemetry.io/contrib/config v0.10.0/go.mod h1:aND2M6/KfNkntI5cyvHriR/zvZgPf8j9yETdSmvpfmc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= +go.opentelemetry.io/contrib/config v0.14.0 h1:QAG8uHNp5ZiCkpT7XggSmg5AyW1sA0LgypMoXgBB1+4= +go.opentelemetry.io/contrib/config v0.14.0/go.mod h1:77rDmFPqBae5jtQ2C78RuDTHz4P27C8LzoN0MZyumYQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= go.opentelemetry.io/contrib/propagators/b3 v1.34.0 h1:9pQdCEvV/6RWQmag94D6rhU+A4rzUhYBEJ8bpscx5p8= @@ -117,34 +115,36 @@ go.opentelemetry.io/contrib/zpages v0.59.0 h1:t0H5zUy8fifIhRuVwm2FrA/D70Kk10SSpA go.opentelemetry.io/contrib/zpages v0.59.0/go.mod h1:9wo+yUPvHnBQEzoHJ8R3nA/Q5rkef7HjtLlSFI0Tgrc= go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0 h1:mMOmtYie9Fx6TSVzw4W+NTpvoaS1JWWga37oI1a/4qQ= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.7.0/go.mod h1:yy7nDsMMBUkD+jeekJ36ur5f3jJIrmCwUrY67VFhNpA= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 h1:5dTKu4I5Dn4P2hxyW3l3jTaZx9ACgg0ECos1eAVrheY= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0/go.mod h1:P5HcUI8obLrCCmM3sbVBohZFH34iszk/+CPWuakZWL8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 h1:q/heq5Zh8xV1+7GoMGJpTxM2Lhq5+bFxB29tshuRuw0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0/go.mod h1:leO2CSTg0Y+LyvmR7Wm4pUxE8KAmaM2GCVx7O+RATLA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 h1:ajl4QczuJVA2TU9W9AGw++86Xga/RKt//16z/yxPgdk= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0/go.mod h1:Vn3/rlOJ3ntf/Q3zAI0V5lDnTbHGaUsNUeF6nZmm7pA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 h1:opwv08VbCZ8iecIWs+McMdHRcAXzjAeda3uG2kI/hcA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0/go.mod h1:oOP3ABpW7vFHulLpE8aYtNBodrHhMTrvfxUXGvqm7Ac= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4= go.opentelemetry.io/otel/exporters/prometheus v0.56.0 h1:GnCIi0QyG0yy2MrJLzVrIM7laaJstj//flf1zEJCG+E= go.opentelemetry.io/otel/exporters/prometheus v0.56.0/go.mod h1:JQcVZtbIIPM+7SWBB+T6FK+xunlyidwLp++fN0sUaOk= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0 h1:TwmL3O3fRR80m8EshBrd8YydEZMcUCsZXzOUlnFohwM= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.7.0/go.mod h1:tH98dDv5KPmPThswbXA0fr0Lwfs+OhK8HgaCo7PjRrk= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 h1:GKCEAZLEpEf78cUvudQdTg0aET2ObOZRB2HtXA0qPAI= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0/go.mod h1:9/zqSWLCmHT/9Jo6fYeUDRRogOLL60ABLsHWS99lF8s= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 h1:czJDQwFrMbOr9Kk+BPo1y8WZIIFIK58SA1kykuVeiOU= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0/go.mod h1:lT7bmsxOe58Tq+JIOkTQMCGXdu47oA+VJKLZHbaBKbs= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 h1:UGZ1QwZWY67Z6BmckTU+9Rxn04m2bD3gD6Mk0OIOCPk= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0/go.mod h1:fcwWuDuaObkkChiDlhEpSq9+X1C0omv+s5mBtToAQ64= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 h1:jBpDk4HAUsrnVO1FsfCfCOTEc/MkInJmvfCHYLFiT80= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0/go.mod h1:H9LUIM1daaeZaz91vZcfeM0fejXPmgCYE8ZhzqfJuiU= go.opentelemetry.io/otel/log v0.10.0 h1:1CXmspaRITvFcjA4kyVszuG4HjA61fPDxMb7q3BuyF0= go.opentelemetry.io/otel/log v0.10.0/go.mod h1:PbVdm9bXKku/gL0oFfUF4wwsQsOPlpo4VEqjvxih+FM= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/sdk/log v0.7.0 h1:dXkeI2S0MLc5g0/AwxTZv6EUEjctiH8aG14Am56NTmQ= -go.opentelemetry.io/otel/sdk/log v0.7.0/go.mod h1:oIRXpW+WD6M8BuGj5rtS0aRu/86cbDV/dAfNaZBIjYM= +go.opentelemetry.io/otel/sdk/log v0.10.0 h1:lR4teQGWfeDVGoute6l0Ou+RpFqQ9vaPdrNJlST0bvw= +go.opentelemetry.io/otel/sdk/log v0.10.0/go.mod h1:A+V1UTWREhWAittaQEG4bYm4gAZa6xnvVu+xKrIRkzo= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= @@ -200,10 +200,10 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1: google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/service/internal/metadata/generated_telemetry.go b/service/internal/metadata/generated_telemetry.go index 90cccbcd35c9..99cf9b2839b0 100644 --- a/service/internal/metadata/generated_telemetry.go +++ b/service/internal/metadata/generated_telemetry.go @@ -5,8 +5,10 @@ package metadata import ( "context" "errors" + "sync" "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/embedded" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" @@ -23,19 +25,27 @@ func Tracer(settings component.TelemetrySettings) trace.Tracer { // TelemetryBuilder provides an interface for components to report telemetry // as defined in metadata and user config. type TelemetryBuilder struct { - meter metric.Meter - ProcessCPUSeconds metric.Float64ObservableCounter - observeProcessCPUSeconds func(context.Context, metric.Observer) error - ProcessMemoryRss metric.Int64ObservableGauge - observeProcessMemoryRss func(context.Context, metric.Observer) error - ProcessRuntimeHeapAllocBytes metric.Int64ObservableGauge - observeProcessRuntimeHeapAllocBytes func(context.Context, metric.Observer) error - ProcessRuntimeTotalAllocBytes metric.Int64ObservableCounter - observeProcessRuntimeTotalAllocBytes func(context.Context, metric.Observer) error - ProcessRuntimeTotalSysMemoryBytes metric.Int64ObservableGauge + meter metric.Meter + mu sync.Mutex + registrations []metric.Registration + ProcessCPUSeconds metric.Float64ObservableCounter + // TODO: Remove in v0.119.0 when remove deprecated funcs. + observeProcessCPUSeconds func(context.Context, metric.Observer) error + ProcessMemoryRss metric.Int64ObservableGauge + // TODO: Remove in v0.119.0 when remove deprecated funcs. + observeProcessMemoryRss func(context.Context, metric.Observer) error + ProcessRuntimeHeapAllocBytes metric.Int64ObservableGauge + // TODO: Remove in v0.119.0 when remove deprecated funcs. + observeProcessRuntimeHeapAllocBytes func(context.Context, metric.Observer) error + ProcessRuntimeTotalAllocBytes metric.Int64ObservableCounter + // TODO: Remove in v0.119.0 when remove deprecated funcs. + observeProcessRuntimeTotalAllocBytes func(context.Context, metric.Observer) error + ProcessRuntimeTotalSysMemoryBytes metric.Int64ObservableGauge + // TODO: Remove in v0.119.0 when remove deprecated funcs. observeProcessRuntimeTotalSysMemoryBytes func(context.Context, metric.Observer) error ProcessUptime metric.Float64ObservableCounter - observeProcessUptime func(context.Context, metric.Observer) error + // TODO: Remove in v0.119.0 when remove deprecated funcs. + observeProcessUptime func(context.Context, metric.Observer) error } // TelemetryBuilderOption applies changes to default builder. @@ -49,7 +59,7 @@ func (tbof telemetryBuilderOptionFunc) apply(mb *TelemetryBuilder) { tbof(mb) } -// WithProcessCPUSecondsCallback sets callback for observable ProcessCPUSeconds metric. +// Deprecated: [v0.119.0] use RegisterProcessCPUSecondsCallback. func WithProcessCPUSecondsCallback(cb func() float64, opts ...metric.ObserveOption) TelemetryBuilderOption { return telemetryBuilderOptionFunc(func(builder *TelemetryBuilder) { builder.observeProcessCPUSeconds = func(_ context.Context, o metric.Observer) error { @@ -59,7 +69,22 @@ func WithProcessCPUSecondsCallback(cb func() float64, opts ...metric.ObserveOpti }) } -// WithProcessMemoryRssCallback sets callback for observable ProcessMemoryRss metric. +// RegisterProcessCPUSecondsCallback sets callback for observable ProcessCPUSeconds metric. +func (builder *TelemetryBuilder) RegisterProcessCPUSecondsCallback(cb metric.Float64Callback) error { + reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { + cb(ctx, &observerFloat64{inst: builder.ProcessCPUSeconds, obs: o}) + return nil + }, builder.ProcessCPUSeconds) + if err != nil { + return err + } + builder.mu.Lock() + defer builder.mu.Unlock() + builder.registrations = append(builder.registrations, reg) + return nil +} + +// Deprecated: [v0.119.0] use RegisterProcessMemoryRssCallback. func WithProcessMemoryRssCallback(cb func() int64, opts ...metric.ObserveOption) TelemetryBuilderOption { return telemetryBuilderOptionFunc(func(builder *TelemetryBuilder) { builder.observeProcessMemoryRss = func(_ context.Context, o metric.Observer) error { @@ -69,7 +94,22 @@ func WithProcessMemoryRssCallback(cb func() int64, opts ...metric.ObserveOption) }) } -// WithProcessRuntimeHeapAllocBytesCallback sets callback for observable ProcessRuntimeHeapAllocBytes metric. +// RegisterProcessMemoryRssCallback sets callback for observable ProcessMemoryRss metric. +func (builder *TelemetryBuilder) RegisterProcessMemoryRssCallback(cb metric.Int64Callback) error { + reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { + cb(ctx, &observerInt64{inst: builder.ProcessMemoryRss, obs: o}) + return nil + }, builder.ProcessMemoryRss) + if err != nil { + return err + } + builder.mu.Lock() + defer builder.mu.Unlock() + builder.registrations = append(builder.registrations, reg) + return nil +} + +// Deprecated: [v0.119.0] use RegisterProcessRuntimeHeapAllocBytesCallback. func WithProcessRuntimeHeapAllocBytesCallback(cb func() int64, opts ...metric.ObserveOption) TelemetryBuilderOption { return telemetryBuilderOptionFunc(func(builder *TelemetryBuilder) { builder.observeProcessRuntimeHeapAllocBytes = func(_ context.Context, o metric.Observer) error { @@ -79,7 +119,22 @@ func WithProcessRuntimeHeapAllocBytesCallback(cb func() int64, opts ...metric.Ob }) } -// WithProcessRuntimeTotalAllocBytesCallback sets callback for observable ProcessRuntimeTotalAllocBytes metric. +// RegisterProcessRuntimeHeapAllocBytesCallback sets callback for observable ProcessRuntimeHeapAllocBytes metric. +func (builder *TelemetryBuilder) RegisterProcessRuntimeHeapAllocBytesCallback(cb metric.Int64Callback) error { + reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { + cb(ctx, &observerInt64{inst: builder.ProcessRuntimeHeapAllocBytes, obs: o}) + return nil + }, builder.ProcessRuntimeHeapAllocBytes) + if err != nil { + return err + } + builder.mu.Lock() + defer builder.mu.Unlock() + builder.registrations = append(builder.registrations, reg) + return nil +} + +// Deprecated: [v0.119.0] use RegisterProcessRuntimeTotalAllocBytesCallback. func WithProcessRuntimeTotalAllocBytesCallback(cb func() int64, opts ...metric.ObserveOption) TelemetryBuilderOption { return telemetryBuilderOptionFunc(func(builder *TelemetryBuilder) { builder.observeProcessRuntimeTotalAllocBytes = func(_ context.Context, o metric.Observer) error { @@ -89,7 +144,22 @@ func WithProcessRuntimeTotalAllocBytesCallback(cb func() int64, opts ...metric.O }) } -// WithProcessRuntimeTotalSysMemoryBytesCallback sets callback for observable ProcessRuntimeTotalSysMemoryBytes metric. +// RegisterProcessRuntimeTotalAllocBytesCallback sets callback for observable ProcessRuntimeTotalAllocBytes metric. +func (builder *TelemetryBuilder) RegisterProcessRuntimeTotalAllocBytesCallback(cb metric.Int64Callback) error { + reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { + cb(ctx, &observerInt64{inst: builder.ProcessRuntimeTotalAllocBytes, obs: o}) + return nil + }, builder.ProcessRuntimeTotalAllocBytes) + if err != nil { + return err + } + builder.mu.Lock() + defer builder.mu.Unlock() + builder.registrations = append(builder.registrations, reg) + return nil +} + +// Deprecated: [v0.119.0] use RegisterProcessRuntimeTotalSysMemoryBytesCallback. func WithProcessRuntimeTotalSysMemoryBytesCallback(cb func() int64, opts ...metric.ObserveOption) TelemetryBuilderOption { return telemetryBuilderOptionFunc(func(builder *TelemetryBuilder) { builder.observeProcessRuntimeTotalSysMemoryBytes = func(_ context.Context, o metric.Observer) error { @@ -99,7 +169,22 @@ func WithProcessRuntimeTotalSysMemoryBytesCallback(cb func() int64, opts ...metr }) } -// WithProcessUptimeCallback sets callback for observable ProcessUptime metric. +// RegisterProcessRuntimeTotalSysMemoryBytesCallback sets callback for observable ProcessRuntimeTotalSysMemoryBytes metric. +func (builder *TelemetryBuilder) RegisterProcessRuntimeTotalSysMemoryBytesCallback(cb metric.Int64Callback) error { + reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { + cb(ctx, &observerInt64{inst: builder.ProcessRuntimeTotalSysMemoryBytes, obs: o}) + return nil + }, builder.ProcessRuntimeTotalSysMemoryBytes) + if err != nil { + return err + } + builder.mu.Lock() + defer builder.mu.Unlock() + builder.registrations = append(builder.registrations, reg) + return nil +} + +// Deprecated: [v0.119.0] use RegisterProcessUptimeCallback. func WithProcessUptimeCallback(cb func() float64, opts ...metric.ObserveOption) TelemetryBuilderOption { return telemetryBuilderOptionFunc(func(builder *TelemetryBuilder) { builder.observeProcessUptime = func(_ context.Context, o metric.Observer) error { @@ -109,6 +194,50 @@ func WithProcessUptimeCallback(cb func() float64, opts ...metric.ObserveOption) }) } +// RegisterProcessUptimeCallback sets callback for observable ProcessUptime metric. +func (builder *TelemetryBuilder) RegisterProcessUptimeCallback(cb metric.Float64Callback) error { + reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error { + cb(ctx, &observerFloat64{inst: builder.ProcessUptime, obs: o}) + return nil + }, builder.ProcessUptime) + if err != nil { + return err + } + builder.mu.Lock() + defer builder.mu.Unlock() + builder.registrations = append(builder.registrations, reg) + return nil +} + +type observerInt64 struct { + embedded.Int64Observer + inst metric.Int64Observable + obs metric.Observer +} + +func (oi *observerInt64) Observe(value int64, opts ...metric.ObserveOption) { + oi.obs.ObserveInt64(oi.inst, value, opts...) +} + +type observerFloat64 struct { + embedded.Float64Observer + inst metric.Float64Observable + obs metric.Observer +} + +func (oi *observerFloat64) Observe(value float64, opts ...metric.ObserveOption) { + oi.obs.ObserveFloat64(oi.inst, value, opts...) +} + +// Shutdown unregister all registered callbacks for async instruments. +func (builder *TelemetryBuilder) Shutdown() { + builder.mu.Lock() + defer builder.mu.Unlock() + for _, reg := range builder.registrations { + reg.Unregister() + } +} + // NewTelemetryBuilder provides a struct with methods to update all internal telemetry // for a component func NewTelemetryBuilder(settings component.TelemetrySettings, options ...TelemetryBuilderOption) (*TelemetryBuilder, error) { @@ -124,47 +253,77 @@ func NewTelemetryBuilder(settings component.TelemetrySettings, options ...Teleme metric.WithUnit("s"), ) errs = errors.Join(errs, err) - _, err = builder.meter.RegisterCallback(builder.observeProcessCPUSeconds, builder.ProcessCPUSeconds) - errs = errors.Join(errs, err) + if builder.observeProcessCPUSeconds != nil { + reg, err := builder.meter.RegisterCallback(builder.observeProcessCPUSeconds, builder.ProcessCPUSeconds) + errs = errors.Join(errs, err) + if err == nil { + builder.registrations = append(builder.registrations, reg) + } + } builder.ProcessMemoryRss, err = builder.meter.Int64ObservableGauge( "otelcol_process_memory_rss", metric.WithDescription("Total physical memory (resident set size) [alpha]"), metric.WithUnit("By"), ) errs = errors.Join(errs, err) - _, err = builder.meter.RegisterCallback(builder.observeProcessMemoryRss, builder.ProcessMemoryRss) - errs = errors.Join(errs, err) + if builder.observeProcessMemoryRss != nil { + reg, err := builder.meter.RegisterCallback(builder.observeProcessMemoryRss, builder.ProcessMemoryRss) + errs = errors.Join(errs, err) + if err == nil { + builder.registrations = append(builder.registrations, reg) + } + } builder.ProcessRuntimeHeapAllocBytes, err = builder.meter.Int64ObservableGauge( "otelcol_process_runtime_heap_alloc_bytes", metric.WithDescription("Bytes of allocated heap objects (see 'go doc runtime.MemStats.HeapAlloc') [alpha]"), metric.WithUnit("By"), ) errs = errors.Join(errs, err) - _, err = builder.meter.RegisterCallback(builder.observeProcessRuntimeHeapAllocBytes, builder.ProcessRuntimeHeapAllocBytes) - errs = errors.Join(errs, err) + if builder.observeProcessRuntimeHeapAllocBytes != nil { + reg, err := builder.meter.RegisterCallback(builder.observeProcessRuntimeHeapAllocBytes, builder.ProcessRuntimeHeapAllocBytes) + errs = errors.Join(errs, err) + if err == nil { + builder.registrations = append(builder.registrations, reg) + } + } builder.ProcessRuntimeTotalAllocBytes, err = builder.meter.Int64ObservableCounter( "otelcol_process_runtime_total_alloc_bytes", metric.WithDescription("Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc') [alpha]"), metric.WithUnit("By"), ) errs = errors.Join(errs, err) - _, err = builder.meter.RegisterCallback(builder.observeProcessRuntimeTotalAllocBytes, builder.ProcessRuntimeTotalAllocBytes) - errs = errors.Join(errs, err) + if builder.observeProcessRuntimeTotalAllocBytes != nil { + reg, err := builder.meter.RegisterCallback(builder.observeProcessRuntimeTotalAllocBytes, builder.ProcessRuntimeTotalAllocBytes) + errs = errors.Join(errs, err) + if err == nil { + builder.registrations = append(builder.registrations, reg) + } + } builder.ProcessRuntimeTotalSysMemoryBytes, err = builder.meter.Int64ObservableGauge( "otelcol_process_runtime_total_sys_memory_bytes", metric.WithDescription("Total bytes of memory obtained from the OS (see 'go doc runtime.MemStats.Sys') [alpha]"), metric.WithUnit("By"), ) errs = errors.Join(errs, err) - _, err = builder.meter.RegisterCallback(builder.observeProcessRuntimeTotalSysMemoryBytes, builder.ProcessRuntimeTotalSysMemoryBytes) - errs = errors.Join(errs, err) + if builder.observeProcessRuntimeTotalSysMemoryBytes != nil { + reg, err := builder.meter.RegisterCallback(builder.observeProcessRuntimeTotalSysMemoryBytes, builder.ProcessRuntimeTotalSysMemoryBytes) + errs = errors.Join(errs, err) + if err == nil { + builder.registrations = append(builder.registrations, reg) + } + } builder.ProcessUptime, err = builder.meter.Float64ObservableCounter( "otelcol_process_uptime", metric.WithDescription("Uptime of the process [alpha]"), metric.WithUnit("s"), ) errs = errors.Join(errs, err) - _, err = builder.meter.RegisterCallback(builder.observeProcessUptime, builder.ProcessUptime) - errs = errors.Join(errs, err) + if builder.observeProcessUptime != nil { + reg, err := builder.meter.RegisterCallback(builder.observeProcessUptime, builder.ProcessUptime) + errs = errors.Join(errs, err) + if err == nil { + builder.registrations = append(builder.registrations, reg) + } + } return &builder, errs } diff --git a/service/internal/metadatatest/generated_telemetrytest.go b/service/internal/metadatatest/generated_telemetrytest.go index bda59ab3ea5c..8f988ab5952e 100644 --- a/service/internal/metadatatest/generated_telemetrytest.go +++ b/service/internal/metadatatest/generated_telemetrytest.go @@ -13,20 +13,23 @@ import ( "go.opentelemetry.io/collector/component/componenttest" ) +// Deprecated: [v0.119.0] Use componenttest.Telemetry type Telemetry struct { - componenttest.Telemetry + *componenttest.Telemetry } +// Deprecated: [v0.119.0] Use componenttest.NewTelemetry func SetupTelemetry(opts ...componenttest.TelemetryOption) Telemetry { return Telemetry{Telemetry: componenttest.NewTelemetry(opts...)} } +// Deprecated: [v0.119.0] Use metadatatest.AssertEqual* func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { var md metricdata.ResourceMetrics require.NoError(t, tt.Reader.Collect(context.Background(), &md)) // ensure all required metrics are present for _, want := range expected { - got := getMetric(want.Name, md) + got := getMetricFromResource(want.Name, md) metricdatatest.AssertEqual(t, want, got, opts...) } @@ -34,7 +37,97 @@ func (tt *Telemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, require.Equal(t, len(expected), lenMetrics(md)) } -func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { +func AssertEqualProcessCPUSeconds(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[float64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_process_cpu_seconds", + Description: "Total CPU user and system time in seconds [alpha]", + Unit: "s", + Data: metricdata.Sum[float64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_process_cpu_seconds") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessMemoryRss(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_process_memory_rss", + Description: "Total physical memory (resident set size) [alpha]", + Unit: "By", + Data: metricdata.Gauge[int64]{ + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_process_memory_rss") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessRuntimeHeapAllocBytes(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_process_runtime_heap_alloc_bytes", + Description: "Bytes of allocated heap objects (see 'go doc runtime.MemStats.HeapAlloc') [alpha]", + Unit: "By", + Data: metricdata.Gauge[int64]{ + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_process_runtime_heap_alloc_bytes") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessRuntimeTotalAllocBytes(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_process_runtime_total_alloc_bytes", + Description: "Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc') [alpha]", + Unit: "By", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_process_runtime_total_alloc_bytes") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessRuntimeTotalSysMemoryBytes(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_process_runtime_total_sys_memory_bytes", + Description: "Total bytes of memory obtained from the OS (see 'go doc runtime.MemStats.Sys') [alpha]", + Unit: "By", + Data: metricdata.Gauge[int64]{ + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_process_runtime_total_sys_memory_bytes") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func AssertEqualProcessUptime(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[float64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_process_uptime", + Description: "Uptime of the process [alpha]", + Unit: "s", + Data: metricdata.Sum[float64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_process_uptime") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} + +func getMetricFromResource(name string, got metricdata.ResourceMetrics) metricdata.Metrics { for _, sm := range got.ScopeMetrics { for _, m := range sm.Metrics { if m.Name == name { diff --git a/service/internal/metadatatest/generated_telemetrytest_test.go b/service/internal/metadatatest/generated_telemetrytest_test.go index 70f39cdcd0e7..fb882a8faf19 100644 --- a/service/internal/metadatatest/generated_telemetrytest_test.go +++ b/service/internal/metadatatest/generated_telemetrytest_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/sdk/metric/metricdata" "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" @@ -15,17 +16,33 @@ import ( func TestSetupTelemetry(t *testing.T) { testTel := SetupTelemetry() - tb, err := metadata.NewTelemetryBuilder( - testTel.NewTelemetrySettings(), - metadata.WithProcessCPUSecondsCallback(func() float64 { return 1 }), - metadata.WithProcessMemoryRssCallback(func() int64 { return 1 }), - metadata.WithProcessRuntimeHeapAllocBytesCallback(func() int64 { return 1 }), - metadata.WithProcessRuntimeTotalAllocBytesCallback(func() int64 { return 1 }), - metadata.WithProcessRuntimeTotalSysMemoryBytesCallback(func() int64 { return 1 }), - metadata.WithProcessUptimeCallback(func() float64 { return 1 }), - ) + tb, err := metadata.NewTelemetryBuilder(testTel.NewTelemetrySettings()) require.NoError(t, err) - require.NotNil(t, tb) + defer tb.Shutdown() + require.NoError(t, tb.RegisterProcessCPUSecondsCallback(func(_ context.Context, observer metric.Float64Observer) error { + observer.Observe(1) + return nil + })) + require.NoError(t, tb.RegisterProcessMemoryRssCallback(func(_ context.Context, observer metric.Int64Observer) error { + observer.Observe(1) + return nil + })) + require.NoError(t, tb.RegisterProcessRuntimeHeapAllocBytesCallback(func(_ context.Context, observer metric.Int64Observer) error { + observer.Observe(1) + return nil + })) + require.NoError(t, tb.RegisterProcessRuntimeTotalAllocBytesCallback(func(_ context.Context, observer metric.Int64Observer) error { + observer.Observe(1) + return nil + })) + require.NoError(t, tb.RegisterProcessRuntimeTotalSysMemoryBytesCallback(func(_ context.Context, observer metric.Int64Observer) error { + observer.Observe(1) + return nil + })) + require.NoError(t, tb.RegisterProcessUptimeCallback(func(_ context.Context, observer metric.Float64Observer) error { + observer.Observe(1) + return nil + })) testTel.AssertMetrics(t, []metricdata.Metrics{ { @@ -95,5 +112,24 @@ func TestSetupTelemetry(t *testing.T) { }, }, }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + AssertEqualProcessCPUSeconds(t, testTel.Telemetry, + []metricdata.DataPoint[float64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessMemoryRss(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessRuntimeHeapAllocBytes(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessRuntimeTotalAllocBytes(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessRuntimeTotalSysMemoryBytes(t, testTel.Telemetry, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + AssertEqualProcessUptime(t, testTel.Telemetry, + []metricdata.DataPoint[float64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + require.NoError(t, testTel.Shutdown(context.Background())) } diff --git a/service/internal/proctelemetry/process_telemetry.go b/service/internal/proctelemetry/process_telemetry.go index 82719224fc7a..00042b353ec8 100644 --- a/service/internal/proctelemetry/process_telemetry.go +++ b/service/internal/proctelemetry/process_telemetry.go @@ -5,6 +5,7 @@ package proctelemetry // import "go.opentelemetry.io/collector/service/internal/ import ( "context" + "errors" "os" "runtime" "sync" @@ -12,6 +13,7 @@ import ( "github.com/shirou/gopsutil/v4/common" "github.com/shirou/gopsutil/v4/process" + "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/service/internal/metadata" @@ -74,63 +76,72 @@ func RegisterProcessMetrics(cfg component.TelemetrySettings, opts ...RegisterOpt return err } - _, err = metadata.NewTelemetryBuilder(cfg, - metadata.WithProcessUptimeCallback(pm.updateProcessUptime), - metadata.WithProcessRuntimeHeapAllocBytesCallback(pm.updateAllocMem), - metadata.WithProcessRuntimeTotalAllocBytesCallback(pm.updateTotalAllocMem), - metadata.WithProcessRuntimeTotalSysMemoryBytesCallback(pm.updateSysMem), - metadata.WithProcessCPUSecondsCallback(pm.updateCPUSeconds), - metadata.WithProcessMemoryRssCallback(pm.updateRSSMemory), + tb, err := metadata.NewTelemetryBuilder(cfg) + if err != nil { + return err + } + return errors.Join( + tb.RegisterProcessUptimeCallback(pm.updateProcessUptime), + tb.RegisterProcessRuntimeHeapAllocBytesCallback(pm.updateAllocMem), + tb.RegisterProcessRuntimeTotalAllocBytesCallback(pm.updateTotalAllocMem), + tb.RegisterProcessRuntimeTotalSysMemoryBytesCallback(pm.updateSysMem), + tb.RegisterProcessCPUSecondsCallback(pm.updateCPUSeconds), + tb.RegisterProcessMemoryRssCallback(pm.updateRSSMemory), ) - return err } -func (pm *processMetrics) updateProcessUptime() float64 { +func (pm *processMetrics) updateProcessUptime(_ context.Context, obs metric.Float64Observer) error { now := time.Now().UnixNano() - return float64(now-pm.startTimeUnixNano) / 1e9 + obs.Observe(float64(now-pm.startTimeUnixNano) / 1e9) + return nil } -func (pm *processMetrics) updateAllocMem() int64 { +func (pm *processMetrics) updateAllocMem(_ context.Context, obs metric.Int64Observer) error { pm.mu.Lock() defer pm.mu.Unlock() pm.readMemStatsIfNeeded() //nolint:gosec - return int64(pm.ms.Alloc) + obs.Observe(int64(pm.ms.Alloc)) + return nil } -func (pm *processMetrics) updateTotalAllocMem() int64 { +func (pm *processMetrics) updateTotalAllocMem(_ context.Context, obs metric.Int64Observer) error { pm.mu.Lock() defer pm.mu.Unlock() pm.readMemStatsIfNeeded() //nolint:gosec - return int64(pm.ms.TotalAlloc) + obs.Observe(int64(pm.ms.TotalAlloc)) + return nil } -func (pm *processMetrics) updateSysMem() int64 { +func (pm *processMetrics) updateSysMem(_ context.Context, obs metric.Int64Observer) error { pm.mu.Lock() defer pm.mu.Unlock() pm.readMemStatsIfNeeded() //nolint:gosec - return int64(pm.ms.Sys) + obs.Observe(int64(pm.ms.Sys)) + return nil } -func (pm *processMetrics) updateCPUSeconds() float64 { +func (pm *processMetrics) updateCPUSeconds(_ context.Context, obs metric.Float64Observer) error { times, err := pm.proc.TimesWithContext(pm.context) if err != nil { - return 0 + return err } - return times.User + times.System + times.Idle + times.Nice + - times.Iowait + times.Irq + times.Softirq + times.Steal + obs.Observe(times.User + times.System + times.Idle + times.Nice + + times.Iowait + times.Irq + times.Softirq + times.Steal) + return nil } -func (pm *processMetrics) updateRSSMemory() int64 { +func (pm *processMetrics) updateRSSMemory(_ context.Context, obs metric.Int64Observer) error { mem, err := pm.proc.MemoryInfoWithContext(pm.context) if err != nil { - return 0 + return err } //nolint:gosec - return int64(mem.RSS) + obs.Observe(int64(mem.RSS)) + return nil } func (pm *processMetrics) readMemStatsIfNeeded() { diff --git a/service/internal/proctelemetry/process_telemetry_linux_test.go b/service/internal/proctelemetry/process_telemetry_linux_test.go index 30c94ecfd603..f4ddab4d1984 100644 --- a/service/internal/proctelemetry/process_telemetry_linux_test.go +++ b/service/internal/proctelemetry/process_telemetry_linux_test.go @@ -12,80 +12,31 @@ import ( "go.opentelemetry.io/otel/sdk/metric/metricdata" "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/service/internal/metadatatest" ) func TestProcessTelemetryWithHostProc(t *testing.T) { // Make the sure the environment variable value is not used. t.Setenv("HOST_PROC", "foo/bar") - tel := metadatatest.SetupTelemetry() + tel := componenttest.NewTelemetry() require.NoError(t, RegisterProcessMetrics(tel.NewTelemetrySettings(), WithHostProc("/proc"))) - tel.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_process_uptime", - Description: "Uptime of the process [alpha]", - Unit: "s", - Data: metricdata.Sum[float64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[float64]{ - {}, - }, - }, - }, - { - Name: "otelcol_process_runtime_heap_alloc_bytes", - Description: "Bytes of allocated heap objects (see 'go doc runtime.MemStats.HeapAlloc') [alpha]", - Unit: "By", - Data: metricdata.Gauge[int64]{ - DataPoints: []metricdata.DataPoint[int64]{ - {}, - }, - }, - }, - { - Name: "otelcol_process_runtime_total_alloc_bytes", - Description: "Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc') [alpha]", - Unit: "By", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - {}, - }, - }, - }, - { - Name: "otelcol_process_runtime_total_sys_memory_bytes", - Description: "Total bytes of memory obtained from the OS (see 'go doc runtime.MemStats.Sys') [alpha]", - Unit: "By", - Data: metricdata.Gauge[int64]{ - DataPoints: []metricdata.DataPoint[int64]{ - {}, - }, - }, - }, - { - Name: "otelcol_process_cpu_seconds", - Description: "Total CPU user and system time in seconds [alpha]", - Unit: "s", - Data: metricdata.Sum[float64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[float64]{ - {}, - }, - }, - }, - { - Name: "otelcol_process_memory_rss", - Description: "Total physical memory (resident set size) [alpha]", - Unit: "By", - Data: metricdata.Gauge[int64]{ - DataPoints: []metricdata.DataPoint[int64]{ - {}, - }, - }, - }, - }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + + metadatatest.AssertEqualProcessUptime(t, tel, + []metricdata.DataPoint[float64]{{}}, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + + metadatatest.AssertEqualProcessRuntimeHeapAllocBytes(t, tel, + []metricdata.DataPoint[int64]{{}}, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + + metadatatest.AssertEqualProcessRuntimeTotalAllocBytes(t, tel, + []metricdata.DataPoint[int64]{{}}, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + + metadatatest.AssertEqualProcessRuntimeTotalSysMemoryBytes(t, tel, + []metricdata.DataPoint[int64]{{}}, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + + metadatatest.AssertEqualProcessCPUSeconds(t, tel, + []metricdata.DataPoint[float64]{{}}, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + + metadatatest.AssertEqualProcessMemoryRss(t, tel, + []metricdata.DataPoint[int64]{{}}, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) } diff --git a/service/internal/proctelemetry/process_telemetry_test.go b/service/internal/proctelemetry/process_telemetry_test.go index f86b233db2e9..1dc312f7ce6c 100644 --- a/service/internal/proctelemetry/process_telemetry_test.go +++ b/service/internal/proctelemetry/process_telemetry_test.go @@ -10,78 +10,29 @@ import ( "go.opentelemetry.io/otel/sdk/metric/metricdata" "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/service/internal/metadatatest" ) func TestProcessTelemetry(t *testing.T) { - tel := metadatatest.SetupTelemetry() + tel := componenttest.NewTelemetry() require.NoError(t, RegisterProcessMetrics(tel.NewTelemetrySettings())) - tel.AssertMetrics(t, []metricdata.Metrics{ - { - Name: "otelcol_process_uptime", - Description: "Uptime of the process [alpha]", - Unit: "s", - Data: metricdata.Sum[float64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[float64]{ - {}, - }, - }, - }, - { - Name: "otelcol_process_runtime_heap_alloc_bytes", - Description: "Bytes of allocated heap objects (see 'go doc runtime.MemStats.HeapAlloc') [alpha]", - Unit: "By", - Data: metricdata.Gauge[int64]{ - DataPoints: []metricdata.DataPoint[int64]{ - {}, - }, - }, - }, - { - Name: "otelcol_process_runtime_total_alloc_bytes", - Description: "Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc') [alpha]", - Unit: "By", - Data: metricdata.Sum[int64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{ - {}, - }, - }, - }, - { - Name: "otelcol_process_runtime_total_sys_memory_bytes", - Description: "Total bytes of memory obtained from the OS (see 'go doc runtime.MemStats.Sys') [alpha]", - Unit: "By", - Data: metricdata.Gauge[int64]{ - DataPoints: []metricdata.DataPoint[int64]{ - {}, - }, - }, - }, - { - Name: "otelcol_process_cpu_seconds", - Description: "Total CPU user and system time in seconds [alpha]", - Unit: "s", - Data: metricdata.Sum[float64]{ - Temporality: metricdata.CumulativeTemporality, - IsMonotonic: true, - DataPoints: []metricdata.DataPoint[float64]{ - {}, - }, - }, - }, - { - Name: "otelcol_process_memory_rss", - Description: "Total physical memory (resident set size) [alpha]", - Unit: "By", - Data: metricdata.Gauge[int64]{ - DataPoints: []metricdata.DataPoint[int64]{ - {}, - }, - }, - }, - }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + + metadatatest.AssertEqualProcessUptime(t, tel, + []metricdata.DataPoint[float64]{{}}, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + + metadatatest.AssertEqualProcessRuntimeHeapAllocBytes(t, tel, + []metricdata.DataPoint[int64]{{}}, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + + metadatatest.AssertEqualProcessRuntimeTotalAllocBytes(t, tel, + []metricdata.DataPoint[int64]{{}}, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + + metadatatest.AssertEqualProcessRuntimeTotalSysMemoryBytes(t, tel, + []metricdata.DataPoint[int64]{{}}, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + + metadatatest.AssertEqualProcessCPUSeconds(t, tel, + []metricdata.DataPoint[float64]{{}}, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + + metadatatest.AssertEqualProcessMemoryRss(t, tel, + []metricdata.DataPoint[int64]{{}}, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) } diff --git a/service/internal/promtest/server_util.go b/service/internal/promtest/server_util.go index 0c7df35fd36e..4c04ba7a76fd 100644 --- a/service/internal/promtest/server_util.go +++ b/service/internal/promtest/server_util.go @@ -8,7 +8,7 @@ import ( "strconv" "testing" - "go.opentelemetry.io/contrib/config" + config "go.opentelemetry.io/contrib/config/v0.3.0" "go.opentelemetry.io/collector/internal/testutil" ) @@ -23,6 +23,9 @@ func GetAvailableLocalAddressPrometheus(tb testing.TB) *config.Prometheus { func addrToPrometheus(address string) *config.Prometheus { host, port, err := net.SplitHostPort(address) + if host == "::1" { + host = "[::1]" + } if err != nil { return nil } @@ -31,7 +34,17 @@ func addrToPrometheus(address string) *config.Prometheus { return nil } return &config.Prometheus{ - Host: &host, - Port: &portInt, + Host: &host, + Port: &portInt, + WithoutScopeInfo: ptr(true), + WithoutUnits: ptr(true), + WithoutTypeSuffix: ptr(true), + WithResourceConstantLabels: &config.IncludeExclude{ + Included: []string{}, + }, } } + +func ptr[T any](v T) *T { + return &v +} diff --git a/service/pipelines/config.go b/service/pipelines/config.go index 025d3c8395a7..18e2621a86c7 100644 --- a/service/pipelines/config.go +++ b/service/pipelines/config.go @@ -38,7 +38,7 @@ func (cfg Config) Validate() error { // Check that all pipelines have at least one receiver and one exporter, and they reference // only configured components. - for pipelineID, p := range cfg { + for pipelineID := range cfg { switch pipelineID.Signal() { case pipeline.SignalTraces, pipeline.SignalMetrics, pipeline.SignalLogs: // Continue @@ -53,11 +53,6 @@ func (cfg Config) Validate() error { default: return fmt.Errorf("pipeline %q: unknown signal %q", pipelineID.String(), pipelineID.Signal()) } - - // Validate pipeline has at least one receiver. - if err := p.Validate(); err != nil { - return fmt.Errorf("pipeline %q: %w", pipelineID.String(), err) - } } return nil diff --git a/service/pipelines/config_test.go b/service/pipelines/config_test.go index eba5fa0cb6bb..19ca0be6d4a5 100644 --- a/service/pipelines/config_test.go +++ b/service/pipelines/config_test.go @@ -5,10 +5,8 @@ package pipelines import ( "errors" - "fmt" "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/collector/component" @@ -36,7 +34,7 @@ func TestConfigValidate(t *testing.T) { pipe.Processors = append(pipe.Processors, pipe.Processors...) return cfg }, - expected: fmt.Errorf(`pipeline "traces": %w`, errors.New(`references processor "nop" multiple times`)), + expected: errors.New(`references processor "nop" multiple times`), }, { name: "missing-pipeline-receivers", @@ -45,7 +43,7 @@ func TestConfigValidate(t *testing.T) { cfg[pipeline.NewID(pipeline.SignalTraces)].Receivers = nil return cfg }, - expected: fmt.Errorf(`pipeline "traces": %w`, errMissingServicePipelineReceivers), + expected: errMissingServicePipelineReceivers, }, { name: "missing-pipeline-exporters", @@ -54,7 +52,7 @@ func TestConfigValidate(t *testing.T) { cfg[pipeline.NewID(pipeline.SignalTraces)].Exporters = nil return cfg }, - expected: fmt.Errorf(`pipeline "traces": %w`, errMissingServicePipelineExporters), + expected: errMissingServicePipelineExporters, }, { name: "missing-pipelines", @@ -74,7 +72,7 @@ func TestConfigValidate(t *testing.T) { } return cfg }, - expected: errors.New(`pipeline "wrongtype": unknown signal "wrongtype"`), + expected: errors.New(`unknown signal "wrongtype"`), }, { name: "disabled-featuregate-profiles", @@ -87,7 +85,7 @@ func TestConfigValidate(t *testing.T) { } return cfg }, - expected: errors.New(`pipeline "profiles": profiling signal support is at alpha level, gated under the "service.profilesSupport" feature gate`), + expected: errors.New(`profiling signal support is at alpha level, gated under the "service.profilesSupport" feature gate`), }, { name: "enabled-featuregate-profiles", @@ -109,7 +107,11 @@ func TestConfigValidate(t *testing.T) { for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { cfg := tt.cfgFn(t) - assert.Equal(t, tt.expected, cfg.Validate()) + if tt.expected != nil { + require.ErrorContains(t, component.ValidateConfig(cfg), tt.expected.Error()) + } else { + require.NoError(t, component.ValidateConfig(cfg)) + } // Clean up the profiles support gate, which may have been enabled in `cfgFn`. require.NoError(t, featuregate.GlobalRegistry().Set(serviceProfileSupportGateID, false)) diff --git a/service/service.go b/service/service.go index b47ecb0fdde0..1cde310a5a4b 100644 --- a/service/service.go +++ b/service/service.go @@ -11,7 +11,7 @@ import ( "fmt" "runtime" - "go.opentelemetry.io/contrib/config" + config "go.opentelemetry.io/contrib/config/v0.3.0" "go.opentelemetry.io/otel/log" "go.opentelemetry.io/otel/metric" sdkresource "go.opentelemetry.io/otel/sdk/resource" @@ -28,6 +28,7 @@ import ( "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/processor" "go.opentelemetry.io/collector/receiver" + semconv118 "go.opentelemetry.io/collector/semconv/v1.18.0" semconv "go.opentelemetry.io/collector/semconv/v1.26.0" "go.opentelemetry.io/collector/service/extensions" "go.opentelemetry.io/collector/service/internal/builders" @@ -47,6 +48,14 @@ var _ = featuregate.GlobalRegistry().MustRegister( featuregate.WithRegisterDescription("controls whether the collector supports extended OpenTelemetry"+ "configuration for internal telemetry")) +// disableHighCardinalityMetricsFeatureGate is the feature gate that controls whether the collector should enable +// potentially high cardinality metrics. The gate will be removed when the collector allows for view configuration. +var disableHighCardinalityMetricsFeatureGate = featuregate.GlobalRegistry().MustRegister( + "telemetry.disableHighCardinalityMetrics", + featuregate.StageAlpha, + featuregate.WithRegisterDescription("controls whether the collector should enable potentially high"+ + "cardinality metrics. The gate will be removed when the collector allows for view configuration.")) + // Settings holds configuration for building a new Service. type Settings struct { // BuildInfo provides collector start information. @@ -120,9 +129,12 @@ func New(ctx context.Context, set Settings, cfg Config) (*Service, error) { pcommonRes := pdataFromSdk(res) sch := semconv.SchemaURL - cfgRes := config.Resource{ - SchemaUrl: &sch, - Attributes: attributes(res, cfg.Telemetry), + + views := configureViews(cfg.Telemetry.Metrics.Level) + + readers := cfg.Telemetry.Metrics.Readers + if cfg.Telemetry.Metrics.Level == configtelemetry.LevelNone { + readers = []config.MetricReader{} } sdk, err := config.NewSDK( @@ -132,10 +144,17 @@ func New(ctx context.Context, set Settings, cfg Config) (*Service, error) { LoggerProvider: &config.LoggerProvider{ Processors: cfg.Telemetry.Logs.Processors, }, + MeterProvider: &config.MeterProvider{ + Readers: readers, + Views: views, + }, TracerProvider: &config.TracerProvider{ Processors: cfg.Telemetry.Traces.Processors, }, - Resource: &cfgRes, + Resource: &config.Resource{ + SchemaUrl: &sch, + Attributes: attributes(res, cfg.Telemetry), + }, }, ), ) @@ -145,19 +164,22 @@ func New(ctx context.Context, set Settings, cfg Config) (*Service, error) { telFactory := telemetry.NewFactory() telset := telemetry.Settings{ - BuildInfo: set.BuildInfo, - ZapOptions: set.LoggingOptions, - SDK: &sdk, + AsyncErrorChannel: set.AsyncErrorChannel, + BuildInfo: set.BuildInfo, + ZapOptions: set.LoggingOptions, + SDK: &sdk, } logger, lp, err := telFactory.CreateLogger(ctx, telset, &cfg.Telemetry) if err != nil { + err = multierr.Append(err, sdk.Shutdown(ctx)) return nil, fmt.Errorf("failed to create logger: %w", err) } srv.loggerProvider = lp tracerProvider, err := telFactory.CreateTracerProvider(ctx, telset, &cfg.Telemetry) if err != nil { + err = multierr.Append(err, sdk.Shutdown(ctx)) return nil, fmt.Errorf("failed to create tracer provider: %w", err) } @@ -165,6 +187,7 @@ func New(ctx context.Context, set Settings, cfg Config) (*Service, error) { mp, err := telFactory.CreateMeterProvider(ctx, telset, &cfg.Telemetry) if err != nil { + err = multierr.Append(err, sdk.Shutdown(ctx)) return nil, fmt.Errorf("failed to create meter provider: %w", err) } @@ -208,8 +231,7 @@ func logsAboutMeterProvider(logger *zap.Logger, cfg telemetry.MetricsConfig, mp return } - //nolint:staticcheck - if len(cfg.Address) != 0 { + if len(cfg.Address) != 0 { // SA1019 logger.Warn("service::telemetry::metrics::address is being deprecated in favor of service::telemetry::metrics::readers") } @@ -362,3 +384,136 @@ func pdataFromSdk(res *sdkresource.Resource) pcommon.Resource { } return pcommonRes } + +func dropViewOption(selector *config.ViewSelector) config.View { + return config.View{ + Selector: selector, + Stream: &config.ViewStream{ + Aggregation: &config.ViewStreamAggregation{ + Drop: config.ViewStreamAggregationDrop{}, + }, + }, + } +} + +func configureViews(level configtelemetry.Level) []config.View { + views := []config.View{} + + if disableHighCardinalityMetricsFeatureGate.IsEnabled() { + views = append(views, []config.View{ + { + Selector: &config.ViewSelector{ + MeterName: ptr("go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"), + }, + Stream: &config.ViewStream{ + AttributeKeys: &config.IncludeExclude{ + Excluded: []string{ + semconv118.AttributeNetSockPeerAddr, + semconv118.AttributeNetSockPeerPort, + semconv118.AttributeNetSockPeerName, + }, + }, + }, + }, + { + Selector: &config.ViewSelector{ + MeterName: ptr("go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"), + }, + Stream: &config.ViewStream{ + AttributeKeys: &config.IncludeExclude{ + Excluded: []string{ + semconv118.AttributeNetHostName, + semconv118.AttributeNetHostPort, + }, + }, + }, + }, + }...) + } + + if level < configtelemetry.LevelDetailed { + // Drop all otelhttp and otelgrpc metrics if the level is not detailed. + views = append(views, + dropViewOption(&config.ViewSelector{ + MeterName: ptr("go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"), + }), + dropViewOption(&config.ViewSelector{ + MeterName: ptr("go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"), + }), + ) + } + + // otel-arrow library metrics + // See https://github.com/open-telemetry/otel-arrow/blob/c39257/pkg/otel/arrow_record/consumer.go#L174-L176 + if level < configtelemetry.LevelNormal { + scope := ptr("otel-arrow/pkg/otel/arrow_record") + views = append(views, + dropViewOption(&config.ViewSelector{ + MeterName: scope, + InstrumentName: ptr("arrow_batch_records"), + }), + dropViewOption(&config.ViewSelector{ + MeterName: scope, + InstrumentName: ptr("arrow_schema_resets"), + }), + dropViewOption(&config.ViewSelector{ + MeterName: scope, + InstrumentName: ptr("arrow_memory_inuse"), + }), + ) + } + + // contrib's internal/otelarrow/netstats metrics + // See + // - https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/a25f05/internal/otelarrow/netstats/netstats.go#L130 + // - https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/a25f05/internal/otelarrow/netstats/netstats.go#L165 + if level < configtelemetry.LevelDetailed { + scope := ptr("github.com/open-telemetry/opentelemetry-collector-contrib/internal/otelarrow/netstats") + + views = append(views, + // Compressed size metrics. + dropViewOption(&config.ViewSelector{ + MeterName: scope, + InstrumentName: ptr("otelcol_*_compressed_size"), + }), + dropViewOption(&config.ViewSelector{ + MeterName: scope, + InstrumentName: ptr("otelcol_*_compressed_size"), + }), + + // makeRecvMetrics for exporters. + dropViewOption(&config.ViewSelector{ + MeterName: scope, + InstrumentName: ptr("otelcol_exporter_recv"), + }), + dropViewOption(&config.ViewSelector{ + MeterName: scope, + InstrumentName: ptr("otelcol_exporter_recv_wire"), + }), + + // makeSentMetrics for receivers. + dropViewOption(&config.ViewSelector{ + MeterName: scope, + InstrumentName: ptr("otelcol_receiver_sent"), + }), + dropViewOption(&config.ViewSelector{ + MeterName: scope, + InstrumentName: ptr("otelcol_receiver_sent_wire"), + }), + ) + } + + // Batch processor metrics + if level < configtelemetry.LevelDetailed { + scope := ptr("go.opentelemetry.io/collector/processor/batchprocessor") + views = append(views, dropViewOption(&config.ViewSelector{ + MeterName: scope, + InstrumentName: ptr("otelcol_processor_batch_batch_send_size_bytes"), + })) + } + return views +} + +func ptr[T any](v T) *T { + return &v +} diff --git a/service/service_test.go b/service/service_test.go index 472d32b99cd6..2abb433fa196 100644 --- a/service/service_test.go +++ b/service/service_test.go @@ -17,7 +17,7 @@ import ( "github.com/prometheus/common/expfmt" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opentelemetry.io/contrib/config" + config "go.opentelemetry.io/contrib/config/v0.3.0" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -207,7 +207,7 @@ func TestServiceGetFactory(t *testing.T) { assert.Equal(t, srv.host.Extensions.Factory(nopType), srv.host.GetFactory(component.KindExtension, nopType)) // Try retrieve non existing component.Kind. - assert.Nil(t, srv.host.GetFactory(42, nopType)) + assert.Nil(t, srv.host.GetFactory(component.Kind{}, nopType)) } func TestServiceGetExtensions(t *testing.T) { @@ -318,7 +318,7 @@ func testCollectorStartHelperWithReaders(t *testing.T, tc ownMetricsTestCase, ne cfg.Telemetry.Metrics.Readers = []config.MetricReader{ { Pull: &config.PullMetricReader{ - Exporter: config.MetricExporter{ + Exporter: config.PullMetricExporter{ Prometheus: metricsAddr, }, }, @@ -497,7 +497,7 @@ func TestServiceInvalidTelemetryConfiguration(t *testing.T) { }, }, }, - wantErr: errors.New("unsupported protocol \"\""), + wantErr: errors.New("no valid log exporter"), }, } for _, tt := range tests { @@ -556,12 +556,16 @@ func assertMetrics(t *testing.T, metricsAddr string, expectedLabels map[string]l "otelcol_process_runtime_heap_alloc_bytes": false, "otelcol_process_runtime_total_alloc_bytes": false, "otelcol_process_uptime": false, + "promhttp_metric_handler_errors_total": false, } for metricName, metricFamily := range parsed { if _, ok := expectedMetrics[metricName]; !ok { require.True(t, ok, "unexpected metric: %s", metricName) } expectedMetrics[metricName] = true + if metricName == "promhttp_metric_handler_errors_total" { + continue + } if metricName != "target_info" { // require is used here so test fails with a single message. require.True( @@ -691,7 +695,7 @@ func newNopConfigPipelineConfigs(pipelineCfgs pipelines.Config) Config { Level: configtelemetry.LevelBasic, Readers: []config.MetricReader{ { - Pull: &config.PullMetricReader{Exporter: config.MetricExporter{Prometheus: &config.Prometheus{ + Pull: &config.PullMetricReader{Exporter: config.PullMetricExporter{Prometheus: &config.Prometheus{ Host: newPtr("localhost"), Port: newPtr(8888), }}}, diff --git a/service/telemetry/config.go b/service/telemetry/config.go index e6d80dbd16cf..73f7cfb368c4 100644 --- a/service/telemetry/config.go +++ b/service/telemetry/config.go @@ -8,14 +8,13 @@ import ( "fmt" "net" "strconv" - "time" - "go.opentelemetry.io/contrib/config" - "go.uber.org/zap/zapcore" + config "go.opentelemetry.io/contrib/config/v0.3.0" "go.opentelemetry.io/collector/config/configtelemetry" "go.opentelemetry.io/collector/confmap" "go.opentelemetry.io/collector/featuregate" + "go.opentelemetry.io/collector/service/telemetry/internal/migration" ) var _ confmap.Unmarshaler = (*Config)(nil) @@ -43,123 +42,20 @@ type Config struct { // LogsConfig defines the configurable settings for service telemetry logs. // This MUST be compatible with zap.Config. Cannot use directly zap.Config because // the collector uses mapstructure and not yaml tags. -type LogsConfig struct { - // Level is the minimum enabled logging level. - // (default = "INFO") - Level zapcore.Level `mapstructure:"level"` - - // Development puts the logger in development mode, which changes the - // behavior of DPanicLevel and takes stacktraces more liberally. - // (default = false) - Development bool `mapstructure:"development"` - - // Encoding sets the logger's encoding. - // Example values are "json", "console". - Encoding string `mapstructure:"encoding"` - - // DisableCaller stops annotating logs with the calling function's file - // name and line number. By default, all logs are annotated. - // (default = false) - DisableCaller bool `mapstructure:"disable_caller"` - - // DisableStacktrace completely disables automatic stacktrace capturing. By - // default, stacktraces are captured for WarnLevel and above logs in - // development and ErrorLevel and above in production. - // (default = false) - DisableStacktrace bool `mapstructure:"disable_stacktrace"` - - // Sampling sets a sampling policy. - // Default: - // sampling: - // enabled: true - // tick: 10s - // initial: 10 - // thereafter: 100 - // Sampling can be disabled by setting 'enabled' to false - Sampling *LogsSamplingConfig `mapstructure:"sampling"` - - // OutputPaths is a list of URLs or file paths to write logging output to. - // The URLs could only be with "file" schema or without schema. - // The URLs with "file" schema must be an absolute path. - // The URLs without schema are treated as local file paths. - // "stdout" and "stderr" are interpreted as os.Stdout and os.Stderr. - // see details at Open in zap/writer.go. - // (default = ["stderr"]) - OutputPaths []string `mapstructure:"output_paths"` - - // ErrorOutputPaths is a list of URLs or file paths to write zap internal logger errors to. - // The URLs could only be with "file" schema or without schema. - // The URLs with "file" schema must use absolute paths. - // The URLs without schema are treated as local file paths. - // "stdout" and "stderr" are interpreted as os.Stdout and os.Stderr. - // see details at Open in zap/writer.go. - // - // Note that this setting only affects the zap internal logger errors. - // (default = ["stderr"]) - ErrorOutputPaths []string `mapstructure:"error_output_paths"` - - // InitialFields is a collection of fields to add to the root logger. - // Example: - // - // initial_fields: - // foo: "bar" - // - // By default, there is no initial field. - InitialFields map[string]any `mapstructure:"initial_fields"` - - // Processors allow configuration of log record processors to emit logs to - // any number of suported backends. - Processors []config.LogRecordProcessor `mapstructure:"processors"` -} +type LogsConfig = migration.LogsConfigV030 // LogsSamplingConfig sets a sampling strategy for the logger. Sampling caps the // global CPU and I/O load that logging puts on your process while attempting // to preserve a representative subset of your logs. -type LogsSamplingConfig struct { - // Enabled enable sampling logging - Enabled bool `mapstructure:"enabled"` - // Tick represents the interval in seconds that the logger apply each sampling. - Tick time.Duration `mapstructure:"tick"` - // Initial represents the first M messages logged each Tick. - Initial int `mapstructure:"initial"` - // Thereafter represents the sampling rate, every Nth message will be sampled after Initial messages are logged during each Tick. - // If Thereafter is zero, the logger will drop all the messages after the Initial each Tick. - Thereafter int `mapstructure:"thereafter"` -} +type LogsSamplingConfig = migration.LogsSamplingConfig // MetricsConfig exposes the common Telemetry configuration for one component. // Experimental: *NOTE* this structure is subject to change or removal in the future. -type MetricsConfig struct { - // Level is the level of telemetry metrics, the possible values are: - // - "none" indicates that no telemetry data should be collected; - // - "basic" is the recommended and covers the basics of the service telemetry. - // - "normal" adds some other indicators on top of basic. - // - "detailed" adds dimensions and views to the previous levels. - Level configtelemetry.Level `mapstructure:"level"` - - // Deprecated: [v0.111.0] use readers configuration. - Address string `mapstructure:"address"` - - // Readers allow configuration of metric readers to emit metrics to - // any number of supported backends. - Readers []config.MetricReader `mapstructure:"readers"` -} +type MetricsConfig = migration.MetricsConfigV030 // TracesConfig exposes the common Telemetry configuration for collector's internal spans. // Experimental: *NOTE* this structure is subject to change or removal in the future. -type TracesConfig struct { - // Level configures whether spans are emitted or not, the possible values are: - // - "none" indicates that no tracing data should be collected; - // - "basic" is the recommended and covers the basics of the service telemetry. - Level configtelemetry.Level `mapstructure:"level"` - // Propagators is a list of TextMapPropagators from the supported propagators list. Currently, - // tracecontext and b3 are supported. By default, the value is set to empty list and - // context propagation is disabled. - Propagators []string `mapstructure:"propagators"` - // Processors allow configuration of span processors to emit spans to - // any number of supported backends. - Processors []config.SpanProcessor `mapstructure:"processors"` -} +type TracesConfig = migration.TracesConfigV030 func (c *Config) Unmarshal(conf *confmap.Conf) error { if err := conf.Unmarshal(c); err != nil { @@ -172,14 +68,14 @@ func (c *Config) Unmarshal(conf *confmap.Conf) error { return nil } - if len(c.Metrics.Address) != 0 { - host, port, err := net.SplitHostPort(c.Metrics.Address) + if len(c.Metrics.Address) != 0 { //nolint:staticcheck // SA1019 + host, port, err := net.SplitHostPort(c.Metrics.Address) //nolint:staticcheck // SA1019 if err != nil { - return fmt.Errorf("failing to parse metrics address %q: %w", c.Metrics.Address, err) + return fmt.Errorf("failing to parse metrics address %q: %w", c.Metrics.Address, err) //nolint:staticcheck // SA1019 } portInt, err := strconv.Atoi(port) if err != nil { - return fmt.Errorf("failing to extract the port from the metrics address %q: %w", c.Metrics.Address, err) + return fmt.Errorf("failing to extract the port from the metrics address %q: %w", c.Metrics.Address, err) //nolint:staticcheck // SA1019 } // User did not overwrite readers, so we will remove the default configured reader. @@ -189,10 +85,16 @@ func (c *Config) Unmarshal(conf *confmap.Conf) error { c.Metrics.Readers = append(c.Metrics.Readers, config.MetricReader{ Pull: &config.PullMetricReader{ - Exporter: config.MetricExporter{ + Exporter: config.PullMetricExporter{ Prometheus: &config.Prometheus{ - Host: &host, - Port: &portInt, + Host: &host, + Port: &portInt, + WithoutScopeInfo: newPtr(true), + WithoutUnits: newPtr(true), + WithoutTypeSuffix: newPtr(true), + WithResourceConstantLabels: &config.IncludeExclude{ + Included: []string{}, + }, }, }, }, diff --git a/service/telemetry/config_test.go b/service/telemetry/config_test.go index 780f059aff63..fb2cfbfc04b6 100644 --- a/service/telemetry/config_test.go +++ b/service/telemetry/config_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opentelemetry.io/contrib/config" + config "go.opentelemetry.io/contrib/config/v0.3.0" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/config/configtelemetry" @@ -119,7 +119,7 @@ func TestConfigValidate(t *testing.T) { Level: configtelemetry.LevelBasic, Readers: []config.MetricReader{ { - Pull: &config.PullMetricReader{Exporter: config.MetricExporter{Prometheus: &config.Prometheus{ + Pull: &config.PullMetricReader{Exporter: config.PullMetricExporter{Prometheus: &config.Prometheus{ Host: newPtr("127.0.0.1"), Port: newPtr(3333), }}}, diff --git a/service/telemetry/factory.go b/service/telemetry/factory.go index af23cfcabaea..310574743a72 100644 --- a/service/telemetry/factory.go +++ b/service/telemetry/factory.go @@ -7,7 +7,7 @@ import ( "context" "time" - "go.opentelemetry.io/contrib/config" + config "go.opentelemetry.io/contrib/config/v0.3.0" "go.opentelemetry.io/otel/log" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/trace" @@ -17,7 +17,6 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configtelemetry" "go.opentelemetry.io/collector/featuregate" - "go.opentelemetry.io/collector/service/internal/resource" ) var useLocalHostAsDefaultMetricsAddressFeatureGate = featuregate.GlobalRegistry().MustRegister( @@ -27,14 +26,6 @@ var useLocalHostAsDefaultMetricsAddressFeatureGate = featuregate.GlobalRegistry( featuregate.WithRegisterDescription("controls whether default Prometheus metrics server use localhost as the default host for their endpoints"), ) -// disableHighCardinalityMetricsFeatureGate is the feature gate that controls whether the collector should enable -// potentially high cardinality metrics. The gate will be removed when the collector allows for view configuration. -var disableHighCardinalityMetricsFeatureGate = featuregate.GlobalRegistry().MustRegister( - "telemetry.disableHighCardinalityMetrics", - featuregate.StageAlpha, - featuregate.WithRegisterDescription("controls whether the collector should enable potentially high"+ - "cardinality metrics. The gate will be removed when the collector allows for view configuration.")) - // Settings holds configuration for building Telemetry. type Settings struct { BuildInfo component.BuildInfo @@ -77,15 +68,7 @@ func NewFactory() Factory { }), withMeterProvider(func(_ context.Context, set Settings, cfg component.Config) (metric.MeterProvider, error) { c := *cfg.(*Config) - disableHighCard := disableHighCardinalityMetricsFeatureGate.IsEnabled() - return newMeterProvider( - meterProviderSettings{ - res: resource.New(set.BuildInfo, c.Resource), - cfg: c.Metrics, - asyncErrorChannel: set.AsyncErrorChannel, - }, - disableHighCard, - ) + return newMeterProvider(set, c) }), ) } @@ -117,9 +100,15 @@ func createDefaultConfig() component.Config { Level: configtelemetry.LevelNormal, Readers: []config.MetricReader{ { - Pull: &config.PullMetricReader{Exporter: config.MetricExporter{Prometheus: &config.Prometheus{ - Host: &metricsHost, - Port: newPtr(8888), + Pull: &config.PullMetricReader{Exporter: config.PullMetricExporter{Prometheus: &config.Prometheus{ + WithoutScopeInfo: newPtr(true), + WithoutUnits: newPtr(true), + WithoutTypeSuffix: newPtr(true), + Host: &metricsHost, + Port: newPtr(8888), + WithResourceConstantLabels: &config.IncludeExclude{ + Included: []string{}, + }, }}}, }, }, @@ -127,6 +116,6 @@ func createDefaultConfig() component.Config { } } -func newPtr[T int | string](str T) *T { +func newPtr[T int | string | bool](str T) *T { return &str } diff --git a/service/telemetry/factory_test.go b/service/telemetry/factory_test.go index 23fbcc4ad898..8b8d20bc1d14 100644 --- a/service/telemetry/factory_test.go +++ b/service/telemetry/factory_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opentelemetry.io/contrib/config" + config "go.opentelemetry.io/contrib/config/v0.3.0" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -67,7 +67,7 @@ func TestTelemetryConfiguration(t *testing.T) { Level: configtelemetry.LevelBasic, Readers: []config.MetricReader{ { - Pull: &config.PullMetricReader{Exporter: config.MetricExporter{Prometheus: &config.Prometheus{ + Pull: &config.PullMetricReader{Exporter: config.PullMetricExporter{Prometheus: &config.Prometheus{ Host: newPtr("127.0.0.1"), Port: newPtr(3333), }}}, @@ -87,7 +87,7 @@ func TestTelemetryConfiguration(t *testing.T) { Level: configtelemetry.LevelBasic, Readers: []config.MetricReader{ { - Pull: &config.PullMetricReader{Exporter: config.MetricExporter{Prometheus: &config.Prometheus{ + Pull: &config.PullMetricReader{Exporter: config.PullMetricExporter{Prometheus: &config.Prometheus{ Host: newPtr("127.0.0.1"), Port: newPtr(3333), }}}, diff --git a/service/telemetry/internal/migration/testdata/v0.2.0_logs.yaml b/service/telemetry/internal/migration/testdata/v0.2.0_logs.yaml new file mode 100644 index 000000000000..63575fefe71c --- /dev/null +++ b/service/telemetry/internal/migration/testdata/v0.2.0_logs.yaml @@ -0,0 +1,12 @@ +level: "info" +processors: + - batch: + exporter: + otlp: + protocol: http/protobuf + endpoint: 127.0.0.1:4317 + headers: + "key1": "value1" + - simple: + exporter: + console: {} diff --git a/service/telemetry/internal/migration/testdata/v0.2.0_metrics.yaml b/service/telemetry/internal/migration/testdata/v0.2.0_metrics.yaml new file mode 100644 index 000000000000..2a26102400b1 --- /dev/null +++ b/service/telemetry/internal/migration/testdata/v0.2.0_metrics.yaml @@ -0,0 +1,14 @@ +level: detailed +readers: + - periodic: + exporter: + otlp: + protocol: http/protobuf + endpoint: 127.0.0.1:4317 + headers: + "key1": "value1" + - pull: + exporter: + prometheus: + host: 127.0.0.1 + port: 8902 \ No newline at end of file diff --git a/service/telemetry/internal/migration/testdata/v0.2.0_traces.yaml b/service/telemetry/internal/migration/testdata/v0.2.0_traces.yaml new file mode 100644 index 000000000000..9b7f3b21730b --- /dev/null +++ b/service/telemetry/internal/migration/testdata/v0.2.0_traces.yaml @@ -0,0 +1,12 @@ +level: "none" +processors: + - batch: + exporter: + otlp: + protocol: http/protobuf + endpoint: 127.0.0.1:4317 + headers: + "key1": "value1" + - simple: + exporter: + console: {} diff --git a/service/telemetry/internal/migration/testdata/v0.3.0_logs.yaml b/service/telemetry/internal/migration/testdata/v0.3.0_logs.yaml new file mode 100644 index 000000000000..e3f61ed2fc3c --- /dev/null +++ b/service/telemetry/internal/migration/testdata/v0.3.0_logs.yaml @@ -0,0 +1,13 @@ +level: "info" +processors: + - batch: + exporter: + otlp: + protocol: http/protobuf + endpoint: 127.0.0.1:4317 + headers: + - name: "key1" + value: "value1" + - simple: + exporter: + console: {} diff --git a/service/telemetry/internal/migration/testdata/v0.3.0_metrics.yaml b/service/telemetry/internal/migration/testdata/v0.3.0_metrics.yaml new file mode 100644 index 000000000000..b8181be139a0 --- /dev/null +++ b/service/telemetry/internal/migration/testdata/v0.3.0_metrics.yaml @@ -0,0 +1,15 @@ +level: detailed +readers: + - periodic: + exporter: + otlp: + protocol: http/protobuf + endpoint: 127.0.0.1:4317 + headers: + - name: "key1" + value: "value1" + - pull: + exporter: + prometheus: + host: 127.0.0.1 + port: 8902 \ No newline at end of file diff --git a/service/telemetry/internal/migration/testdata/v0.3.0_traces.yaml b/service/telemetry/internal/migration/testdata/v0.3.0_traces.yaml new file mode 100644 index 000000000000..464aa66bb94a --- /dev/null +++ b/service/telemetry/internal/migration/testdata/v0.3.0_traces.yaml @@ -0,0 +1,13 @@ +level: "none" +processors: + - batch: + exporter: + otlp: + protocol: http/protobuf + endpoint: 127.0.0.1:4317 + headers: + - name: "key1" + value: "value1" + - simple: + exporter: + console: {} diff --git a/service/telemetry/internal/migration/v0.2.0.go b/service/telemetry/internal/migration/v0.2.0.go new file mode 100644 index 000000000000..cdfb5b0727b7 --- /dev/null +++ b/service/telemetry/internal/migration/v0.2.0.go @@ -0,0 +1,214 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package migration // import "go.opentelemetry.io/collector/service/telemetry/internal/migration" + +import ( + configv02 "go.opentelemetry.io/contrib/config/v0.2.0" + config "go.opentelemetry.io/contrib/config/v0.3.0" + "go.uber.org/zap/zapcore" + + "go.opentelemetry.io/collector/config/configtelemetry" +) + +type tracesConfigV020 struct { + Level configtelemetry.Level `mapstructure:"level"` + Propagators []string `mapstructure:"propagators"` + Processors []configv02.SpanProcessor `mapstructure:"processors"` +} + +type metricsConfigV020 struct { + Level configtelemetry.Level `mapstructure:"level"` + Address string `mapstructure:"address"` + Readers []configv02.MetricReader `mapstructure:"readers"` +} + +type logsConfigV020 struct { + Level zapcore.Level `mapstructure:"level"` + Development bool `mapstructure:"development"` + Encoding string `mapstructure:"encoding"` + DisableCaller bool `mapstructure:"disable_caller"` + DisableStacktrace bool `mapstructure:"disable_stacktrace"` + Sampling *LogsSamplingConfig `mapstructure:"sampling"` + OutputPaths []string `mapstructure:"output_paths"` + ErrorOutputPaths []string `mapstructure:"error_output_paths"` + InitialFields map[string]any `mapstructure:"initial_fields"` + Processors []configv02.LogRecordProcessor `mapstructure:"processors"` +} + +func headersV02ToV03(in configv02.Headers) []config.NameStringValuePair { + headers := make([]config.NameStringValuePair, len(in)) + idx := 0 + for k, v := range in { + headers[idx] = config.NameStringValuePair{ + Name: k, + Value: &v, + } + } + return headers +} + +func otlpV02ToV03(in *configv02.OTLP) *config.OTLP { + if in == nil { + return nil + } + return &config.OTLP{ + Certificate: in.Certificate, + ClientCertificate: in.ClientCertificate, + ClientKey: in.ClientKey, + Compression: in.Compression, + Endpoint: &in.Endpoint, + Insecure: in.Insecure, + Protocol: &in.Protocol, + Timeout: in.Timeout, + Headers: headersV02ToV03(in.Headers), + } +} + +func otlpMetricV02ToV03(in *configv02.OTLPMetric) *config.OTLPMetric { + if in == nil { + return nil + } + return &config.OTLPMetric{ + Certificate: in.Certificate, + ClientCertificate: in.ClientCertificate, + ClientKey: in.ClientKey, + Compression: in.Compression, + Endpoint: &in.Endpoint, + Insecure: in.Insecure, + Protocol: &in.Protocol, + Timeout: in.Timeout, + Headers: headersV02ToV03(in.Headers), + } +} + +func zipkinV02ToV03(in *configv02.Zipkin) *config.Zipkin { + if in == nil { + return nil + } + return &config.Zipkin{ + Endpoint: &in.Endpoint, + Timeout: in.Timeout, + } +} + +func tracesConfigV02ToV03(v2 tracesConfigV020, v3 *TracesConfigV030) error { + processors := make([]config.SpanProcessor, len(v2.Processors)) + for idx, p := range v2.Processors { + processors[idx] = config.SpanProcessor{} + if p.Batch != nil { + processors[idx].Batch = &config.BatchSpanProcessor{ + ExportTimeout: p.Batch.ExportTimeout, + MaxExportBatchSize: p.Batch.MaxExportBatchSize, + MaxQueueSize: p.Batch.MaxQueueSize, + ScheduleDelay: p.Batch.ScheduleDelay, + Exporter: config.SpanExporter{ + Console: config.Console(p.Batch.Exporter.Console), + OTLP: otlpV02ToV03(p.Batch.Exporter.OTLP), + Zipkin: zipkinV02ToV03(p.Batch.Exporter.Zipkin), + AdditionalProperties: p.Batch.Exporter.AdditionalProperties, + }, + } + } + if p.Simple != nil { + processors[idx].Simple = &config.SimpleSpanProcessor{ + Exporter: config.SpanExporter{ + Console: config.Console(p.Simple.Exporter.Console), + OTLP: otlpV02ToV03(p.Simple.Exporter.OTLP), + Zipkin: zipkinV02ToV03(p.Simple.Exporter.Zipkin), + AdditionalProperties: p.Simple.Exporter.AdditionalProperties, + }, + } + } + processors[idx].AdditionalProperties = p.AdditionalProperties + } + v3.Level = v2.Level + v3.Propagators = v2.Propagators + v3.Processors = processors + return nil +} + +func prometheusV02ToV03(in *configv02.Prometheus) *config.Prometheus { + if in == nil { + return nil + } + return &config.Prometheus{ + Host: in.Host, + Port: in.Port, + WithoutScopeInfo: in.WithoutScopeInfo, + WithoutUnits: in.WithoutUnits, + WithoutTypeSuffix: in.WithoutTypeSuffix, + WithResourceConstantLabels: (*config.IncludeExclude)(in.WithResourceConstantLabels), + } +} + +func metricsConfigV02ToV03(v2 metricsConfigV020, v3 *MetricsConfigV030) error { + readers := make([]config.MetricReader, len(v2.Readers)) + for idx, p := range v2.Readers { + readers[idx] = config.MetricReader{} + if p.Periodic != nil { + readers[idx].Periodic = &config.PeriodicMetricReader{ + Interval: p.Periodic.Interval, + Timeout: p.Periodic.Timeout, + Exporter: config.PushMetricExporter{ + Console: config.Console(p.Periodic.Exporter.Console), + OTLP: otlpMetricV02ToV03(p.Periodic.Exporter.OTLP), + AdditionalProperties: p.Periodic.Exporter.AdditionalProperties, + }, + } + } + if p.Pull != nil { + readers[idx].Pull = &config.PullMetricReader{ + Exporter: config.PullMetricExporter{ + Prometheus: prometheusV02ToV03(p.Pull.Exporter.Prometheus), + AdditionalProperties: p.Pull.Exporter.AdditionalProperties, + }, + } + } + } + v3.Level = v2.Level + v3.Address = v2.Address + v3.Readers = readers + return nil +} + +func logsConfigV02ToV03(v2 logsConfigV020, v3 *LogsConfigV030) error { + processors := make([]config.LogRecordProcessor, len(v2.Processors)) + for idx, p := range v2.Processors { + processors[idx] = config.LogRecordProcessor{} + if p.Batch != nil { + processors[idx].Batch = &config.BatchLogRecordProcessor{ + ExportTimeout: p.Batch.ExportTimeout, + MaxExportBatchSize: p.Batch.MaxExportBatchSize, + MaxQueueSize: p.Batch.MaxQueueSize, + ScheduleDelay: p.Batch.ScheduleDelay, + Exporter: config.LogRecordExporter{ + Console: config.Console(p.Batch.Exporter.Console), + OTLP: otlpV02ToV03(p.Batch.Exporter.OTLP), + AdditionalProperties: p.Batch.Exporter.AdditionalProperties, + }, + } + } + if p.Simple != nil { + processors[idx].Simple = &config.SimpleLogRecordProcessor{ + Exporter: config.LogRecordExporter{ + Console: config.Console(p.Simple.Exporter.Console), + OTLP: otlpV02ToV03(p.Simple.Exporter.OTLP), + AdditionalProperties: p.Simple.Exporter.AdditionalProperties, + }, + } + } + processors[idx].AdditionalProperties = p.AdditionalProperties + } + v3.Level = v2.Level + v3.Development = v2.Development + v3.Encoding = v2.Encoding + v3.DisableCaller = v2.DisableCaller + v3.DisableStacktrace = v2.DisableStacktrace + v3.Sampling = v2.Sampling + v3.OutputPaths = v2.OutputPaths + v3.ErrorOutputPaths = v2.ErrorOutputPaths + v3.InitialFields = v2.InitialFields + v3.Processors = processors + return nil +} diff --git a/service/telemetry/internal/migration/v0.2.0_test.go b/service/telemetry/internal/migration/v0.2.0_test.go new file mode 100644 index 000000000000..9c77df5fef57 --- /dev/null +++ b/service/telemetry/internal/migration/v0.2.0_test.go @@ -0,0 +1,40 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package migration + +import ( + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestUnmarshalLogsConfigV020(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "v0.2.0_logs.yaml")) + require.NoError(t, err) + + cfg := LogsConfigV030{} + require.NoError(t, cm.Unmarshal(&cfg)) + require.Len(t, cfg.Processors, 2) +} + +func TestUnmarshalTracesConfigV020(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "v0.2.0_traces.yaml")) + require.NoError(t, err) + + cfg := TracesConfigV030{} + require.NoError(t, cm.Unmarshal(&cfg)) + require.Len(t, cfg.Processors, 2) +} + +func TestUnmarshalMetricsConfigV020(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "v0.2.0_metrics.yaml")) + require.NoError(t, err) + + cfg := MetricsConfigV030{} + require.NoError(t, cm.Unmarshal(&cfg)) + require.Len(t, cfg.Readers, 2) +} diff --git a/service/telemetry/internal/migration/v0.3.0.go b/service/telemetry/internal/migration/v0.3.0.go new file mode 100644 index 000000000000..7190dd249350 --- /dev/null +++ b/service/telemetry/internal/migration/v0.3.0.go @@ -0,0 +1,174 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package migration // import "go.opentelemetry.io/collector/service/telemetry/internal/migration" + +import ( + "time" + + config "go.opentelemetry.io/contrib/config/v0.3.0" + "go.uber.org/zap/zapcore" + + "go.opentelemetry.io/collector/config/configtelemetry" + "go.opentelemetry.io/collector/confmap" +) + +type TracesConfigV030 struct { + // Level configures whether spans are emitted or not, the possible values are: + // - "none" indicates that no tracing data should be collected; + // - "basic" is the recommended and covers the basics of the service telemetry. + Level configtelemetry.Level `mapstructure:"level"` + // Propagators is a list of TextMapPropagators from the supported propagators list. Currently, + // tracecontext and b3 are supported. By default, the value is set to empty list and + // context propagation is disabled. + Propagators []string `mapstructure:"propagators"` + // Processors allow configuration of span processors to emit spans to + // any number of supported backends. + Processors []config.SpanProcessor `mapstructure:"processors"` +} + +func (c *TracesConfigV030) Unmarshal(conf *confmap.Conf) error { + if err := conf.Unmarshal(c); err != nil { + var v2TracesConfig tracesConfigV020 + // try unmarshaling using v0.2.0 struct + if e := conf.Unmarshal(&v2TracesConfig); e != nil { + // error could not be resolved through backwards + // compatibility attempts + return err + } + // TODO: add a warning log to tell users to migrate their config + return tracesConfigV02ToV03(v2TracesConfig, c) + } + return nil +} + +type MetricsConfigV030 struct { + // Level is the level of telemetry metrics, the possible values are: + // - "none" indicates that no telemetry data should be collected; + // - "basic" is the recommended and covers the basics of the service telemetry. + // - "normal" adds some other indicators on top of basic. + // - "detailed" adds dimensions and views to the previous levels. + Level configtelemetry.Level `mapstructure:"level"` + + // Deprecated: [v0.111.0] use readers configuration. + Address string `mapstructure:"address"` + + // Readers allow configuration of metric readers to emit metrics to + // any number of supported backends. + Readers []config.MetricReader `mapstructure:"readers"` +} + +func (c *MetricsConfigV030) Unmarshal(conf *confmap.Conf) error { + if err := conf.Unmarshal(c); err != nil { + var v02 metricsConfigV020 + // try unmarshaling using v0.2.0 struct + if e := conf.Unmarshal(&v02); e != nil { + // error could not be resolved through backwards + // compatibility attempts + return err + } + // TODO: add a warning log to tell users to migrate their config + return metricsConfigV02ToV03(v02, c) + } + return nil +} + +type LogsConfigV030 struct { + // Level is the minimum enabled logging level. + // (default = "INFO") + Level zapcore.Level `mapstructure:"level"` + + // Development puts the logger in development mode, which changes the + // behavior of DPanicLevel and takes stacktraces more liberally. + // (default = false) + Development bool `mapstructure:"development"` + + // Encoding sets the logger's encoding. + // Example values are "json", "console". + Encoding string `mapstructure:"encoding"` + + // DisableCaller stops annotating logs with the calling function's file + // name and line number. By default, all logs are annotated. + // (default = false) + DisableCaller bool `mapstructure:"disable_caller"` + + // DisableStacktrace completely disables automatic stacktrace capturing. By + // default, stacktraces are captured for WarnLevel and above logs in + // development and ErrorLevel and above in production. + // (default = false) + DisableStacktrace bool `mapstructure:"disable_stacktrace"` + + // Sampling sets a sampling policy. + // Default: + // sampling: + // enabled: true + // tick: 10s + // initial: 10 + // thereafter: 100 + // Sampling can be disabled by setting 'enabled' to false + Sampling *LogsSamplingConfig `mapstructure:"sampling"` + + // OutputPaths is a list of URLs or file paths to write logging output to. + // The URLs could only be with "file" schema or without schema. + // The URLs with "file" schema must be an absolute path. + // The URLs without schema are treated as local file paths. + // "stdout" and "stderr" are interpreted as os.Stdout and os.Stderr. + // see details at Open in zap/writer.go. + // (default = ["stderr"]) + OutputPaths []string `mapstructure:"output_paths"` + + // ErrorOutputPaths is a list of URLs or file paths to write zap internal logger errors to. + // The URLs could only be with "file" schema or without schema. + // The URLs with "file" schema must use absolute paths. + // The URLs without schema are treated as local file paths. + // "stdout" and "stderr" are interpreted as os.Stdout and os.Stderr. + // see details at Open in zap/writer.go. + // + // Note that this setting only affects the zap internal logger errors. + // (default = ["stderr"]) + ErrorOutputPaths []string `mapstructure:"error_output_paths"` + + // InitialFields is a collection of fields to add to the root logger. + // Example: + // + // initial_fields: + // foo: "bar" + // + // By default, there is no initial field. + InitialFields map[string]any `mapstructure:"initial_fields"` + + // Processors allow configuration of log record processors to emit logs to + // any number of suported backends. + Processors []config.LogRecordProcessor `mapstructure:"processors"` +} + +// LogsSamplingConfig sets a sampling strategy for the logger. Sampling caps the +// global CPU and I/O load that logging puts on your process while attempting +// to preserve a representative subset of your logs. +type LogsSamplingConfig struct { + // Enabled enable sampling logging + Enabled bool `mapstructure:"enabled"` + // Tick represents the interval in seconds that the logger apply each sampling. + Tick time.Duration `mapstructure:"tick"` + // Initial represents the first M messages logged each Tick. + Initial int `mapstructure:"initial"` + // Thereafter represents the sampling rate, every Nth message will be sampled after Initial messages are logged during each Tick. + // If Thereafter is zero, the logger will drop all the messages after the Initial each Tick. + Thereafter int `mapstructure:"thereafter"` +} + +func (c *LogsConfigV030) Unmarshal(conf *confmap.Conf) error { + if err := conf.Unmarshal(c); err != nil { + var v02 logsConfigV020 + // try unmarshaling using v0.2.0 struct + if e := conf.Unmarshal(&v02); e != nil { + // error could not be resolved through backwards + // compatibility attempts + return err + } + // TODO: add a warning log to tell users to migrate their config + return logsConfigV02ToV03(v02, c) + } + // + return nil +} diff --git a/service/telemetry/internal/migration/v0.3.0_test.go b/service/telemetry/internal/migration/v0.3.0_test.go new file mode 100644 index 000000000000..a22c252197b8 --- /dev/null +++ b/service/telemetry/internal/migration/v0.3.0_test.go @@ -0,0 +1,40 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package migration + +import ( + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestUnmarshalLogsConfigV030(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "v0.3.0_logs.yaml")) + require.NoError(t, err) + + cfg := LogsConfigV030{} + require.NoError(t, cm.Unmarshal(&cfg)) + require.Len(t, cfg.Processors, 2) +} + +func TestUnmarshalTracesConfigV030(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "v0.3.0_traces.yaml")) + require.NoError(t, err) + + cfg := TracesConfigV030{} + require.NoError(t, cm.Unmarshal(&cfg)) + require.Len(t, cfg.Processors, 2) +} + +func TestUnmarshalMetricsConfigV030(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "v0.3.0_metrics.yaml")) + require.NoError(t, err) + + cfg := MetricsConfigV030{} + require.NoError(t, cm.Unmarshal(&cfg)) + require.Len(t, cfg.Readers, 2) +} diff --git a/service/telemetry/internal/otelinit/config.go b/service/telemetry/internal/otelinit/config.go deleted file mode 100644 index 8e4a5c45adf0..000000000000 --- a/service/telemetry/internal/otelinit/config.go +++ /dev/null @@ -1,341 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package otelinit // import "go.opentelemetry.io/collector/service/telemetry/internal/otelinit" - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "net" - "net/http" - "net/url" - "os" - "strconv" - "strings" - "sync" - "time" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - "go.opentelemetry.io/contrib/config" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" - otelprom "go.opentelemetry.io/otel/exporters/prometheus" - "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" - "go.opentelemetry.io/otel/sdk/instrumentation" - sdkmetric "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/metric/metricdata" - "go.opentelemetry.io/otel/sdk/resource" - "google.golang.org/grpc/credentials" - - semconv "go.opentelemetry.io/collector/semconv/v1.18.0" -) - -const ( - - // gRPC Instrumentation Name - GRPCInstrumentation = "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" - - // http Instrumentation Name - HTTPInstrumentation = "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" - - // supported protocols - protocolProtobufHTTP = "http/protobuf" - protocolProtobufGRPC = "grpc/protobuf" - defaultReadHeaderTimeout = 10 * time.Second -) - -var ( - // GRPCUnacceptableKeyValues is a list of high cardinality grpc attributes that should be filtered out. - GRPCUnacceptableKeyValues = attribute.NewSet( - attribute.String(semconv.AttributeNetSockPeerAddr, ""), - attribute.String(semconv.AttributeNetSockPeerPort, ""), - attribute.String(semconv.AttributeNetSockPeerName, ""), - ) - - // HTTPUnacceptableKeyValues is a list of high cardinality http attributes that should be filtered out. - HTTPUnacceptableKeyValues = attribute.NewSet( - attribute.String(semconv.AttributeNetHostName, ""), - attribute.String(semconv.AttributeNetHostPort, ""), - ) - - errNoValidMetricExporter = errors.New("no valid metric exporter") -) - -func InitMetricReader(ctx context.Context, reader config.MetricReader, asyncErrorChannel chan error, serverWG *sync.WaitGroup) (sdkmetric.Reader, *http.Server, error) { - if reader.Pull != nil { - return initPullExporter(reader.Pull.Exporter, asyncErrorChannel, serverWG) - } - if reader.Periodic != nil { - var opts []sdkmetric.PeriodicReaderOption - if reader.Periodic.Interval != nil { - opts = append(opts, sdkmetric.WithInterval(time.Duration(*reader.Periodic.Interval)*time.Millisecond)) - } - - if reader.Periodic.Timeout != nil { - opts = append(opts, sdkmetric.WithTimeout(time.Duration(*reader.Periodic.Timeout)*time.Millisecond)) - } - return initPeriodicExporter(ctx, reader.Periodic.Exporter, opts...) - } - return nil, nil, fmt.Errorf("unsupported metric reader type %v", reader) -} - -func InitOpenTelemetry(res *resource.Resource, options []sdkmetric.Option, disableHighCardinality bool) (*sdkmetric.MeterProvider, error) { - opts := []sdkmetric.Option{ - sdkmetric.WithResource(res), - sdkmetric.WithView(disableHighCardinalityViews(disableHighCardinality)...), - } - - opts = append(opts, options...) - return sdkmetric.NewMeterProvider( - opts..., - ), nil -} - -func InitPrometheusServer(registry *prometheus.Registry, address string, asyncErrorChannel chan error, serverWG *sync.WaitGroup) *http.Server { - mux := http.NewServeMux() - mux.Handle("/metrics", promhttp.HandlerFor(registry, promhttp.HandlerOpts{})) - server := &http.Server{ - Addr: address, - Handler: mux, - ReadHeaderTimeout: defaultReadHeaderTimeout, - } - - serverWG.Add(1) - go func() { - defer serverWG.Done() - if serveErr := server.ListenAndServe(); serveErr != nil && !errors.Is(serveErr, http.ErrServerClosed) { - select { - case asyncErrorChannel <- serveErr: - case <-time.After(1 * time.Second): - } - } - }() - return server -} - -func disableHighCardinalityViews(disableHighCardinality bool) []sdkmetric.View { - if !disableHighCardinality { - return nil - } - return []sdkmetric.View{ - sdkmetric.NewView( - sdkmetric.Instrument{Scope: instrumentation.Scope{Name: GRPCInstrumentation}}, - sdkmetric.Stream{ - AttributeFilter: cardinalityFilter(GRPCUnacceptableKeyValues), - }), - sdkmetric.NewView( - sdkmetric.Instrument{Scope: instrumentation.Scope{Name: HTTPInstrumentation}}, - sdkmetric.Stream{ - AttributeFilter: cardinalityFilter(HTTPUnacceptableKeyValues), - }), - } -} - -func cardinalityFilter(filter attribute.Set) attribute.Filter { - return func(kv attribute.KeyValue) bool { - return !filter.HasValue(kv.Key) - } -} - -func initPrometheusExporter(prometheusConfig *config.Prometheus, asyncErrorChannel chan error, serverWG *sync.WaitGroup) (sdkmetric.Reader, *http.Server, error) { - promRegistry := prometheus.NewRegistry() - if prometheusConfig.Host == nil { - return nil, nil, errors.New("host must be specified") - } - if prometheusConfig.Port == nil { - return nil, nil, errors.New("port must be specified") - } - - opts := []otelprom.Option{ - otelprom.WithRegisterer(promRegistry), - // https://github.com/open-telemetry/opentelemetry-collector/issues/8043 - otelprom.WithoutUnits(), - // Disabled for the moment until this becomes stable, and we are ready to break backwards compatibility. - otelprom.WithoutScopeInfo(), - // This allows us to produce metrics that are backwards compatible w/ opencensus - otelprom.WithoutCounterSuffixes(), - otelprom.WithResourceAsConstantLabels(attribute.NewDenyKeysFilter()), - } - exporter, err := otelprom.New(opts...) - if err != nil { - return nil, nil, fmt.Errorf("error creating otel prometheus exporter: %w", err) - } - - return exporter, InitPrometheusServer(promRegistry, net.JoinHostPort(*prometheusConfig.Host, strconv.Itoa(*prometheusConfig.Port)), asyncErrorChannel, serverWG), nil -} - -func initPullExporter(exporter config.MetricExporter, asyncErrorChannel chan error, serverWG *sync.WaitGroup) (sdkmetric.Reader, *http.Server, error) { - if exporter.Prometheus != nil { - return initPrometheusExporter(exporter.Prometheus, asyncErrorChannel, serverWG) - } - return nil, nil, errNoValidMetricExporter -} - -func initPeriodicExporter(ctx context.Context, exporter config.MetricExporter, opts ...sdkmetric.PeriodicReaderOption) (sdkmetric.Reader, *http.Server, error) { - if exporter.Console != nil { - enc := json.NewEncoder(os.Stdout) - enc.SetIndent("", " ") - - exp, err := stdoutmetric.New( - stdoutmetric.WithEncoder(enc), - ) - if err != nil { - return nil, nil, err - } - return sdkmetric.NewPeriodicReader(exp, opts...), nil, nil - } - if exporter.OTLP != nil { - var err error - var exp sdkmetric.Exporter - switch exporter.OTLP.Protocol { - case protocolProtobufHTTP: - exp, err = initOTLPHTTPExporter(ctx, exporter.OTLP) - case protocolProtobufGRPC: - exp, err = initOTLPgRPCExporter(ctx, exporter.OTLP) - default: - return nil, nil, fmt.Errorf("unsupported protocol %s", exporter.OTLP.Protocol) - } - if err != nil { - return nil, nil, err - } - return sdkmetric.NewPeriodicReader(exp, opts...), nil, nil - } - return nil, nil, errNoValidMetricExporter -} - -func normalizeEndpoint(endpoint string) string { - if !strings.HasPrefix(endpoint, "https://") && !strings.HasPrefix(endpoint, "http://") { - return "http://" + endpoint - } - return endpoint -} - -func initOTLPgRPCExporter(ctx context.Context, otlpConfig *config.OTLPMetric) (sdkmetric.Exporter, error) { - opts := []otlpmetricgrpc.Option{} - - if len(otlpConfig.Endpoint) > 0 { - u, err := url.ParseRequestURI(normalizeEndpoint(otlpConfig.Endpoint)) - if err != nil { - return nil, err - } - opts = append(opts, otlpmetricgrpc.WithEndpoint(u.Host)) - if u.Scheme == "http" { - opts = append(opts, otlpmetricgrpc.WithInsecure()) - } else if otlpConfig.Certificate != nil { - creds, err := credentials.NewClientTLSFromFile(*otlpConfig.Certificate, "") - if err != nil { - return nil, fmt.Errorf("could not create client tls credentials: %w", err) - } - opts = append(opts, otlpmetricgrpc.WithTLSCredentials(creds)) - } - } - - if otlpConfig.Compression != nil { - switch *otlpConfig.Compression { - case "gzip": - opts = append(opts, otlpmetricgrpc.WithCompressor(*otlpConfig.Compression)) - case "none": - 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))) - } - if len(otlpConfig.Headers) > 0 { - opts = append(opts, otlpmetricgrpc.WithHeaders(otlpConfig.Headers)) - } - if otlpConfig.TemporalityPreference != nil { - switch *otlpConfig.TemporalityPreference { - case "delta": - opts = append(opts, otlpmetricgrpc.WithTemporalitySelector(temporalityPreferenceDelta)) - case "cumulative": - opts = append(opts, otlpmetricgrpc.WithTemporalitySelector(temporalityPreferenceCumulative)) - case "lowmemory": - opts = append(opts, otlpmetricgrpc.WithTemporalitySelector(temporalityPreferenceLowMemory)) - default: - return nil, fmt.Errorf("unsupported temporality preference %q", *otlpConfig.TemporalityPreference) - } - } - - return otlpmetricgrpc.New(ctx, opts...) -} - -func initOTLPHTTPExporter(ctx context.Context, otlpConfig *config.OTLPMetric) (sdkmetric.Exporter, error) { - opts := []otlpmetrichttp.Option{} - - if len(otlpConfig.Endpoint) > 0 { - u, err := url.ParseRequestURI(normalizeEndpoint(otlpConfig.Endpoint)) - if err != nil { - return nil, err - } - opts = append(opts, otlpmetrichttp.WithEndpoint(u.Host)) - - if u.Scheme == "http" { - opts = append(opts, otlpmetrichttp.WithInsecure()) - } - if len(u.Path) > 0 { - opts = append(opts, otlpmetrichttp.WithURLPath(u.Path)) - } - } - if otlpConfig.Compression != nil { - switch *otlpConfig.Compression { - case "gzip": - opts = append(opts, otlpmetrichttp.WithCompression(otlpmetrichttp.GzipCompression)) - case "none": - opts = append(opts, otlpmetrichttp.WithCompression(otlpmetrichttp.NoCompression)) - default: - return nil, fmt.Errorf("unsupported compression %q", *otlpConfig.Compression) - } - } - if otlpConfig.Timeout != nil { - opts = append(opts, otlpmetrichttp.WithTimeout(time.Millisecond*time.Duration(*otlpConfig.Timeout))) - } - if len(otlpConfig.Headers) > 0 { - opts = append(opts, otlpmetrichttp.WithHeaders(otlpConfig.Headers)) - } - if otlpConfig.TemporalityPreference != nil { - switch *otlpConfig.TemporalityPreference { - case "delta": - opts = append(opts, otlpmetrichttp.WithTemporalitySelector(temporalityPreferenceDelta)) - case "cumulative": - opts = append(opts, otlpmetrichttp.WithTemporalitySelector(temporalityPreferenceCumulative)) - case "lowmemory": - opts = append(opts, otlpmetrichttp.WithTemporalitySelector(temporalityPreferenceLowMemory)) - default: - return nil, fmt.Errorf("unsupported temporality preference %q", *otlpConfig.TemporalityPreference) - } - } - - return otlpmetrichttp.New(ctx, opts...) -} - -func temporalityPreferenceCumulative(_ sdkmetric.InstrumentKind) metricdata.Temporality { - return metricdata.CumulativeTemporality -} - -func temporalityPreferenceDelta(ik sdkmetric.InstrumentKind) metricdata.Temporality { - switch ik { - case sdkmetric.InstrumentKindCounter, sdkmetric.InstrumentKindObservableCounter, sdkmetric.InstrumentKindHistogram: - return metricdata.DeltaTemporality - case sdkmetric.InstrumentKindObservableUpDownCounter, sdkmetric.InstrumentKindUpDownCounter: - return metricdata.CumulativeTemporality - default: - return metricdata.DeltaTemporality - } -} - -func temporalityPreferenceLowMemory(ik sdkmetric.InstrumentKind) metricdata.Temporality { - switch ik { - case sdkmetric.InstrumentKindCounter, sdkmetric.InstrumentKindHistogram: - return metricdata.DeltaTemporality - case sdkmetric.InstrumentKindObservableCounter, sdkmetric.InstrumentKindObservableUpDownCounter, sdkmetric.InstrumentKindUpDownCounter: - return metricdata.CumulativeTemporality - default: - return metricdata.DeltaTemporality - } -} diff --git a/service/telemetry/internal/otelinit/config_test.go b/service/telemetry/internal/otelinit/config_test.go deleted file mode 100644 index 5041a9d322c8..000000000000 --- a/service/telemetry/internal/otelinit/config_test.go +++ /dev/null @@ -1,601 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package otelinit - -import ( - "context" - "errors" - "fmt" - "net/url" - "path/filepath" - "reflect" - "sync" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.opentelemetry.io/contrib/config" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" - otelprom "go.opentelemetry.io/otel/exporters/prometheus" - "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" - sdkmetric "go.opentelemetry.io/otel/sdk/metric" -) - -func strPtr(s string) *string { - return &s -} - -func intPtr(i int) *int { - return &i -} - -func TestMetricReader(t *testing.T) { - consoleExporter, err := stdoutmetric.New( - stdoutmetric.WithPrettyPrint(), - ) - require.NoError(t, err) - ctx := context.Background() - otlpGRPCExporter, err := otlpmetricgrpc.New(ctx) - require.NoError(t, err) - otlpHTTPExporter, err := otlpmetrichttp.New(ctx) - require.NoError(t, err) - promExporter, err := otelprom.New() - require.NoError(t, err) - - testCases := []struct { - name string - reader config.MetricReader - args any - wantErr error - wantReader sdkmetric.Reader - }{ - { - name: "noreader", - wantErr: errors.New("unsupported metric reader type { }"), - }, - { - name: "pull prometheus invalid exporter", - reader: config.MetricReader{ - Pull: &config.PullMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{}, - }, - }, - }, - wantErr: errNoValidMetricExporter, - }, - { - name: "pull/prometheus-invalid-config-no-host", - reader: config.MetricReader{ - Pull: &config.PullMetricReader{ - Exporter: config.MetricExporter{ - Prometheus: &config.Prometheus{}, - }, - }, - }, - wantErr: errors.New("host must be specified"), - }, - { - name: "pull/prometheus-invalid-config-no-port", - reader: config.MetricReader{ - Pull: &config.PullMetricReader{ - Exporter: config.MetricExporter{ - Prometheus: &config.Prometheus{ - Host: strPtr("localhost"), - }, - }, - }, - }, - wantErr: errors.New("port must be specified"), - }, - { - name: "pull/prometheus-valid", - reader: config.MetricReader{ - Pull: &config.PullMetricReader{ - Exporter: config.MetricExporter{ - Prometheus: &config.Prometheus{ - Host: strPtr("localhost"), - Port: intPtr(8080), - }, - }, - }, - }, - wantReader: promExporter, - }, - { - name: "periodic/invalid-exporter", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - Prometheus: &config.Prometheus{ - Host: strPtr("localhost"), - Port: intPtr(8080), - }, - }, - }, - }, - wantErr: errNoValidMetricExporter, - }, - { - name: "periodic/no-exporter", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{}, - }, - wantErr: errNoValidMetricExporter, - }, - { - name: "periodic/console-exporter", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - Console: config.Console{}, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(consoleExporter), - }, - { - name: "periodic/console-exporter-with-timeout-interval", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Interval: intPtr(10), - Timeout: intPtr(5), - Exporter: config.MetricExporter{ - Console: config.Console{}, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(consoleExporter), - }, - { - name: "periodic/otlp-exporter-invalid-protocol", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: *strPtr("http/invalid"), - }, - }, - }, - }, - wantErr: errors.New("unsupported protocol http/invalid"), - }, - { - name: "periodic/otlp-grpc-exporter-no-endpoint", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "grpc/protobuf", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(otlpGRPCExporter), - }, - { - name: "periodic/otlp-grpc-exporter", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "grpc/protobuf", - Endpoint: "http://localhost:4317", - Compression: strPtr("none"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(otlpGRPCExporter), - }, - { - name: "periodic/otlp-grpc-exporter-no-scheme", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "grpc/protobuf", - Endpoint: "localhost:4317", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(otlpGRPCExporter), - }, - { - name: "periodic/otlp-grpc-invalid-endpoint", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "grpc/protobuf", - Endpoint: " ", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - wantErr: &url.Error{Op: "parse", URL: "http:// ", Err: url.InvalidHostError(" ")}, - }, - { - name: "periodic/otlp-grpc-invalid-compression", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "grpc/protobuf", - Endpoint: "localhost:4317", - Compression: strPtr("invalid"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - wantErr: errors.New("unsupported compression \"invalid\""), - }, - { - name: "periodic/otlp-grpc-delta-temporality", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "grpc/protobuf", - Endpoint: "localhost:4318", - Compression: strPtr("none"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - TemporalityPreference: strPtr("delta"), - }, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(otlpGRPCExporter), - }, - { - name: "periodic/otlp-grpc-cumulative-temporality", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "grpc/protobuf", - Endpoint: "localhost:4318", - Compression: strPtr("none"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - TemporalityPreference: strPtr("cumulative"), - }, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(otlpGRPCExporter), - }, - { - name: "periodic/otlp-grpc-lowmemory-temporality", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "grpc/protobuf", - Endpoint: "localhost:4318", - Compression: strPtr("none"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - TemporalityPreference: strPtr("lowmemory"), - }, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(otlpGRPCExporter), - }, - { - name: "periodic/otlp-grpc-invalid-temporality", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "grpc/protobuf", - Endpoint: "localhost:4318", - Compression: strPtr("none"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - TemporalityPreference: strPtr("invalid"), - }, - }, - }, - }, - wantErr: errors.New("unsupported temporality preference \"invalid\""), - }, - { - name: "periodic/otlp-http-exporter", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "http/protobuf", - Endpoint: "http://localhost:4318", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(otlpHTTPExporter), - }, - { - name: "periodic/otlp-http-exporter-with-path", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "http/protobuf", - Endpoint: "http://localhost:4318/path/123", - Compression: strPtr("none"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(otlpHTTPExporter), - }, - { - name: "periodic/otlp-http-exporter-no-endpoint", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "http/protobuf", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(otlpHTTPExporter), - }, - { - name: "periodic/otlp-http-exporter-no-scheme", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "http/protobuf", - Endpoint: "localhost:4318", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(otlpHTTPExporter), - }, - { - name: "periodic/otlp-http-invalid-endpoint", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "http/protobuf", - Endpoint: " ", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - wantErr: &url.Error{Op: "parse", URL: "http:// ", Err: url.InvalidHostError(" ")}, - }, - { - name: "periodic/otlp-http-invalid-compression", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "http/protobuf", - Endpoint: "localhost:4318", - Compression: strPtr("invalid"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - wantErr: errors.New("unsupported compression \"invalid\""), - }, - { - name: "periodic/otlp-http-cumulative-temporality", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "http/protobuf", - Endpoint: "localhost:4318", - Compression: strPtr("none"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - TemporalityPreference: strPtr("cumulative"), - }, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(otlpHTTPExporter), - }, - { - name: "periodic/otlp-http-lowmemory-temporality", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "http/protobuf", - Endpoint: "localhost:4318", - Compression: strPtr("none"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - TemporalityPreference: strPtr("lowmemory"), - }, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(otlpHTTPExporter), - }, - { - name: "periodic/otlp-http-delta-temporality", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "http/protobuf", - Endpoint: "localhost:4318", - Compression: strPtr("none"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - TemporalityPreference: strPtr("delta"), - }, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(otlpHTTPExporter), - }, - { - name: "periodic/otlp-http-invalid-temporality", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "http/protobuf", - Endpoint: "localhost:4318", - Compression: strPtr("none"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - TemporalityPreference: strPtr("invalid"), - }, - }, - }, - }, - wantErr: errors.New("unsupported temporality preference \"invalid\""), - }, - { - name: "periodic/otlp-grpc-good-ca-certificate", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "grpc/protobuf", - Endpoint: "https://localhost:4317", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Certificate: strPtr(filepath.Join("testdata", "ca.crt")), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - wantReader: sdkmetric.NewPeriodicReader(otlpGRPCExporter), - }, - { - name: "periodic/otlp-grpc-bad-ca-certificate", - reader: config.MetricReader{ - Periodic: &config.PeriodicMetricReader{ - Exporter: config.MetricExporter{ - OTLP: &config.OTLPMetric{ - Protocol: "grpc/protobuf", - Endpoint: "https://localhost:4317", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Certificate: strPtr(filepath.Join("testdata", "bad_cert.crt")), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - wantErr: fmt.Errorf("could not create client tls credentials: %w", errors.New("credentials: failed to append certificates")), - }, - } - for _, tt := range testCases { - t.Run(tt.name, func(t *testing.T) { - gotReader, server, err := InitMetricReader(context.Background(), tt.reader, make(chan error), &sync.WaitGroup{}) - - defer func() { - if gotReader != nil { - require.NoError(t, gotReader.Shutdown(context.Background())) - } - if server != nil { - assert.NoError(t, server.Shutdown(context.Background())) - } - }() - - assert.Equal(t, tt.wantErr, err) - - if tt.wantReader == nil { - assert.Nil(t, gotReader) - } else { - assert.Equal(t, reflect.TypeOf(tt.wantReader), reflect.TypeOf(gotReader)) - - if reflect.TypeOf(tt.wantReader).String() == "*metric.PeriodicReader" { - wantExporterType := reflect.Indirect(reflect.ValueOf(tt.wantReader)).FieldByName("exporter").Elem().Type() - gotExporterType := reflect.Indirect(reflect.ValueOf(gotReader)).FieldByName("exporter").Elem().Type() - assert.Equal(t, wantExporterType, gotExporterType) - } - } - }) - } -} diff --git a/service/telemetry/logger_test.go b/service/telemetry/logger_test.go index 901c3fce79e4..6544ca0607e8 100644 --- a/service/telemetry/logger_test.go +++ b/service/telemetry/logger_test.go @@ -10,7 +10,7 @@ import ( "testing" "github.com/stretchr/testify/require" - "go.opentelemetry.io/contrib/config" + config "go.opentelemetry.io/contrib/config/v0.3.0" "go.uber.org/zap/zapcore" ) diff --git a/service/telemetry/metrics.go b/service/telemetry/metrics.go index 7705c74032b3..c8087afaffe4 100644 --- a/service/telemetry/metrics.go +++ b/service/telemetry/metrics.go @@ -4,179 +4,22 @@ package telemetry // import "go.opentelemetry.io/collector/service/telemetry" import ( - "context" - "net/http" - "sync" + "errors" - "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" - "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/noop" - "go.opentelemetry.io/otel/sdk/instrumentation" - sdkmetric "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/resource" - "go.uber.org/multierr" - "go.uber.org/zap" "go.opentelemetry.io/collector/config/configtelemetry" - "go.opentelemetry.io/collector/service/telemetry/internal/otelinit" ) -const ( - zapKeyTelemetryAddress = "address" - zapKeyTelemetryLevel = "metrics level" -) - -type meterProvider struct { - *sdkmetric.MeterProvider - servers []*http.Server - serverWG sync.WaitGroup -} - -type meterProviderSettings struct { - res *resource.Resource - cfg MetricsConfig - asyncErrorChannel chan error -} - -func dropViewOption(instrument sdkmetric.Instrument) sdkmetric.Option { - return sdkmetric.WithView(sdkmetric.NewView( - instrument, - sdkmetric.Stream{ - Aggregation: sdkmetric.AggregationDrop{}, - }, - )) -} - // newMeterProvider creates a new MeterProvider from Config. -func newMeterProvider(set meterProviderSettings, disableHighCardinality bool) (metric.MeterProvider, error) { - if set.cfg.Level == configtelemetry.LevelNone || len(set.cfg.Readers) == 0 { +func newMeterProvider(set Settings, cfg Config) (metric.MeterProvider, error) { + if cfg.Metrics.Level == configtelemetry.LevelNone || len(cfg.Metrics.Readers) == 0 { return noop.NewMeterProvider(), nil } - mp := &meterProvider{} - var opts []sdkmetric.Option - for _, reader := range set.cfg.Readers { - // https://github.com/open-telemetry/opentelemetry-collector/issues/8045 - r, server, err := otelinit.InitMetricReader(context.Background(), reader, set.asyncErrorChannel, &mp.serverWG) - if err != nil { - return nil, err - } - if server != nil { - mp.servers = append(mp.servers, server) - } - opts = append(opts, sdkmetric.WithReader(r)) - } - - if set.cfg.Level < configtelemetry.LevelDetailed { - // Drop all otelhttp and otelgrpc metrics if the level is not detailed. - opts = append(opts, - dropViewOption(sdkmetric.Instrument{ - Scope: instrumentation.Scope{Name: otelhttp.ScopeName}, - }), - dropViewOption(sdkmetric.Instrument{ - Scope: instrumentation.Scope{Name: otelgrpc.ScopeName}, - }), - ) - } - - // otel-arrow library metrics - // See https://github.com/open-telemetry/otel-arrow/blob/c39257/pkg/otel/arrow_record/consumer.go#L174-L176 - if set.cfg.Level < configtelemetry.LevelNormal { - scope := instrumentation.Scope{Name: "otel-arrow/pkg/otel/arrow_record"} - opts = append(opts, - dropViewOption(sdkmetric.Instrument{ - Name: "arrow_batch_records", - Scope: scope, - }), - dropViewOption(sdkmetric.Instrument{ - Name: "arrow_schema_resets", - Scope: scope, - }), - dropViewOption(sdkmetric.Instrument{ - Name: "arrow_memory_inuse", - Scope: scope, - }), - ) - } - - // contrib's internal/otelarrow/netstats metrics - // See - // - https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/a25f05/internal/otelarrow/netstats/netstats.go#L130 - // - https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/a25f05/internal/otelarrow/netstats/netstats.go#L165 - if set.cfg.Level < configtelemetry.LevelDetailed { - scope := instrumentation.Scope{Name: "github.com/open-telemetry/opentelemetry-collector-contrib/internal/otelarrow/netstats"} - // Compressed size metrics. - opts = append(opts, dropViewOption(sdkmetric.Instrument{ - Name: "otelcol_*_compressed_size", - Scope: scope, - })) - - opts = append(opts, dropViewOption(sdkmetric.Instrument{ - Name: "otelcol_*_compressed_size", - Scope: scope, - })) - - // makeRecvMetrics for exporters. - opts = append(opts, dropViewOption(sdkmetric.Instrument{ - Name: "otelcol_exporter_recv", - Scope: scope, - })) - opts = append(opts, dropViewOption(sdkmetric.Instrument{ - Name: "otelcol_exporter_recv_wire", - Scope: scope, - })) - - // makeSentMetrics for receivers. - opts = append(opts, dropViewOption(sdkmetric.Instrument{ - Name: "otelcol_receiver_sent", - Scope: scope, - })) - opts = append(opts, dropViewOption(sdkmetric.Instrument{ - Name: "otelcol_receiver_sent_wire", - Scope: scope, - })) - } - - // Batch processor metrics - if set.cfg.Level < configtelemetry.LevelDetailed { - scope := instrumentation.Scope{Name: "go.opentelemetry.io/collector/processor/batchprocessor"} - opts = append(opts, dropViewOption(sdkmetric.Instrument{ - Name: "otelcol_processor_batch_batch_send_size_bytes", - Scope: scope, - })) - } - - var err error - mp.MeterProvider, err = otelinit.InitOpenTelemetry(set.res, opts, disableHighCardinality) - if err != nil { - return nil, err + if set.SDK != nil { + return set.SDK.MeterProvider(), nil } - return mp, nil -} - -// LogAboutServers logs about the servers that are serving metrics. -func (mp *meterProvider) LogAboutServers(logger *zap.Logger, cfg MetricsConfig) { - for _, server := range mp.servers { - logger.Info( - "Serving metrics", - zap.String(zapKeyTelemetryAddress, server.Addr), - zap.Stringer(zapKeyTelemetryLevel, cfg.Level), - ) - } -} - -// Shutdown the meter provider and all the associated resources. -// The type signature of this method matches that of the sdkmetric.MeterProvider. -func (mp *meterProvider) Shutdown(ctx context.Context) error { - var errs error - for _, server := range mp.servers { - if server != nil { - errs = multierr.Append(errs, server.Close()) - } - } - errs = multierr.Append(errs, mp.MeterProvider.Shutdown(ctx)) - mp.serverWG.Wait() - - return errs + return nil, errors.New("no sdk set") } diff --git a/service/telemetry/metrics_test.go b/service/telemetry/metrics_test.go index 9e86b20e92c6..47f41e92f490 100644 --- a/service/telemetry/metrics_test.go +++ b/service/telemetry/metrics_test.go @@ -14,16 +14,13 @@ import ( "github.com/prometheus/common/expfmt" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opentelemetry.io/contrib/config" + config "go.opentelemetry.io/contrib/config/v0.3.0" + "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" - sdkresource "go.opentelemetry.io/otel/sdk/resource" - "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configtelemetry" semconv "go.opentelemetry.io/collector/semconv/v1.18.0" "go.opentelemetry.io/collector/service/internal/promtest" - "go.opentelemetry.io/collector/service/internal/resource" - "go.opentelemetry.io/collector/service/telemetry/internal/otelinit" ) const ( @@ -44,7 +41,6 @@ func TestTelemetryInit(t *testing.T) { for _, tt := range []struct { name string - disableHighCard bool expectedMetrics map[string]metricValue }{ { @@ -87,42 +83,10 @@ func TestTelemetryInit(t *testing.T) { "service_instance_id": testInstanceID, }, }, - }, - }, - { - name: "DisableHighCardinalityWithOtel", - disableHighCard: true, - expectedMetrics: map[string]metricValue{ - metricPrefix + otelPrefix + counterName: { - value: 13, - labels: map[string]string{ - "service_name": "otelcol", - "service_version": "latest", - "service_instance_id": testInstanceID, - }, - }, - metricPrefix + grpcPrefix + counterName: { - value: 11, - labels: map[string]string{ - "service_name": "otelcol", - "service_version": "latest", - "service_instance_id": testInstanceID, - }, - }, - metricPrefix + httpPrefix + counterName: { - value: 10, - labels: map[string]string{ - "service_name": "otelcol", - "service_version": "latest", - "service_instance_id": testInstanceID, - }, - }, - "target_info": { + "promhttp_metric_handler_errors_total": { value: 0, labels: map[string]string{ - "service_name": "otelcol", - "service_version": "latest", - "service_instance_id": testInstanceID, + "cause": "encoding", }, }, }, @@ -130,35 +94,36 @@ func TestTelemetryInit(t *testing.T) { } { prom := promtest.GetAvailableLocalAddressPrometheus(t) endpoint := fmt.Sprintf("http://%s:%d/metrics", *prom.Host, *prom.Port) + cfg := Config{ + Metrics: MetricsConfig{ + Level: configtelemetry.LevelDetailed, + Readers: []config.MetricReader{{ + Pull: &config.PullMetricReader{ + Exporter: config.PullMetricExporter{Prometheus: prom}, + }, + }}, + }, + } t.Run(tt.name, func(t *testing.T) { - cfg := &Config{ - Metrics: MetricsConfig{ - Level: configtelemetry.LevelDetailed, - Readers: []config.MetricReader{{ - Pull: &config.PullMetricReader{Exporter: config.MetricExporter{Prometheus: prom}}, - }}, - }, - Traces: TracesConfig{ - Processors: []config.SpanProcessor{ - { - Batch: &config.BatchSpanProcessor{ - Exporter: config.SpanExporter{ - Console: config.Console{}, - }, - }, + sdk, err := config.NewSDK( + config.WithContext(context.Background()), + config.WithOpenTelemetryConfiguration(config.OpenTelemetryConfiguration{ + MeterProvider: &config.MeterProvider{ + Readers: cfg.Metrics.Readers, + }, + Resource: &config.Resource{ + SchemaUrl: ptr(""), + Attributes: []config.AttributeNameValue{ + {Name: semconv.AttributeServiceInstanceID, Value: testInstanceID}, + {Name: semconv.AttributeServiceName, Value: "otelcol"}, + {Name: semconv.AttributeServiceVersion, Value: "latest"}, }, }, - }, - Resource: map[string]*string{ - semconv.AttributeServiceInstanceID: &testInstanceID, - }, - } - set := meterProviderSettings{ - res: resource.New(component.NewDefaultBuildInfo(), cfg.Resource), - cfg: cfg.Metrics, - asyncErrorChannel: make(chan error), - } - mp, err := newMeterProvider(set, tt.disableHighCard) + }), + ) + require.NoError(t, err) + + mp, err := newMeterProvider(Settings{SDK: &sdk}, cfg) require.NoError(t, err) defer func() { if prov, ok := mp.(interface{ Shutdown(context.Context) error }); ok { @@ -169,11 +134,14 @@ func TestTelemetryInit(t *testing.T) { createTestMetrics(t, mp) metrics := getMetricsFromPrometheus(t, endpoint) - require.Equal(t, len(tt.expectedMetrics), len(metrics)) + require.Len(t, metrics, len(tt.expectedMetrics)) for metricName, metricValue := range tt.expectedMetrics { mf, present := metrics[metricName] require.True(t, present, "expected metric %q was not present", metricName) + if metricName == "promhttp_metric_handler_errors_total" { + continue + } require.Len(t, mf.Metric, 1, "only one measure should exist for metric %q", metricName) labels := make(map[string]string) @@ -194,13 +162,20 @@ func createTestMetrics(t *testing.T, mp metric.MeterProvider) { require.NoError(t, err) counter.Add(context.Background(), 13) - grpcExampleCounter, err := mp.Meter(otelinit.GRPCInstrumentation).Int64Counter(metricPrefix + grpcPrefix + counterName) + grpcExampleCounter, err := mp.Meter("go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc").Int64Counter(metricPrefix + grpcPrefix + counterName) require.NoError(t, err) - grpcExampleCounter.Add(context.Background(), 11, metric.WithAttributeSet(otelinit.GRPCUnacceptableKeyValues)) + grpcExampleCounter.Add(context.Background(), 11, metric.WithAttributeSet(attribute.NewSet( + attribute.String(semconv.AttributeNetSockPeerAddr, ""), + attribute.String(semconv.AttributeNetSockPeerPort, ""), + attribute.String(semconv.AttributeNetSockPeerName, ""), + ))) - httpExampleCounter, err := mp.Meter(otelinit.HTTPInstrumentation).Int64Counter(metricPrefix + httpPrefix + counterName) + httpExampleCounter, err := mp.Meter("go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp").Int64Counter(metricPrefix + httpPrefix + counterName) require.NoError(t, err) - httpExampleCounter.Add(context.Background(), 10, metric.WithAttributeSet(otelinit.HTTPUnacceptableKeyValues)) + httpExampleCounter.Add(context.Background(), 10, metric.WithAttributeSet(attribute.NewSet( + attribute.String(semconv.AttributeNetHostName, ""), + attribute.String(semconv.AttributeNetHostPort, ""), + ))) } func getMetricsFromPrometheus(t *testing.T, endpoint string) map[string]*io_prometheus_client.MetricFamily { @@ -239,17 +214,32 @@ func getMetricsFromPrometheus(t *testing.T, endpoint string) map[string]*io_prom // See https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric/internal/x#readme-instrument-enabled. func TestInstrumentEnabled(t *testing.T) { prom := promtest.GetAvailableLocalAddressPrometheus(t) - set := meterProviderSettings{ - res: sdkresource.Default(), - cfg: MetricsConfig{ + cfg := Config{ + Metrics: MetricsConfig{ Level: configtelemetry.LevelDetailed, Readers: []config.MetricReader{{ - Pull: &config.PullMetricReader{Exporter: config.MetricExporter{Prometheus: prom}}, + Pull: &config.PullMetricReader{Exporter: config.PullMetricExporter{Prometheus: prom}}, }}, }, - asyncErrorChannel: make(chan error), } - meterProvider, err := newMeterProvider(set, false) + sdk, err := config.NewSDK( + config.WithContext(context.Background()), + config.WithOpenTelemetryConfiguration(config.OpenTelemetryConfiguration{ + MeterProvider: &config.MeterProvider{ + Readers: cfg.Metrics.Readers, + }, + Resource: &config.Resource{ + SchemaUrl: ptr(""), + Attributes: []config.AttributeNameValue{ + {Name: semconv.AttributeServiceInstanceID, Value: testInstanceID}, + {Name: semconv.AttributeServiceName, Value: "otelcol"}, + {Name: semconv.AttributeServiceVersion, Value: "latest"}, + }, + }, + }), + ) + require.NoError(t, err) + meterProvider, err := newMeterProvider(Settings{SDK: &sdk}, cfg) defer func() { if prov, ok := meterProvider.(interface{ Shutdown(context.Context) error }); ok { require.NoError(t, prov.Shutdown(context.Background())) @@ -301,3 +291,7 @@ func TestInstrumentEnabled(t *testing.T) { _, ok = floatGauge.(enabledInstrument) assert.True(t, ok, "Float64Gauge does not implement the experimental 'Enabled' method") } + +func ptr[T any](v T) *T { + return &v +} diff --git a/service/telemetry/tracer_test.go b/service/telemetry/tracer_test.go index 1af064e64990..929c2385dd15 100644 --- a/service/telemetry/tracer_test.go +++ b/service/telemetry/tracer_test.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/stretchr/testify/require" - "go.opentelemetry.io/contrib/config" + config "go.opentelemetry.io/contrib/config/v0.3.0" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/collector/config/configtelemetry"