diff --git a/.chloggen/TEMPLATE.yaml b/.chloggen/TEMPLATE.yaml index 5f4d66bd650..3e6c5003947 100644 --- a/.chloggen/TEMPLATE.yaml +++ b/.chloggen/TEMPLATE.yaml @@ -22,4 +22,4 @@ subtext: # Include 'user' if the change is relevant to end users. # Include 'api' if there is a change to a library API. # Default: '[user]' -change_logs: [] \ No newline at end of file +change_logs: [] diff --git a/.chloggen/builder-env.yaml b/.chloggen/builder-env.yaml deleted file mode 100644 index 600f8064564..00000000000 --- a/.chloggen/builder-env.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# 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: builder - -# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: fix setting `dist.*` keys from env - -# One or more tracking issues or pull requests related to the change -issues: [8239] - -# (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/codeboten_deprecate-obsreporttest.yaml b/.chloggen/codeboten_deprecate-obsreporttest.yaml deleted file mode 100755 index da127796df9..00000000000 --- a/.chloggen/codeboten_deprecate-obsreporttest.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# 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: obsreporttest - -# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: deprecate To*CreateSettings funcs in obsreporttest - -# One or more tracking issues or pull requests related to the change -issues: [8492] - -# (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: | - The following TestTelemetry methods have been deprecated: - - ToExporterCreateSettings -> exportertest.NewCreateSettings - - ToProcessorCreateSettings -> processortest.NewCreateSettings - - ToReceiverCreateSettings -> receivertest.NewCreateSettings - -# 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] \ No newline at end of file diff --git a/.chloggen/codeboten_obsreport-dep.yaml b/.chloggen/codeboten_obsreport-dep.yaml deleted file mode 100755 index dc524453e02..00000000000 --- a/.chloggen/codeboten_obsreport-dep.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# 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: obsreport - -# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: "Deprecating `obsreport.Exporter`, `obsreport.ExporterSettings`, `obsreport.NewExporter`" - -# One or more tracking issues or pull requests related to the change -issues: [8492] - -# (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: | - These deprecated methods/structs have been moved to exporterhelper: - - `obsreport.Exporter` -> `exporterhelper.ObsReport` - - `obsreport.ExporterSettings` -> `exporterhelper.ObsReportSettings` - - `obsreport.NewExporter` -> `exporterhelper.NewObsReport` - -# 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/codeboten_obsreport-processor.yaml b/.chloggen/codeboten_obsreport-processor.yaml deleted file mode 100755 index e7732da6763..00000000000 --- a/.chloggen/codeboten_obsreport-processor.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# 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: obsreport - -# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: "Deprecating `obsreport.BuildProcessorCustomMetricName`, `obsreport.Processor`, `obsreport.ProcessorSettings`, `obsreport.NewProcessor`" - -# One or more tracking issues or pull requests related to the change -issues: [8492] - -# (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: | - These deprecated methods/structs have been moved to processorhelper: - - `obsreport.BuildProcessorCustomMetricName` -> `processorhelper.BuildCustomMetricName` - - `obsreport.Processor` -> `processorhelper.ObsReport` - - `obsreport.ProcessorSettings` -> `processorhelper.ObsReportSettings` - - `obsreport.NewProcessor` -> `processorhelper.NewObsReport` - -# 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] \ No newline at end of file diff --git a/.chloggen/codeboten_obsreport-scraper.yaml b/.chloggen/codeboten_obsreport-scraper.yaml deleted file mode 100755 index 33dff252304..00000000000 --- a/.chloggen/codeboten_obsreport-scraper.yaml +++ /dev/null @@ -1,32 +0,0 @@ -# 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: obsreport - -# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: "Deprecating obsreport scraper and receiver API" - -# One or more tracking issues or pull requests related to the change -issues: [8492] - -# (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: | - These deprecated methods/structs have been moved to receiverhelper and scraperhelper: - - `obsreport.Receiver` -> `receiverhelper.ObsReport` - - `obsreport.ReceiverSettings` -> `receiverhelper.ObsReportSettings` - - `obsreport.NewReceiver` -> `receiverhelper.NewObsReport` - - `obsreport.Scraper` -> `scraperhelper.ObsReport` - - `obsreport.ScraperSettings` -> `scraperhelper.ObsReportSettings` - - `obsreport.NewScraper` -> `scraperhelper.NewObsReport` - -# 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] \ No newline at end of file diff --git a/.chloggen/codeboten_rm-pipelineconfig.yaml b/.chloggen/codeboten_rm-pipelineconfig.yaml deleted file mode 100755 index 3a434ba9363..00000000000 --- a/.chloggen/codeboten_rm-pipelineconfig.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# 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: service - -# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: remove deprecated service.PipelineConfig - -# One or more tracking issues or pull requests related to the change -issues: [8485] - -# (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] \ No newline at end of file diff --git a/.chloggen/codeboten_split-otelcol-module.yaml b/.chloggen/codeboten_split-otelcol-module.yaml deleted file mode 100755 index 54ec42558a6..00000000000 --- a/.chloggen/codeboten_split-otelcol-module.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# 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: otelcol - -# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: Splitting otelcol into its own module. - -# One or more tracking issues or pull requests related to the change -issues: [7924] - -# (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] \ No newline at end of file diff --git a/.chloggen/codeboten_split-service-module.yaml b/.chloggen/codeboten_split-service-module.yaml deleted file mode 100755 index eac53d5a636..00000000000 --- a/.chloggen/codeboten_split-service-module.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# 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: Split service into its own module - -# One or more tracking issues or pull requests related to the change -issues: [7923] - -# (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] \ No newline at end of file diff --git a/.chloggen/debug-exporter-2.yaml b/.chloggen/debug-exporter-2.yaml deleted file mode 100644 index 11d7e548e64..00000000000 --- a/.chloggen/debug-exporter-2.yaml +++ /dev/null @@ -1,17 +0,0 @@ - -# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' -change_type: new_component - -# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) -component: debugexporter - -# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: Add debug exporter, which replaces the logging exporter - -# One or more tracking issues or pull requests related to the change -issues: [7769] - -# (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: diff --git a/.chloggen/debug-exporter.yaml b/.chloggen/debug-exporter.yaml deleted file mode 100644 index c82a36f4f2f..00000000000 --- a/.chloggen/debug-exporter.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# 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: loggingexporter - -# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: Mark the logging exporter as deprecated, in favour of debug exporter - -# One or more tracking issues or pull requests related to the change -issues: [7769] - -# (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: diff --git a/.chloggen/fix-incorrect-use-of-fsnotify.yaml b/.chloggen/fix-incorrect-use-of-fsnotify.yaml deleted file mode 100644 index a9b21921364..00000000000 --- a/.chloggen/fix-incorrect-use-of-fsnotify.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# 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: configtls - -# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: fix incorrect use of fsnotify - -# One or more tracking issues or pull requests related to the change -issues: [8438] - -# (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/log-featuregates.yaml b/.chloggen/log-featuregates.yaml deleted file mode 100755 index 08e245dab45..00000000000 --- a/.chloggen/log-featuregates.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# 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: featuregate - -# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: List valid feature gates when failing to load invalid gate - -# One or more tracking issues or pull requests related to the change -issues: [8505] - -# (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: [] \ No newline at end of file diff --git a/.chloggen/s390x-platform-enablement.yaml b/.chloggen/s390x-platform-enablement.yaml deleted file mode 100755 index 1e7a88eb69c..00000000000 --- a/.chloggen/s390x-platform-enablement.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# 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: supported platforms - -# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: Add `linux/s390x` architecture to cross build tests in CI - -# One or more tracking issues or pull requests related to the change -issues: [8213] - -# (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: diff --git a/.codecov.yml b/.codecov.yml index 684b3772c07..b7698210cd3 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -19,3 +19,4 @@ coverage: ignore: - "pdata/internal/data/protogen/**/*" + - "cmd/mdatagen/third_party/**/*" diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..d46e10b98c1 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +# This file is documented at https://git-scm.com/docs/gitattributes. +# Linguist-specific attributes are documented at +# https://github.com/github/linguist. + +go.sum linguist-generated=true diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 9003260b2e4..9211c804bae 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -8,26 +8,26 @@ assignees: '' --- **Describe the bug** -A clear and concise description of what the bug is. + **Steps to reproduce** -If possible, provide a recipe for reproducing the error. + **What did you expect to see?** -A clear and concise description of what you expected to see. + **What did you see instead?** -A clear and concise description of what you saw instead. + **What version did you use?** -Version: (e.g., `v0.4.0`, `1eb551b`, etc) + **What config did you use?** -Config: (e.g. the yaml config file) + **Environment** -OS: (e.g., "Ubuntu 20.04") -Compiler(if manually compiled): (e.g., "go 14.2") + + **Additional context** -Add any other context about the problem here. + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 7c965d578f0..17843187e81 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -9,8 +9,8 @@ assignees: '' ## Important (read before submitting) We are currently preparing for the upcoming 1.0 GA release. Feature requests that are not aligned with -the current roadmap https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/roadmap.md -and are not aimed at stabilizing and preparing the Collector for the release will not be prioritized. +the current roadmap and are not aimed at stabilizing and preparing the Collector for the release will +not be prioritized. _Delete this paragraph before submitting._ diff --git a/.github/ISSUE_TEMPLATE/stabilization.md b/.github/ISSUE_TEMPLATE/stabilization.md new file mode 100644 index 00000000000..aea8102517b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/stabilization.md @@ -0,0 +1,25 @@ +--- +name: Module stabilization +about: Stabilize a module before a 1.0 release +title: 'Stabilize module X' +labels: 'stabilization' +assignees: '' +--- + +Before stabilizing a module, an approver or maintainer must make sure that the following criteria have been met for at least two successive minor version releases (regardless of when this issue was opened): + +- [ ] No open issues or PRs in the module that would require breaking changes +- [ ] No TODOs in the module code that would require breaking changes +- [ ] No deprecated symbols in the module +- [ ] No symbols marked as experimental in the module +- [ ] The module follows the [Coding guidelines](https://github.com/open-telemetry/opentelemetry-collector/blob/main/CONTRIBUTING.md) + +Please also make sure to publicly announce our intent to stabilize the module on: + +- [ ] The #otel-collector CNCF Slack Channel +- [ ] The #opentelemetry CNCF Slack channel +- [ ] A Collector SIG meeting (if unable to attend, just add to the agenda) + +To help other people verify the above criteria, please link to the announcement and other links used to complete the above in a comment on this issue. + +Once all criteria are met, close this issue by moving this module to the `stable` module set. diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 3614e5e928d..00000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,194 +0,0 @@ -# File generated by "make gendependabot"; DO NOT EDIT. - -version: 2 -updates: - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/cmd/builder" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/cmd/otelcorecol" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/component" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/config/configauth" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/config/configcompression" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/config/configgrpc" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/config/confighttp" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/config/confignet" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/config/configopaque" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/config/configtelemetry" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/config/configtls" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/config/internal" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/confmap" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/connector" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/connector/forwardconnector" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/consumer" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/exporter" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/exporter/debugexporter" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/exporter/loggingexporter" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/exporter/otlpexporter" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/exporter/otlphttpexporter" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/extension" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/extension/auth" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/extension/ballastextension" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/extension/zpagesextension" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/featuregate" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/internal/tools" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/otelcol" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/pdata" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/processor" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/processor/batchprocessor" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/processor/memorylimiterprocessor" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/receiver" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/receiver/otlpreceiver" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/semconv" - schedule: - interval: "weekly" - day: "wednesday" - - package-ecosystem: "gomod" - directory: "/service" - schedule: - interval: "weekly" - day: "wednesday" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 308a6cf2bc5..cde4e56a1c5 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,18 +1,18 @@ ## Important (read before submitting) We are currently preparing for the upcoming 1.0 GA release. Pull requests that are not aligned with -the current roadmap https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/roadmap.md -and are not aimed at stabilizing and preparing the Collector for the release will not be accepted. +the current roadmap and are not aimed at stabilizing and preparing the Collector for the release will +not be accepted. -_Delete this paragraph before submitting._ +_Delete the preceding paragraph before submitting._ -**Description:** +**Description:** + **Link to tracking Issue:** -**Testing:** < Describe what testing was performed and which tests were added.> +**Testing:** -**Documentation:** < Describe the documentation added.> +**Documentation:** _Please delete paragraphs that you did not use before submitting._ diff --git a/.github/workflows/api-compatibility.yml b/.github/workflows/api-compatibility.yml index 5e73b1dde85..8bed13f01a8 100644 --- a/.github/workflows/api-compatibility.yml +++ b/.github/workflows/api-compatibility.yml @@ -7,11 +7,12 @@ name: "Inform Incompatible PRs" on: pull_request: - paths-ignore: - - 'cmd/builder/**' branches: - main +permissions: + contents: read + jobs: Check-Compatibility: runs-on: macos-latest @@ -21,20 +22,20 @@ jobs: steps: - name: Checkout-Main - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: ref: ${{ github.base_ref }} path: ${{ github.base_ref }} - name: Checkout-HEAD - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: path: ${{ github.head_ref }} - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 # Generate apidiff states of Main - name: Generate-States diff --git a/.github/workflows/build-and-test-windows.yaml b/.github/workflows/build-and-test-windows.yaml index 653536a0763..4fca5f3ffc6 100644 --- a/.github/workflows/build-and-test-windows.yaml +++ b/.github/workflows/build-and-test-windows.yaml @@ -10,18 +10,22 @@ concurrency: group: ${{ github.workflow }}-${{ github.head_ref }} cancel-in-progress: true +permissions: + contents: read + jobs: windows-unittest: runs-on: windows-latest steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 + cache: false - name: Cache Go - uses: actions/cache@v3 + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 env: cache-name: cache-go-modules with: diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 3d5a9a60a82..a9421cb4976 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -15,14 +15,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 + cache: false - name: Cache Go id: go-cache - uses: actions/cache@v3 + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: | ~/go/bin @@ -37,14 +38,15 @@ jobs: needs: [setup-environment] steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 + cache: false - name: Cache Go id: go-cache - uses: actions/cache@v3 + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: | ~/go/bin @@ -60,14 +62,15 @@ jobs: timeout-minutes: 30 steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 + cache: false - name: Cache Go id: go-cache - uses: actions/cache@v3 + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: | ~/go/bin @@ -84,14 +87,15 @@ jobs: needs: [setup-environment] steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 + cache: false - name: Cache Go id: go-cache - uses: actions/cache@v3 + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: | ~/go/bin @@ -103,6 +107,10 @@ jobs: run: make misspell - name: checkdoc run: make checkdoc + - name: Check for go mod dependency changes + run: | + make gotidy + git diff --exit-code || (echo 'go.mod/go.sum deps changes detected, please run "make gotidy" and commit the changes in this PR.' && exit 1) - name: go:porto run: | make goporto @@ -115,10 +123,6 @@ jobs: run: | make genpdata git diff --exit-code || (echo 'Generated code is out of date, please run "make genpdata" and commit the changes in this PR.' && exit 1) - - name: Gen dependabot - run: | - make gendependabot - git diff -s --exit-code || (echo 'ALL_MODULES have been changed, please run "make gendependabot" and commit the changes in this PR.' && exit 1) - name: Gen otelcorecol run: | make genotelcorecol @@ -133,26 +137,27 @@ jobs: unittest-matrix: strategy: matrix: - go-version: ["~1.21.1", "~1.20.8"] # 1.20 needs quotes otherwise it's interpreted as 1.2 + go-version: ["~1.22", "~1.21.5"] # 1.20 needs quotes otherwise it's interpreted as 1.2 runs-on: ubuntu-latest needs: [setup-environment] steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: ${{ matrix.go-version }} + cache: false - name: Cache Go id: go-cache - uses: actions/cache@v3 + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: | ~/go/bin ~/go/pkg/mod key: go-cache-${{ runner.os }}-${{ hashFiles('**/go.sum') }} - name: Cache Build - uses: actions/cache@v3 + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: ~/.cache/go-build key: unittest-${{ runner.os }}-go-build-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }} @@ -180,28 +185,29 @@ jobs: needs: [setup-environment] steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.6 + go-version: ~1.21.5 + cache: false - name: Cache Go id: go-cache - uses: actions/cache@v3 + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: | ~/go/bin ~/go/pkg/mod key: go-cache-${{ runner.os }}-${{ hashFiles('**/go.sum') }} - name: Cache Build - uses: actions/cache@v3 + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: ~/.cache/go-build key: coverage-${{ runner.os }}-go-build-${{ hashFiles('**/go.sum') }} - name: Run Unit Tests With Coverage run: make gotest-with-cover - name: Upload coverage report - uses: Wandalen/wretry.action@v1.3.0 + uses: Wandalen/wretry.action@0ef67d343938e879e0a9bb37c107a55731e8ed35 # v1.4.5 with: action: codecov/codecov-action@v3 with: | @@ -247,14 +253,15 @@ jobs: steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 + cache: false - name: Cache Go id: go-cache - uses: actions/cache@v3 + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: | ~/go/bin diff --git a/.github/workflows/builder-integration-test.yaml b/.github/workflows/builder-integration-test.yaml index 11673455023..840fe378de3 100644 --- a/.github/workflows/builder-integration-test.yaml +++ b/.github/workflows/builder-integration-test.yaml @@ -20,16 +20,19 @@ concurrency: group: ${{ github.workflow }}-${{ github.head_ref }} cancel-in-progress: true +permissions: + contents: read + jobs: integration-test: name: Integration test runs-on: ubuntu-latest steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 - name: Test run: make builder-integration-test diff --git a/.github/workflows/builder-release.yaml b/.github/workflows/builder-release.yaml index c674b08dc57..12b128e8d17 100644 --- a/.github/workflows/builder-release.yaml +++ b/.github/workflows/builder-release.yaml @@ -10,15 +10,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: fetch-depth: 0 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v5 + uses: goreleaser/goreleaser-action@7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8 # v5.0.0 with: distribution: goreleaser-pro version: latest @@ -31,7 +31,7 @@ jobs: gh release create ${{ github.ref_name }} -t ${{ github.ref_name }} -n "### Images and binaries here: https://github.com/open-telemetry/opentelemetry-collector-releases/releases/tag/${{ github.ref_name }}" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: actions/github-script@v6 + - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | const milestones = await github.rest.issues.listMilestones({ diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 19ee4aad2b2..7a57b9421d5 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -14,6 +14,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.head_ref }} cancel-in-progress: true +permissions: + contents: read + jobs: changelog: runs-on: ubuntu-latest @@ -23,16 +26,16 @@ jobs: PR_HEAD: ${{ github.event.pull_request.head.sha }} steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: fetch-depth: 0 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 - name: Cache Go id: go-cache - uses: actions/cache@v3 + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: | ~/go/bin diff --git a/.github/workflows/check-links.yaml b/.github/workflows/check-links.yaml index 88ce28e6de9..338e0718131 100644 --- a/.github/workflows/check-links.yaml +++ b/.github/workflows/check-links.yaml @@ -2,16 +2,15 @@ name: check-links on: push: branches: [ main ] - paths-ignore: - - 'cmd/builder/**' pull_request: - paths-ignore: - - 'cmd/builder/**' concurrency: group: ${{ github.workflow }}-${{ github.head_ref }} cancel-in-progress: true +permissions: + contents: read + jobs: changedfiles: name: changed files @@ -22,7 +21,7 @@ jobs: md: ${{ steps.changes.outputs.md }} steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: fetch-depth: 0 - name: Get changed files @@ -35,7 +34,7 @@ jobs: if: ${{needs.changedfiles.outputs.md}} steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: fetch-depth: 0 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e3ff82e2256..c49d7dc19af 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -8,27 +8,34 @@ concurrency: group: ${{ github.workflow }}-${{ github.head_ref }} cancel-in-progress: true +permissions: + contents: read + jobs: CodeQL-Build: + permissions: + actions: read # for github/codeql-action/init to get workflow details + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/autobuild to send a status report runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 with: languages: go - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 diff --git a/.github/workflows/contrib-tests.yml b/.github/workflows/contrib-tests.yml index 2a9d85d4f63..d17bfb6f9a8 100644 --- a/.github/workflows/contrib-tests.yml +++ b/.github/workflows/contrib-tests.yml @@ -12,20 +12,57 @@ concurrency: group: ${{ github.workflow }}-${{ github.head_ref }} cancel-in-progress: true +permissions: + contents: read + jobs: - contrib_tests: + contrib-tests-matrix: runs-on: ubuntu-latest if: ${{ !contains(github.event.pull_request.labels.*.name, 'Skip Contrib Tests') }} - + strategy: + matrix: + group: + - receiver-0 + - receiver-1 + - receiver-2 + - receiver-3 + - processor + - exporter-0 + - exporter-1 + - extension + - connector + - internal + - pkg + - cmd-0 + - cmd-1 + - other steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 + cache: false - name: Run Contrib Tests run: | contrib_path=/tmp/opentelemetry-collector-contrib - git clone https://github.com/open-telemetry/opentelemetry-collector-contrib.git $contrib_path - make CONTRIB_PATH=$contrib_path SKIP_RESTORE_CONTRIB=true check-contrib + git clone --depth=1 https://github.com/open-telemetry/opentelemetry-collector-contrib.git $contrib_path + make CONTRIB_PATH=$contrib_path SKIP_RESTORE_CONTRIB=true GROUP=${{ matrix.group }} check-contrib + + contrib_tests: + runs-on: ubuntu-latest + if: ${{ !contains(github.event.pull_request.labels.*.name, 'Skip Contrib Tests') }} + needs: [ contrib-tests-matrix ] + steps: + - name: Print result + run: echo ${{ needs.contrib-tests-matrix.result }} + - name: Interpret result + run: | + if [[ success == ${{ needs.contrib-tests-matrix.result }} ]] + then + echo "All matrix jobs passed!" + else + echo "One or more matrix jobs failed." + false + fi diff --git a/.github/workflows/create-dependabot-pr.yml b/.github/workflows/create-dependabot-pr.yml deleted file mode 100644 index de5d84bda45..00000000000 --- a/.github/workflows/create-dependabot-pr.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Automation - Dependabot PR - -on: - workflow_dispatch: - -jobs: - create-pr: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Setup Go - uses: actions/setup-go@v4 - with: - go-version: ~1.20.8 - - name: Run dependabot-pr.sh - run: ./.github/workflows/scripts/dependabot-pr.sh - env: - GITHUB_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }} diff --git a/.github/workflows/generate-semantic-conventions-pr.yaml b/.github/workflows/generate-semantic-conventions-pr.yaml new file mode 100644 index 00000000000..ad3275a2123 --- /dev/null +++ b/.github/workflows/generate-semantic-conventions-pr.yaml @@ -0,0 +1,109 @@ +name: Generate Semantic Conventions PR + +on: + schedule: + # Daily at 01:30 (UTC) + - cron: '30 1 * * *' + workflow_dispatch: + +jobs: + check-versions: + runs-on: ubuntu-latest + outputs: + latest-version: ${{ steps.check-versions.outputs.latest-version }} + already-added: ${{ steps.check-versions.outputs.already-added }} + already-opened: ${{ steps.check-versions.outputs.already-opened }} + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - id: check-versions + name: Check versions + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # version in this repo are prefixed with v + latest_version=v$(gh release view \ + --repo open-telemetry/semantic-conventions \ + --json tagName \ + --jq .tagName \ + | sed 's/^v//') + + rc=$(find semconv -name $latest_version | grep .) + if $rc == 0; then + already_added=true + fi + + matches=$(gh pr list \ + --author opentelemetrybot \ + --state open \ + --search "in:title \"Add semantic conventions version $latest_version\"") + if [ ! -z "$matches" ] + then + already_opened=true + fi + + echo "latest-version=$latest_version" >> $GITHUB_OUTPUT + echo "already-added=$already_added" >> $GITHUB_OUTPUT + echo "already-opened=$already_opened" >> $GITHUB_OUTPUT + + update-semantic-conventions: + permissions: + contents: write # for Git to git push + runs-on: ubuntu-latest + if: | + needs.check-versions.outputs.already-added != 'true' && + needs.check-versions.outputs.already-opened != 'true' + needs: + - check-versions + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Checkout semantic-convention + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + repository: open-telemetry/semantic-convention + path: tmp-semantic-conventions + + - name: Update version + env: + VERSION: ${{ needs.check-versions.outputs.latest-version }} + run: | + make gensemconv SPECPATH=./tmp-semantic-conventions SPECTAG=$VERSION + git diff + + - name: Use CLA approved github bot + run: | + git config user.name opentelemetrybot + git config user.email 107717825+opentelemetrybot@users.noreply.github.com + + - name: Create pull request against main + env: + VERSION: ${{ needs.check-versions.outputs.latest-version }} + # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows + GH_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }} + run: | + message="Add semantic conventions version $VERSION" + body="Add semantic conventions version \`$VERSION\`." + branch="opentelemetrybot/add-semantic-conventions-${VERSION}" + + git checkout -b $branch + git add semconv/ + git commit -m "$message" + git push --set-upstream origin $branch + url=$(gh pr create --title "$message" \ + --body "$body" \ + --base main) + + pull_request_number=${url//*\//} + + # see the template for change log entry file at blob/main/.chloggen/TEMPLATE.yaml + cat > .chloggen/semconv-$VERSION.yaml << EOF + change_type: enhancement + component: semconv + note: Add semantic conventions version $VERSION + issues: [ $pull_request_number ] + EOF + + git add .chloggen/semconv-$VERSION.yaml + + git commit -m "Add change log entry" + git push diff --git a/.github/workflows/milestone-add-to-pr.yml b/.github/workflows/milestone-add-to-pr.yml index bebe064b5f3..7181d8a2999 100644 --- a/.github/workflows/milestone-add-to-pr.yml +++ b/.github/workflows/milestone-add-to-pr.yml @@ -12,7 +12,7 @@ jobs: if: github.event.pull_request.merged runs-on: ubuntu-latest steps: - - uses: actions/github-script@v6 + - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | const milestones = await github.rest.issues.listMilestones({ diff --git a/.github/workflows/perf.yml b/.github/workflows/perf.yml index 01d6ce59b8b..cc103bafcea 100644 --- a/.github/workflows/perf.yml +++ b/.github/workflows/perf.yml @@ -4,16 +4,19 @@ on: push: branches: [main] +permissions: + contents: read + jobs: runperf: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 - name: Run benchmark run: make gobenchmark diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 6ba1b94351b..6ff746ec06a 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -19,11 +19,42 @@ on: required: true description: Current version (beta, like 0.69.1). Don't include `v`. jobs: + #validate-version format + validate-versions: + runs-on: ubuntu-latest + + steps: + - name: Validate version format + run: | + validate_beta_version() { + local regex_pattern_beta='^[0-9]+\.[0-9]+\.[0-9]+$' + if [[ ! "$1" =~ $regex_pattern_beta ]]; then + echo "Invalid $2 version format. For beta, it can be 0.1.0 or higher" + exit 1 + fi + } + + validate_stable_version() { + local regex_pattern_stable='^[1-9][0-9]*\.[0-9]+\.[0-9]+$' + if [[ ! "$1" =~ $regex_pattern_stable ]]; then + echo "Invalid stable version format for $2. Major version must be greater than 1." + exit 1 + fi + } + + validate_beta_version "${{ inputs.candidate-beta }}" "candidate-beta" + validate_beta_version "${{ inputs.current-beta }}" "current-beta" + validate_stable_version "${{ inputs.candidate-stable }}" "candidate-stable" + validate_stable_version "${{ inputs.current-stable }}" "current-stable" + shell: bash + # Releasing opentelemetry-collector prepare-release: + needs: + - validate-versions runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: fetch-depth: 0 # Make sure that there are no open issues with release:blocker label in Core. The release has to be delayed until they are resolved. @@ -51,9 +82,9 @@ jobs: REPO: open-telemetry/opentelemetry-collector-contrib run: ./.github/workflows/scripts/release-check-build-status.sh - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 # 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 new file mode 100644 index 00000000000..2b8b2e72658 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,69 @@ +name: Scorecard supply-chain security + +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '39 1 * * 3' + push: + branches: [ "main" ] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + # Uncomment the permissions below if installing in a private repository. + # contents: read + # actions: read + + steps: + - name: "Checkout code" + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecard on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@8a470fddafa5cbb6266ee11b37ef4d8aae19c571 # v3.24.6 + with: + sarif_file: results.sarif diff --git a/.github/workflows/scripts/dependabot-pr.sh b/.github/workflows/scripts/dependabot-pr.sh deleted file mode 100755 index 198b7e81b0f..00000000000 --- a/.github/workflows/scripts/dependabot-pr.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -ex -# -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -git config user.name opentelemetrybot -git config user.email 107717825+opentelemetrybot@users.noreply.github.com - -PR_NAME=dependabot-prs/$(date +'%Y-%m-%dT%H%M%S') -git checkout -b "$PR_NAME" - -IFS=$'\n' -requests=$( gh pr list --search "author:app/dependabot" --json title --jq '.[].title' | sort ) -message="" -dirs=$(find . -type f -name "go.mod" -exec dirname {} \; | sort ) - -for line in $requests; do - if [[ $line != Bump* ]]; then - continue - fi - - module=$(echo "$line" | cut -f 2 -d " ") - if [[ $module == go.opentelemetry.io/collector* ]]; then - continue - fi - version=$(echo "$line" | cut -f 6 -d " ") - - topdir=$(pwd) - for dir in $dirs; do - echo "checking $dir" - cd "$dir" && if grep -q "$module " go.mod; then go get "$module"@v"$version"; fi - cd "$topdir" - done - message+=$line - message+=$'\n' -done - -make gotidy -make genotelcorecol - -git add --all -git commit -m "dependabot updates $(date) -$message" -git push origin "$PR_NAME" - -gh pr create --title "[chore] dependabot updates $(date)" --body "$message" diff --git a/.github/workflows/scripts/release-prepare-release.sh b/.github/workflows/scripts/release-prepare-release.sh index d7c09ba63af..e26ff155a6d 100755 --- a/.github/workflows/scripts/release-prepare-release.sh +++ b/.github/workflows/scripts/release-prepare-release.sh @@ -26,14 +26,14 @@ git add --all git commit -m "Changelog update ${RELEASE_VERSION}" if [ "${CANDIDATE_STABLE}" != "" ]; then - make prepare-release GH=none PREVIOUS_VERSION="${CURRENT_STABLE}" RELEASE_CANDIDATE="${CANDIDATE_STABLE}" MODSET=stable + make prepare-release PREVIOUS_VERSION="${CURRENT_STABLE}" RELEASE_CANDIDATE="${CANDIDATE_STABLE}" MODSET=stable COMMANDS+=" -- make prepare-release GH=none PREVIOUS_VERSION=${CURRENT_STABLE} RELEASE_CANDIDATE=${CANDIDATE_STABLE} MODSET=stable" +- make prepare-release PREVIOUS_VERSION=${CURRENT_STABLE} RELEASE_CANDIDATE=${CANDIDATE_STABLE} MODSET=stable" fi if [ "${CANDIDATE_BETA}" != "" ]; then - make prepare-release GH=none PREVIOUS_VERSION="${CURRENT_BETA}" RELEASE_CANDIDATE="${CANDIDATE_BETA}" MODSET=beta + make prepare-release PREVIOUS_VERSION="${CURRENT_BETA}" RELEASE_CANDIDATE="${CANDIDATE_BETA}" MODSET=beta COMMANDS+=" -- make prepare-release GH=none PREVIOUS_VERSION=${CURRENT_BETA} RELEASE_CANDIDATE=${CANDIDATE_BETA} MODSET=beta" +- make prepare-release PREVIOUS_VERSION=${CURRENT_BETA} RELEASE_CANDIDATE=${CANDIDATE_BETA} MODSET=beta" fi git push origin "${BRANCH}" diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index 723bbbf77f7..92446e0fbda 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -5,11 +5,14 @@ on: pull_request: branches: [ main ] +permissions: + contents: read + jobs: shellcheck: name: Shellcheck runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Run ShellCheck - uses: ludeeus/action-shellcheck@2.0.0 + uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0 diff --git a/.github/workflows/stale-pr.yaml b/.github/workflows/stale-pr.yaml index 355edc64da4..312fb051980 100644 --- a/.github/workflows/stale-pr.yaml +++ b/.github/workflows/stale-pr.yaml @@ -3,11 +3,17 @@ on: schedule: - cron: "12 3 * * *" # arbitrary time not to DDOS GitHub +permissions: + contents: read + jobs: stale: + permissions: + issues: write # for actions/stale to close stale issues + pull-requests: write # for actions/stale to close stale PRs runs-on: ubuntu-latest steps: - - uses: actions/stale@v8 + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-pr-message: 'This PR was marked stale due to lack of activity. It will be closed in 14 days.' diff --git a/.github/workflows/tidy-dependencies.yml b/.github/workflows/tidy-dependencies.yml index d0901a16372..28752e3a56d 100644 --- a/.github/workflows/tidy-dependencies.yml +++ b/.github/workflows/tidy-dependencies.yml @@ -5,24 +5,27 @@ on: branches: - main +permissions: + contents: read + jobs: setup-environment: + permissions: + contents: write # for Git to git push timeout-minutes: 30 runs-on: ubuntu-latest - if: ${{ contains(github.event.pull_request.labels.*.name, 'dependencies') }} + if: ${{ !contains(github.event.pull_request.labels.*.name, 'dependency-major-update') && (github.actor == 'renovate[bot]' || contains(github.event.pull_request.labels.*.name, 'renovatebot')) }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: - repository: "renovate-bot/open-telemetry-_-opentelemetry-collector" ref: ${{ github.head_ref }} - token: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }} - - uses: actions/setup-go@v4 + - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.20.8 + go-version: ~1.21.5 cache: false - name: Cache Go id: go-cache - uses: actions/cache@v3 + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: | ~/go/bin @@ -41,5 +44,6 @@ jobs: git config user.email 107717825+opentelemetrybot@users.noreply.github.com echo "git diff --exit-code || (git add . && git commit -m \"go mod tidy\" && git push)" git diff --exit-code || (git add . && git commit -m "go mod tidy" && git push) - env: - GITHUB_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }} + - uses: actions-ecosystem/action-remove-labels@2ce5d41b4b6aa8503e285553f75ed56e0a40bae0 # v1.3.0 + with: + labels: renovatebot diff --git a/.golangci.yml b/.golangci.yml index 65589afbc2f..90d7a1b51c2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -17,6 +17,7 @@ run: # default value is empty list, but default dirs are skipped independently # from this option's value (see skip-dirs-use-default). skip-dirs: + - third_party # default is true. Enables skipping of directories: # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ @@ -69,8 +70,11 @@ linters-settings: - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf enable-all: true - # TODO: Enable this and fix the alignment issues. disable: + # We want to order fields according to readability and grouping them by use cases. + # This linter does not offer a discernible performance improvement as the structs + # defined in this repository are not in the execution hot path. + # See https://github.com/open-telemetry/opentelemetry-collector/issues/2789 - fieldalignment revive: diff --git a/CHANGELOG-API.md b/CHANGELOG-API.md index e62cd022ed4..6ebdddf897f 100644 --- a/CHANGELOG-API.md +++ b/CHANGELOG-API.md @@ -7,6 +7,223 @@ If you are looking for user-facing changes, check out [CHANGELOG.md](./CHANGELOG +## v1.3.0/v0.96.0 + +### 🚩 Deprecations 🚩 + +- `configgrpc`: Deprecates `ToServer`. Use `ToServerContext` instead. (#9624) +- `component`: deprecate component.ErrNilNextConsumer (#9526) +- `configtls`: Rename TLSClientSetting, TLSServerSetting, and TLSSetting based on the naming convention used in other config packages. (#9474) + +### 💡 Enhancements 💡 + +- `receivertest`: add support for metrics in contract checker (#9551) + +## v1.2.0/v0.95.0 + +### 🛑 Breaking changes 🛑 + +- `all`: Bump minimum go version to go 1.21 (#9507) +- `service/telemetry`: Delete generated_config types, use go.opentelemetry.io/contrib/config types instead (#9546) +- `configcompression`: Remove deprecated `configcompression` types, constants and methods. (#9388) +- `component`: Remove `host.ReportFatalError` (#6344) +- `configgrpc`: Remove deprecated `configgrpc.ServerConfig.ToListener` (#9481) +- `confmap`: Remove deprecated `confmap.WithErrorUnused` (#9484) + +### 🚩 Deprecations 🚩 + +- `confignet`: Deprecate `confignet.NetAddr` and `confignet.TCPAddr` in favor of `confignet.AddrConfig` and `confignet.TCPAddrConfig`. (#9509) +- `config/configgrpc`: Deprecate `configgrpc.ClientConfig.SanitizedEndpoint`, `configgrpc.ServerConfig.ToListener` and `configgrpc.ServerConfig.ToListenerContext` (#9481, #9482) +- `scraperhelper`: Deprecate ScraperControllerSettings, use ControllerConfig instead (#6767) + +## v1.1.0/v0.94.0 + +### 🛑 Breaking changes 🛑 + +- `confignet`: Remove deprecated `DialContext` and `ListenContext` functions (#9363) +- `confmap/converter/expandconverter`: Add `confmap.ConverterSettings` argument to experimental `expandconverter.New` function. (#5615, #9162) + - The `confmap.ConverterSettings` struct currently has no fields. It will be used to pass a logger. + +- `component`: Remove deprecated funcs and types (#9283) +- `otlpexporter`: Config struct is moving from embedding the deprecated GRPCClientSettings struct to using ClientConfig instead. (#6767) +- `otlphttpexporter`: otlphttpexporter.Config embeds the struct confighttp.ClientConfig instead of confighttp.HTTPClientSettings (#6767) +- `otlpreceiver`: HTTPConfig struct is moving from embedding the deprecated ServerSettings struct to using HTTPServerConfig instead. (#6767) +- `component`: Validate component.Type at creation and unmarshaling time. (#9208) + - A component.Type must start with an ASCII alphabetic character and can only contain ASCII alphanumeric characters and '_'. + + +### 🚩 Deprecations 🚩 + +- `configcompressions`: Deprecate `IsCompressed`. Use `CompressionType.IsCompressed instead` instead. (#9435) +- `configcompression`: Deprecate `CompressionType`, use `Type` instead. (#9416) +- `confighttp`: Deprecate CORSSettings, use CORSConfig instead (#6767) +- `configgrpc`: Deprecate `ToListener` function in favor of `ToListenerContext` (#9389) +- `configgrpc`: Deprecate GRPCServerSettings, use ServerConfig instead (#6767) +- `confighttp`: Deprecate HTTPClientSettings, use ClientConfig instead (#6767) +- `confighttp`: Deprecate HTTPServerSettings, use ServerConfig instead (#6767) +- `confmap/provider`: Deprecate .New in favor of .NewWithSettings for all core providers (#5615, #9162) + - NewWithSettings now takes an empty confmap.ProviderSettings struct. This will be used to pass a logger in the future. + + +### 💡 Enhancements 💡 + +- `exporter/exporterhelper`: Add API for enabling queue in the new exporter helpers. (#7874) + The following experimental API is introduced in exporter package: + - `exporterhelper.WithRequestQueue`: a new exporter helper option for using a queue. + - `exporterqueue.Queue`: an interface for queue implementations. + - `exporterqueue.Factory`: a queue factory interface, implementations of this interface are intended to be used with WithRequestQueue option. + - `exporterqueue.Settings`: queue factory settings. + - `exporterqueue.Config`: common configuration for queue implementations. + - `exporterqueue.NewDefaultConfig`: a function for creating a default queue configuration. + - `exporterqueue.NewMemoryQueueFactory`: a new factory for creating a memory queue. + - `exporterqueue.NewPersistentQueueFactory: a factory for creating a persistent queue. + +- `featuregate`: Add the `featuregate.ErrAlreadyRegistered` error, which is returned by `featuregate.Registry`'s `Register` when adding a feature gate that is already registered. (#8622) + Use `errors.Is` to check for this error. + + +## v0.93.0 + +### 🛑 Breaking changes 🛑 + +- `bug_fix`: Implement `encoding.BinaryMarshaler` interface to prevent `configopaque` -> `[]byte` -> `string` conversions from leaking the value (#9279) +- `configopaque`: configopaque.String implements `fmt.Stringer` and `fmt.GoStringer`, outputting [REDACTED] when formatted with the %s, %q or %#v verbs` (#9213) + This may break applications that rely on the previous behavior of opaque strings with `fmt.Sprintf` to e.g. build URLs or headers. + Explicitly cast the opaque string to a string before using it in `fmt.Sprintf` to restore the previous behavior. + +- `all`: Remove obsolete "// +build" directives (#9304) +- `connectortest`: Remove deprecated connectortest router helpers. (#9278) + +### 🚩 Deprecations 🚩 + +- `obsreporttest`: deprecate test funcs/structs (#8492) + The following methods/structs have been moved from obsreporttest to componenttest: + - obsreporttest.TestTelemetry -> componenttest.TestTelemetry + - obsreporttest.SetupTelemetry -> componenttest.SetupTelemetry + - obsreporttest.CheckScraperMetrics -> TestTelemetry.CheckScraperMetrics + - obserporttest.TestTelemetry.TelemetrySettings -> componenttest.TestTelemetry.TelemetrySettings() + +- `confignet`: Deprecates `DialContext` and `ListenContext` functions. Use `Dial` and `Listen` instead. (#9258) + Unlike the previous `Dial` and `Listen` functions, the new `Dial` and `Listen` functions take a `context.Context` like `DialContext` and `ListenContext`. + +## v1.0.1/v0.92.0 + +### 🛑 Breaking changes 🛑 + +- `otlpexporter`: Change Config members names to use Config suffix. (#9091) +- `component`: Remove deprecated unused TelemetrySettingsBase (#9145) + +### 🚩 Deprecations 🚩 + +- `confignet`: Deprecates the `Dial` and `Listen` functions in favor of `DialContext` and `ListenContext`. (#9163) +- `component`: Deprecate unnecessary type StatusFunc (#9146) + +## v0.91.0 + +## v1.0.0/v0.90.0 + +### 🛑 Breaking changes 🛑 + +- `exporterhelper`: Replace converter interface with function in the new experimental exporter helper. (#8122) +- `featuregate`: Remove deprecate function `featuregate.NewFlag` (#8727) + Use `featuregate.Registry`'s `RegisterFlags` method instead. + +### 🚩 Deprecations 🚩 + +- `telemetry`: deprecate jsonschema generated types (#15009) + +### 💡 Enhancements 💡 + +- `pdata`: Add ZeroThreshold field to exponentialHistogramDataPoint in pmetric package. (#8802) + +## v1.0.0-rcv0018/v0.89.0 + +### 🛑 Breaking changes 🛑 + +- `otelcol`: CollectorSettings.Factories now expects: `func() (Factories, error)` (#8478) +- `exporter/exporterhelper`: The experimental Request API is updated. (#7874) + - `Request` interface now includes ItemsCount() method. + - `RequestItemsCounter` is removed. + - The following interfaces are added: + - Added an optional interface for handling errors that occur during request processing `RequestErrorHandler`. + - Added a function to unmarshal bytes into a Request `RequestUnmarshaler`. + - Added a function to marshal a Request into bytes `RequestMarshaler` + + +### 🚩 Deprecations 🚩 + +- `featuregate`: Deprecate `featuregate.NewFlag` in favor of `featuregate.Registry`'s `RegisterFlags` method (#8727) + +### 💡 Enhancements 💡 + +- `featuregate`: Add validation for feature gates ID, URL and versions. (#8766) + Feature gates IDs are now explicitly restricted to ASCII alphanumerics and dots. + + +## v1.0.0-rcv0017/v0.88.0 + +### 💡 Enhancements 💡 + +- `pdata`: Add IsReadOnly() method to p[metrics|logs|traces].[Metrics|Logs|Spans] pdata structs allowing to check if the struct is read-only. (#6794) + +## v1.0.0-rcv0016/v0.87.0 + +### 💡 Enhancements 💡 + +- `pdata`: Introduce API to control pdata mutability (#6794) + This change introduces new API pdata methods to control the mutability: + - p[metric|trace|log].[Metrics|Traces|Logs].MarkReadOnly() - marks the pdata as read-only. Any subsequent + mutations will result in a panic. + - p[metric|trace|log].[Metrics|Traces|Logs].IsReadOnly() - returns true if the pdata is marked as read-only. + Currently, all the data is kept mutable. This API will be used by fanout consumer in the following releases. + +### 🛑 Breaking changes 🛑 + +- `obsreport`: remove methods/structs deprecated in previous release. (#8492) +- `extension`: remove deprecated Configs and Factories (#8631) + +## v1.0.0-rcv0015/v0.86.0 + +### 🛑 Breaking changes 🛑 + +- `service`: remove deprecated service.PipelineConfig (#8485) + +### 🚩 Deprecations 🚩 + +- `obsreporttest`: deprecate To*CreateSettings funcs in obsreporttest (#8492) + The following TestTelemetry methods have been deprecated. Use structs instead: + - ToExporterCreateSettings -> exporter.CreateSettings + - ToProcessorCreateSettings -> processor.CreateSettings + - ToReceiverCreateSettings -> receiver.CreateSettings + +- `obsreport`: Deprecating `obsreport.Exporter`, `obsreport.ExporterSettings`, `obsreport.NewExporter` (#8492) + These deprecated methods/structs have been moved to exporterhelper: + - `obsreport.Exporter` -> `exporterhelper.ObsReport` + - `obsreport.ExporterSettings` -> `exporterhelper.ObsReportSettings` + - `obsreport.NewExporter` -> `exporterhelper.NewObsReport` + +- `obsreport`: Deprecating `obsreport.BuildProcessorCustomMetricName`, `obsreport.Processor`, `obsreport.ProcessorSettings`, `obsreport.NewProcessor` (#8492) + These deprecated methods/structs have been moved to processorhelper: + - `obsreport.BuildProcessorCustomMetricName` -> `processorhelper.BuildCustomMetricName` + - `obsreport.Processor` -> `processorhelper.ObsReport` + - `obsreport.ProcessorSettings` -> `processorhelper.ObsReportSettings` + - `obsreport.NewProcessor` -> `processorhelper.NewObsReport` + +- `obsreport`: Deprecating obsreport scraper and receiver API (#8492) + These deprecated methods/structs have been moved to receiverhelper and scraperhelper: + - `obsreport.Receiver` -> `receiverhelper.ObsReport` + - `obsreport.ReceiverSettings` -> `receiverhelper.ObsReportSettings` + - `obsreport.NewReceiver` -> `receiverhelper.NewObsReport` + - `obsreport.Scraper` -> `scraperhelper.ObsReport` + - `obsreport.ScraperSettings` -> `scraperhelper.ObsReportSettings` + - `obsreport.NewScraper` -> `scraperhelper.NewObsReport` + + +### 💡 Enhancements 💡 + +- `otelcol`: Splitting otelcol into its own module. (#7924) +- `service`: Split service into its own module (#7923) + ## v0.85.0 ## v0.84.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index e14ace59693..f1238d56c8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,269 @@ If you are looking for developer-facing changes, check out [CHANGELOG-API.md](./ +## v1.3.0/v0.96.0 + +### 🛑 Breaking changes 🛑 + +- `configgrpc`: Remove deprecated `GRPCClientSettings`, `GRPCServerSettings`, and `ServerConfig.ToListenerContext`. (#9616) +- `confighttp`: Remove deprecated `HTTPClientSettings`, `NewDefaultHTTPClientSettings`, and `CORSSettings`. (#9625) +- `confignet`: Removes deprecated `NetAddr` and `TCPAddr` (#9614) + +### 💡 Enhancements 💡 + +- `configtls`: Add `include_system_ca_certs_pool` to configtls, allowing to load system certs and additional custom certs. (#7774) +- `otelcol`: Add `ConfigProviderSettings` to `CollectorSettings` (#4759) + This allows passing a custom list of `confmap.Provider`s to `otelcol.NewCommand`. +- `pdata`: Update to OTLP v1.1.0 (#9587) + Introduces Span and SpanLink flags. +- `confmap`: Update mapstructure to use a maintained fork, github.com/go-viper/mapstructure/v2. (#9634) + See https://github.com/mitchellh/mapstructure/issues/349 for context. + + +### 🧰 Bug fixes 🧰 + +- `configretry`: Allow max_elapsed_time to be set to 0 for indefinite retries (#9641) +- `client`: Make `Metadata.Get` thread safe (#9595) + +## v1.2.0/v0.95.0 + +### 🛑 Breaking changes 🛑 + +- `all`: scope name for all generated Meter/Tracer funcs now includes full package name (#9494) + +### 💡 Enhancements 💡 + +- `confighttp`: Adds support for Snappy decompression of HTTP requests. (#7632) +- `configretry`: Validate `max_elapsed_time`, ensure it is larger than `max_interval` and `initial_interval` respectively. (#9489) +- `configopaque`: Mark module as stable (#9167) +- `otlphttpexporter`: Add support for json content encoding when exporting telemetry (#6945) +- `confmap/converter/expandconverter, confmap/provider/envprovider, confmap/provider/fileprovider, confmap/provider/httprovider, confmap/provider/httpsprovider, confmap/provider/yamlprovider`: Split confmap.Converter and confmap.Provider implementation packages out of confmap. (#4759, #9460) + +## v1.1.0/v0.94.0 + +### 🛑 Breaking changes 🛑 + +- `receiver/otlp`: Update gRPC code from `codes.InvalidArgument` to `codes.Internal` when a permanent error doesn't contain a gRPC status (#9415) + +### 🚩 Deprecations 🚩 + +- `configgrpc`: Deprecate GRPCClientSettings, use ClientConfig instead (#6767) + +### 💡 Enhancements 💡 + +- `mdatagen`: Add a generated test that checks the config struct using `componenttest.CheckConfigStruct` (#9438) +- `component`: Add `component.UseLocalHostAsDefaultHost` feature gate that changes default endpoints from 0.0.0.0 to localhost (#8510) + The only component in this repository affected by this is the OTLP receiver. + +- `confighttp`: Add support of Host header (#9395) +- `mdatagen`: Remove use of ReportFatalError in generated tests (#9439) + +### 🧰 Bug fixes 🧰 + +- `service`: fix opencensus bridge configuration in periodic readers (#9361) +- `otlpreceiver`: Fix goroutine leak when GRPC server is started but HTTP server is unsuccessful (#9165) +- `otlpexporter`: PartialSuccess is treated as success, logged as warning. (#9243) + +## v0.93.0 + +### 🛑 Breaking changes 🛑 + +- `exporterhelper`: remove deprecated exporterhelper.RetrySettings and exporterhelper.NewDefaultRetrySettings (#9256) +- `configopaque`: configopaque.String implements `fmt.Stringer` and `fmt.GoStringer`, outputting [REDACTED] when formatted with the %s, %q or %#v verbs` (#9213) + This may break applications that rely on the previous behavior of opaque strings with `fmt.Sprintf` to e.g. build URLs or headers. + Explicitly cast the opaque string to a string before using it in `fmt.Sprintf` to restore the previous behavior. + + +### 🚀 New components 🚀 + +- `extension/memory_limiter`: Introduce a `memory_limiter` extension which receivers can use to reject incoming requests when collector doesn't have enough memory (#8632) + The extension has the same configuration interface and behavior as the existing `memory_limiter` processor, which potentially can be deprecated and removed in the future + +### 💡 Enhancements 💡 + +- `configtls`: add `cipher_suites` to configtls. (#8105) + Users can specify a list of cipher suites to pick from. If left blank, a safe default list is used. + +- `service`: mark `telemetry.useOtelForInternalMetrics` as stable (#816) +- `exporters`: Cleanup log messages for export failures (#9219) + 1. Ensure an error message is logged every time and only once when data is dropped/rejected due to export failure. + 2. Update the wording. Specifically, don't use "dropped" term when an error is reported back to the pipeline. + Keep the "dropped" wording for failures happened after the enabled queue. + 3. Properly report any error reported by a queue. For example, a persistent storage error must be reported as a storage error, not as "queue overflow". + + +### 🧰 Bug fixes 🧰 + +- `configgrpc`: Update dependency to address a potential crash in the grpc instrumentation (#9296) +- `otlpreceiver`: Ensure OTLP receiver handles consume errors correctly (#4335) + Make sure OTLP receiver returns correct status code and follows the receiver contract (gRPC) +- `zpagesextension`: Remove mention of rpcz page from zpages extension (#9328) + +## v1.0.1/v0.92.0 + +### 🛑 Breaking changes 🛑 + +- `exporters/sending_queue`: Do not re-enqueue failed batches, rely on the retry_on_failure strategy instead. (#8382) + The current re-enqueuing behavior is not obvious and cannot be configured. It takes place only for persistent queue + and only if `retry_on_failure::enabled=true` even if `retry_on_failure` is a setting for a different backoff retry + strategy. This change removes the re-enqueuing behavior. Consider increasing `retry_on_failure::max_elapsed_time` + to reduce chances of data loss or set it to 0 to keep retrying until requests succeed. + +- `confmap`: Make the option `WithErrorUnused` enabled by default when unmarshaling configuration (#7102) + The option `WithErrorUnused` is now enabled by default, and a new option `WithIgnoreUnused` is introduced to ignore + errors about unused fields. + +- `status`: Deprecate `ReportComponentStatus` in favor of `ReportStatus`. This new function does not return an error. (#9148) + +### 🚩 Deprecations 🚩 + +- `connectortest`: Deprecate connectortest.New[Metrics|Logs|Traces]Router in favour of connector.New[Metrics|Logs|Traces]Router (#9095) +- `exporterhelper`: Deprecate exporterhelper.RetrySettings in favor of configretry.BackOffConfig (#9091) +- `extension/ballast`: Deprecate `memory_ballast` extension. (#8343) + Use `GOMEMLIMIT` environment variable instead. + +- `connector`: Deprecate [Metrics|Logs|Traces]Router in favour of [Metrics|Logs|Traces]RouterAndConsumer (#9095) + +### 💡 Enhancements 💡 + +- `exporterhelper`: Add RetrySettings validation function (#9089) + Validate that time.Duration, multiplier values in configretry are non-negative, and randomization_factor is between 0 and 1 + +- `service`: Enable `telemetry.useOtelForInternalMetrics` by updating the flag to beta (#7454) + The metrics generated should be consistent with the metrics generated + previously with OpenCensus. Users can disable the behaviour + by setting `--feature-gates -telemetry.useOtelForInternalMetrics` at + collector start. + +- `mdatagen`: move component from contrib to core (#9172) +- `semconv`: Generated Semantic conventions 1.22.0. (#8686) +- `confignet`: Add `dialer_timeout` config option. (#9066) +- `processor/memory_limiter`: Update config validation errors (#9059) + - Fix names of the config fields that are validated in the error messages + - Move the validation from start to the initialization phrase + +- `exporterhelper`: Add config Validate for TimeoutSettings (#9104) + +### 🧰 Bug fixes 🧰 + +- `memorylimiterprocessor`: Fixed leaking goroutines from memorylimiterprocessor (#9099) +- `cmd/otelcorecol`: Fix the code detecting if the collector is running as a service on Windows. (#7350) + Removed the `NO_WINDOWS_SERVICE` environment variable given it is not needed anymore. +- `otlpexporter`: remove dependency of otlphttpreceiver on otlpexporter (#6454) + +## v0.91.0 + +### 💡 Enhancements 💡 + +- `statusreporting`: Automates status reporting upon the completion of component.Start(). (#7682) +- `service`: add resource attributes as labels to otel metrics to ensures backwards compatibility with OpenCensus metrics. (#9029) +- `semconv`: Generated Semantic conventions 1.21. (#9056) +- `config/confighttp`: Exposes http/2 transport settings to enable health check and workaround golang http/2 issue https://github.com/golang/go/issues/59690 (#9022) +- `cmd/builder`: running builder version on binaries installed with `go install` will output the version specified at the suffix. (#8770) + +### 🧰 Bug fixes 🧰 + +- `exporterhelper`: fix missed metric aggregations (#9048) + This ensures that context cancellation in the exporter doesn't interfere with metric aggregation. The OTel + SDK currently returns if there's an error in the context used in `Add`. This means that if there's a + cancelled context in an export, the metrics are now recorded. + +- `service`: Fix bug where MutatesData would not correctly propagate through connectors. (#9053) + +## v0.90.1 + +### 🧰 Bug fixes 🧰 + +- `exporterhelper`: Remove noisy log (#9017) + +## v1.0.0/v0.90.0 + +### 🛑 Breaking changes 🛑 + +- `service`: To remain backwards compatible w/ the metrics generated today, otel generated metrics will be generated without the `_total` suffix (#7454) +- `service`: use WithNamespace instead of WrapRegistererWithPrefix (#8988) + Using this functionality in the otel prom exporter fixes a bug where the + target_info was prefixed as otelcol_target_info previously. + + +### 💡 Enhancements 💡 + +- `exporter/debug`: Change default `verbosity` from `normal` to `basic` (#8844) + This change has currently no effect, as `basic` and `normal` verbosity share the same behavior. This might change in the future though, with the `normal` verbosity being more verbose than it currently is (see https://github.com/open-telemetry/opentelemetry-collector/issues/7806). This is why we are changing the default to `basic`, which is expected to stay at the current level of verbosity (one line per batch). +- `exporterhelper`: Fix shutdown logic in persistent queue to not require consumers to be closed first (#8899) +- `confighttp`: Support proxy configuration field in all exporters that support confighttp (#5761) + +### 🧰 Bug fixes 🧰 + +- `exporterhelper`: Fix invalid write index updates in the persistent queue (#8115) + +## v1.0.0-rcv0018/v0.89.0 + +### 💡 Enhancements 💡 + +- `builder`: remove replace statement in builder template (#8763) +- `service/extensions`: Allow extensions to declare dependencies on other extensions and guarantee start/stop/notification order accordingly. (#8732) +- `exporterhelper`: Log export errors when retry is not used by the component. (#8791) +- `cmd/builder`: Add --verbose flag to log `go` subcommands output that are ran as part of a build (#8715) +- `exporterhelper`: Remove internal goroutine loop for persistent queue (#8868) +- `exporterhelper`: Simplify usage of storage client, avoid unnecessary allocations (#8830) +- `exporterhelper`: Simplify logic in boundedMemoryQueue, use channels len/cap (#8829) + +### 🧰 Bug fixes 🧰 + +- `exporterhelper`: fix bug with queue size and capacity metrics (#8682) +- `obsreporttest`: split handler for otel vs oc test path in TestTelemetry (#8758) +- `builder`: Fix featuregate late initialization (#4967) +- `service`: Fix connector logger zap kind key (#8878) + +## v1.0.0-rcv0017/v0.88.0 + +### 💡 Enhancements 💡 + +- `fanoutconsumer`: Enable runtime assertions to catch incorrect pdata mutations in the components claiming as non-mutating pdata. (#6794) + This change enables the runtime assertions to catch unintentional pdata mutations in components that are claimed + as non-mutating pdata. Without these assertions, runtime errors may still occur, but thrown by unrelated components, + making it very difficult to troubleshoot. + + +### 🧰 Bug fixes 🧰 + +- `exporterhelper`: make enqueue failures available for otel metrics (#8673) +- `exporterhelper`: Fix nil pointer dereference when stopping persistent queue after a start encountered an error (#8718) +- `cmd/builder`: Fix ocb ignoring `otelcol_version` when set to v0.86.0 or later (#8692) + +## v1.0.0-rcv0016/v0.87.0 + +### 💡 Enhancements 💡 + +- `service/telemetry exporter/exporterhelper`: Enable sampling logging by default and apply it to all components. (#8134) + The sampled logger configuration can be disabled easily by setting the `service::telemetry::logs::sampling::enabled` to `false`. +- `core`: Adds the ability for components to report status and for extensions to subscribe to status events by implementing an optional StatusWatcher interface. (#7682) + +### 🧰 Bug fixes 🧰 + +- `telemetry`: remove workaround to ignore errors when an instrument includes a `/` (#8346) + +## v1.0.0-rcv0015/v0.86.0 + +### 🚩 Deprecations 🚩 + +- `loggingexporter`: Mark the logging exporter as deprecated, in favour of debug exporter (#7769) + +### 🚀 New components 🚀 + +- `debugexporter`: Add debug exporter, which replaces the logging exporter (#7769) + +### 💡 Enhancements 💡 + +- `featuregate`: List valid feature gates when failing to load invalid gate (#8505) +- `supported platforms`: Add `linux/s390x` architecture to cross build tests in CI (#8213) + +### 🧰 Bug fixes 🧰 + +- `builder`: fix setting `dist.*` keys from env (#8239) +- `configtls`: fix incorrect use of fsnotify (#8438) + ## v0.85.0 ### 💡 Enhancements 💡 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b8c2865fbd8..1f99bb80c8c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -95,15 +95,14 @@ for general practices for OpenTelemetry project. Select a good issue from the links below (ordered by difficulty/complexity): * [Good First Issue](https://github.com/open-telemetry/opentelemetry-collector/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) -* [Up for Grabs](https://github.com/open-telemetry/opentelemetry-collector/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Aup-for-grabs+) * [Help Wanted](https://github.com/open-telemetry/opentelemetry-collector/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) Comment on the issue that you want to work on so we can assign it to you and clarify anything related to it. If you would like to work on something that is not listed as an issue -(e.g. a new feature or enhancement) please first read our [vision](docs/vision.md) and -[roadmap](docs/roadmap.md) to make sure your proposal aligns with the goals of the +(e.g. a new feature or enhancement) please first read our [vision](docs/vision.md) +to make sure your proposal aligns with the goals of the Collector, then create an issue and describe your proposal. It is best to do this in advance so that maintainers can decide if the proposal is a good fit for this repository. This will help avoid situations when you spend significant time @@ -148,7 +147,7 @@ section of general project contributing guide. Working with the project sources requires the following tools: 1. [git](https://git-scm.com/) -2. [go](https://golang.org/) (version 1.18 and up) +2. [go](https://golang.org/) (version 1.20 and up) 3. [make](https://www.gnu.org/software/make/) 4. [docker](https://www.docker.com/) @@ -205,7 +204,7 @@ before merging (but see above paragraph about writing good commit messages in th ## General Notes -This project uses Go 1.18.* and [Github Actions.](https://github.com/features/actions) +This project uses Go 1.20.* and [Github Actions.](https://github.com/features/actions) It is recommended to run `make gofmt all` before submitting your PR @@ -214,8 +213,7 @@ The dependencies are managed with `go mod` if you work with the sources under yo ## Coding Guidelines -Although OpenTelemetry project as a whole is still in Alpha stage we consider -OpenTelemetry Collector to be close to production quality and the quality bar +We consider the OpenTelemetry Collector to be close to production quality and the quality bar for contributions is set accordingly. Contributions must have readable code written with maintainability in mind (if in doubt check [Effective Go](https://golang.org/doc/effective_go.html) for coding advice). The code must adhere to the following robustness principles that @@ -253,6 +251,20 @@ To keep naming patterns consistent across the project, naming patterns are enfor - `func CreateTracesExport(...) {...}` - `func CreateTracesToTracesFunc(...) {...}` +### Enumerations + +To keep naming patterns consistent across the project, enumeration patterns are enforced to make intent clear: + +- Enumerations should be defined using a type definition, such as `type Level int32`. +- Enumerations should use either `int` or `string` as the underlying type +- Enumeration name should succinctly describe the enumeration's purpose + - If the package name represents the entity described by the enumeration then the package name should be factored into the name of the enumeration. For example, `component.Type` instead of `component.ComponentType`. + - The name should convey a sense of limited categorization. For example, `pcommon.ValueType` is better than `pcommon.Value` and `component.Kind` is better than `component.KindType`, since `Kind` already conveys categorization. +- Constant values of an enumeration should be prefixed with the enumeration type name in the name: + - `pcommon.ValueTypeStr` for `pcommon.ValueType` + - `pmetric.MetricTypeGauge` for `pmetric.MetricType` + + ### Recommended Libraries / Defaults In order to simplify developing within the project, library recommendations have been set @@ -266,6 +278,11 @@ and should be followed. Within the project, there are some packages that are yet to follow the recommendations and are being address, however, any new code should adhere to the recommendations. +### Default Configuration + +To guarantee backwards compatible behavior, all configuration packages should supply a `NewDefault[config name]` functions that create a default version of the config. The package does not need to guarantee that `NewDefault[config name]` returns a usable configuration, only that default values will be set. For example, if the configuration requires that a field, such as `Endpoint` be set, but there is no valid default value, then `NewDefault[config name]` may set that value to `""` with the expectation that the user will set a valid value. + +Users should always initialize the config struct with this function and overwrite anything as needed. ### Startup Error Handling @@ -364,8 +381,7 @@ The following limitations are recommended: ### Observability Out of the box, your users should be able to observe the state of your component. -The collector exposes an OpenMetrics endpoint at `http://localhost:8888/metrics` -where your data will land. +See [observability.md](docs/observability.md) for more details. When using the regular helpers, you should have some metrics added around key events automatically. For instance, exporters should have `otelcol_exporter_sent_spans` @@ -650,6 +666,19 @@ target would result in unacceptable latency in the local development loop. The default repo-level target (i.e. running `make` at the root of the repo) should meaningfully validate the entire repo. This should include running the default common target for each module as well as additional repo-level targets. +## How to update the OTLP protocol version + +When a new OTLP version is published, the following steps are required to update this code base: + +1. Edit the top-level Makefile's `OPENTELEMETRY_PROTO_VERSION` variable +2. Run `make genproto` +3. Inspect modifications to the generated code in `pdata/internal/data/protogen` +4. When new fields are added in the protocol, make corresponding changes in `pdata/internal/cmd/pdatagen/internal` +5. Run `make genpdata` +6. Inspect modifications to the generated code in `pdata/*` +7. Run `make genproto-cleanup`, to remove temporary files +8. Update the supported OTLP version in [README.md](./README.md). + ## Exceptions While the rules in this and other documents in this repository is what we strive to follow, we acknowledge that rules may be diff --git a/Makefile b/Makefile index de19ea41afc..c2cbc2c0bdb 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ include ./Makefile.Common # This is the code that we want to run lint, etc. ALL_SRC := $(shell find . -name '*.go' \ -not -path './internal/tools/*' \ + -not -path '*/third_party/*' \ -not -path './pdata/internal/data/protogen/*' \ -not -path './service/internal/zpages/tmplgen/*' \ -type f | sort) @@ -12,7 +13,7 @@ ALL_DOC := $(shell find . \( -name "*.md" -o -name "*.yaml" \) \ -type f | sort) # ALL_MODULES includes ./* dirs (excludes . dir) -ALL_MODULES := $(shell find . -type f -name "go.mod" -exec dirname {} \; | sort | egrep '^./' ) +ALL_MODULES := $(shell find . -type f -name "go.mod" -exec dirname {} \; | sort | grep -E '^./' ) CMD?= @@ -57,7 +58,7 @@ gotest-with-cover: .PHONY: goporto goporto: $(PORTO) - $(PORTO) -w --include-internal ./ + $(PORTO) -w --include-internal --skip-dirs "^cmd/mdatagen/third_party$$" ./ .PHONY: golint golint: @@ -77,7 +78,9 @@ gotidy: .PHONY: gogenerate gogenerate: + cd cmd/mdatagen && $(GOCMD) install . @$(MAKE) for-all-target TARGET="generate" + $(MAKE) fmt .PHONY: addlicense addlicense: $(ADDLICENSE) @@ -148,37 +151,13 @@ ocb: $(MAKE) -C cmd/builder config $(MAKE) -C cmd/builder ocb -DEPENDABOT_PATH=".github/dependabot.yml" -.PHONY: internal-gendependabot -internal-gendependabot: - @echo "Add rule for \"${PACKAGE}\" in \"${DIR}\""; - @echo " - package-ecosystem: \"${PACKAGE}\"" >> ${DEPENDABOT_PATH}; - @echo " directory: \"${DIR}\"" >> ${DEPENDABOT_PATH}; - @echo " schedule:" >> ${DEPENDABOT_PATH}; - @echo " interval: \"weekly\"" >> ${DEPENDABOT_PATH}; - @echo " day: \"wednesday\"" >> ${DEPENDABOT_PATH}; - -# This target should run on /bin/bash since the syntax DIR=$${dir:1} is not supported by /bin/sh. -.PHONY: gendependabot -gendependabot: $(eval SHELL:=/bin/bash) - @echo "Recreating ${DEPENDABOT_PATH} file" - @echo "# File generated by \"make gendependabot\"; DO NOT EDIT." > ${DEPENDABOT_PATH} - @echo "" >> ${DEPENDABOT_PATH} - @echo "version: 2" >> ${DEPENDABOT_PATH} - @echo "updates:" >> ${DEPENDABOT_PATH} - $(MAKE) internal-gendependabot DIR="/" PACKAGE="github-actions" - $(MAKE) internal-gendependabot DIR="/" PACKAGE="gomod" - @set -e; for dir in $(ALL_MODULES); do \ - $(MAKE) internal-gendependabot DIR=$${dir:1} PACKAGE="gomod"; \ - done - # Definitions for ProtoBuf generation. # The source directory for OTLP ProtoBufs. OPENTELEMETRY_PROTO_SRC_DIR=pdata/internal/opentelemetry-proto -# The SHA matching the current version of the proto to use -OPENTELEMETRY_PROTO_VERSION=v1.0.0 +# The branch matching the current version of the proto to use +OPENTELEMETRY_PROTO_VERSION=v1.1.0 # Find all .proto files. OPENTELEMETRY_PROTO_FILES := $(subst $(OPENTELEMETRY_PROTO_SRC_DIR)/,,$(wildcard $(OPENTELEMETRY_PROTO_SRC_DIR)/opentelemetry/proto/*/v1/*.proto $(OPENTELEMETRY_PROTO_SRC_DIR)/opentelemetry/proto/collector/*/v1/*.proto)) @@ -192,7 +171,7 @@ PROTO_PACKAGE=go.opentelemetry.io/collector/$(PROTO_TARGET_GEN_DIR) # Intermediate directory used during generation. PROTO_INTERMEDIATE_DIR=pdata/internal/.patched-otlp-proto -DOCKER_PROTOBUF ?= otel/build-protobuf:0.9.0 +DOCKER_PROTOBUF ?= otel/build-protobuf:0.23.0 PROTOC := docker run --rm -u ${shell id -u} -v${PWD}:${PWD} -w${PWD}/$(PROTO_INTERMEDIATE_DIR) ${DOCKER_PROTOBUF} --proto_path=${PWD} PROTO_INCLUDES := -I/usr/include/github.com/gogo/protobuf -I./ @@ -250,82 +229,66 @@ genpdata: $(GOCMD) run pdata/internal/cmd/pdatagen/main.go $(MAKE) fmt -# The source directory for configuration schema. -OPENTELEMETRY_JSONSCHEMA_SRC_DIR=service/internal/proctelemetry/opentelememetry-configuration - -# The SHA matching the current version of the configuration schema to use -OPENTELEMETRY_JSONSCHEMA_VERSION=main - -# Cleanup temporary directory -genjsonschema-cleanup: - rm -Rf ${OPENTELEMETRY_JSONSCHEMA_SRC_DIR} - -# Generate structs for configuration from configuration schema -genjsonschema: genjsonschema-cleanup $(GOJSONSCHEMA) - mkdir -p ${OPENTELEMETRY_JSONSCHEMA_SRC_DIR} - curl -sSL https://api.github.com/repos/open-telemetry/opentelemetry-configuration/tarball/${OPENTELEMETRY_JSONSCHEMA_VERSION} | tar xz --strip 1 -C ${OPENTELEMETRY_JSONSCHEMA_SRC_DIR} - $(GOJSONSCHEMA) \ - --package telemetry \ - --tags mapstructure \ - --output ./service/telemetry/generated_config.go \ - --schema-package=https://opentelemetry.io/otelconfig/opentelemetry_configuration.json=github.com/open-telemetry/opentelemetry-collector/schema \ - ${OPENTELEMETRY_JSONSCHEMA_SRC_DIR}/schema/opentelemetry_configuration.json - @echo Modify jsonschema generated files. - sed -f $(TOOLS_MOD_DIR)/jsonschema_patch.sed service/telemetry/generated_config.go > service/telemetry/generated_config_tmp.go - mv service/telemetry/generated_config_tmp.go service/telemetry/generated_config.go - $(MAKE) fmt - $(MAKE) genjsonschema-cleanup - # Generate semantic convention constants. Requires a clone of the opentelemetry-specification repo -gensemconv: +gensemconv: $(SEMCONVGEN) $(SEMCONVKIT) @[ "${SPECPATH}" ] || ( echo ">> env var SPECPATH is not set"; exit 1 ) @[ "${SPECTAG}" ] || ( echo ">> env var SPECTAG is not set"; exit 1 ) @echo "Generating semantic convention constants from specification version ${SPECTAG} at ${SPECPATH}" - semconvgen -o semconv/${SPECTAG} -t semconv/template.j2 -s ${SPECTAG} -i ${SPECPATH}/semantic_conventions/. --only=resource -p conventionType=resource -f generated_resource.go - semconvgen -o semconv/${SPECTAG} -t semconv/template.j2 -s ${SPECTAG} -i ${SPECPATH}/semantic_conventions/. --only=event -p conventionType=event -f generated_event.go - semconvgen -o semconv/${SPECTAG} -t semconv/template.j2 -s ${SPECTAG} -i ${SPECPATH}/semantic_conventions/. --only=span -p conventionType=trace -f generated_trace.go + $(SEMCONVGEN) -o semconv/${SPECTAG} -t semconv/template.j2 -s ${SPECTAG} -i ${SPECPATH}/model/. --only=resource -p conventionType=resource -f generated_resource.go + $(SEMCONVGEN) -o semconv/${SPECTAG} -t semconv/template.j2 -s ${SPECTAG} -i ${SPECPATH}/model/. --only=event -p conventionType=event -f generated_event.go + $(SEMCONVGEN) -o semconv/${SPECTAG} -t semconv/template.j2 -s ${SPECTAG} -i ${SPECPATH}/model/. --only=span -p conventionType=trace -f generated_trace.go + $(SEMCONVKIT) -output "semconv/$(SPECTAG)" -tag "$(SPECTAG)" # Checks that the HEAD of the contrib repo checked out in CONTRIB_PATH compiles # against the current version of this repo. .PHONY: check-contrib check-contrib: @echo Setting contrib at $(CONTRIB_PATH) to use this core checkout - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector=$(CURDIR)" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/component=$(CURDIR)/component" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/config/configauth=$(CURDIR)/config/configauth" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/config/configcompression=$(CURDIR)/config/configcompression" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/config/configgrpc=$(CURDIR)/config/configgrpc" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/config/confighttp=$(CURDIR)/config/confighttp" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/config/confignet=$(CURDIR)/config/confignet" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/config/configopaque=$(CURDIR)/config/configopaque" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/config/configtelemetry=$(CURDIR)/config/configtelemetry" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/config/configtls=$(CURDIR)/config/configtls" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/config/internal=$(CURDIR)/config/internal" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/confmap=$(CURDIR)/confmap" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/connector=$(CURDIR)/connector" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/connector/forwardconnector=$(CURDIR)/connector/forwardconnector" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/consumer=$(CURDIR)/consumer" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/exporter=$(CURDIR)/exporter" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/exporter/debugexporter=$(CURDIR)/exporter/debugexporter" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/exporter/loggingexporter=$(CURDIR)/exporter/loggingexporter" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/exporter/otlpexporter=$(CURDIR)/exporter/otlpexporter" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/exporter/otlphttpexporter=$(CURDIR)/exporter/otlphttpexporter" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/extension=$(CURDIR)/extension" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/extension/auth=$(CURDIR)/extension/auth" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/extension/ballastextension=$(CURDIR)/extension/ballastextension" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/extension/zpagesextension=$(CURDIR)/extension/zpagesextension" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/featuregate=$(CURDIR)/featuregate" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/otelcol=$(CURDIR)/otelcol" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/pdata=$(CURDIR)/pdata" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/processor=$(CURDIR)/processor" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/processor/batchprocessor=$(CURDIR)/processor/batchprocessor" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/processor/memorylimiterprocessor=$(CURDIR)/processor/memorylimiterprocessor" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/receiver=$(CURDIR)/receiver" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/receiver/otlpreceiver=$(CURDIR)/receiver/otlpreceiver" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/semconv=$(CURDIR)/semconv" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -replace go.opentelemetry.io/collector/service=$(CURDIR)/service" - @$(MAKE) -C $(CONTRIB_PATH) -j2 gotidy - @$(MAKE) -C $(CONTRIB_PATH) test + @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit \ + -replace go.opentelemetry.io/collector=$(CURDIR) \ + -replace go.opentelemetry.io/collector/component=$(CURDIR)/component \ + -replace go.opentelemetry.io/collector/config/configauth=$(CURDIR)/config/configauth \ + -replace go.opentelemetry.io/collector/config/configcompression=$(CURDIR)/config/configcompression \ + -replace go.opentelemetry.io/collector/config/configgrpc=$(CURDIR)/config/configgrpc \ + -replace go.opentelemetry.io/collector/config/confighttp=$(CURDIR)/config/confighttp \ + -replace go.opentelemetry.io/collector/config/confignet=$(CURDIR)/config/confignet \ + -replace go.opentelemetry.io/collector/config/configopaque=$(CURDIR)/config/configopaque \ + -replace go.opentelemetry.io/collector/config/configretry=$(CURDIR)/config/configretry \ + -replace go.opentelemetry.io/collector/config/configtelemetry=$(CURDIR)/config/configtelemetry \ + -replace go.opentelemetry.io/collector/config/configtls=$(CURDIR)/config/configtls \ + -replace go.opentelemetry.io/collector/config/internal=$(CURDIR)/config/internal \ + -replace go.opentelemetry.io/collector/confmap=$(CURDIR)/confmap \ + -replace go.opentelemetry.io/collector/confmap/converter/expandconverter=$(CURDIR)/confmap/converter/expandconverter \ + -replace go.opentelemetry.io/collector/confmap/provider/envprovider=$(CURDIR)/confmap/provider/envprovider \ + -replace go.opentelemetry.io/collector/confmap/provider/fileprovider=$(CURDIR)/confmap/provider/fileprovider \ + -replace go.opentelemetry.io/collector/confmap/provider/httpprovider=$(CURDIR)/confmap/provider/httpprovider \ + -replace go.opentelemetry.io/collector/confmap/provider/httpsprovider=$(CURDIR)/confmap/provider/httpsprovider \ + -replace go.opentelemetry.io/collector/confmap/provider/yamlprovider=$(CURDIR)/confmap/provider/yamlprovider \ + -replace go.opentelemetry.io/collector/connector=$(CURDIR)/connector \ + -replace go.opentelemetry.io/collector/connector/forwardconnector=$(CURDIR)/connector/forwardconnector \ + -replace go.opentelemetry.io/collector/consumer=$(CURDIR)/consumer \ + -replace go.opentelemetry.io/collector/exporter=$(CURDIR)/exporter \ + -replace go.opentelemetry.io/collector/exporter/debugexporter=$(CURDIR)/exporter/debugexporter \ + -replace go.opentelemetry.io/collector/exporter/loggingexporter=$(CURDIR)/exporter/loggingexporter \ + -replace go.opentelemetry.io/collector/exporter/otlpexporter=$(CURDIR)/exporter/otlpexporter \ + -replace go.opentelemetry.io/collector/exporter/otlphttpexporter=$(CURDIR)/exporter/otlphttpexporter \ + -replace go.opentelemetry.io/collector/extension=$(CURDIR)/extension \ + -replace go.opentelemetry.io/collector/extension/auth=$(CURDIR)/extension/auth \ + -replace go.opentelemetry.io/collector/extension/ballastextension=$(CURDIR)/extension/ballastextension \ + -replace go.opentelemetry.io/collector/extension/memorylimiterextension=$(CURDIR)/extension/memorylimiterextension \ + -replace go.opentelemetry.io/collector/extension/zpagesextension=$(CURDIR)/extension/zpagesextension \ + -replace go.opentelemetry.io/collector/featuregate=$(CURDIR)/featuregate \ + -replace go.opentelemetry.io/collector/otelcol=$(CURDIR)/otelcol \ + -replace go.opentelemetry.io/collector/pdata=$(CURDIR)/pdata \ + -replace go.opentelemetry.io/collector/processor=$(CURDIR)/processor \ + -replace go.opentelemetry.io/collector/processor/batchprocessor=$(CURDIR)/processor/batchprocessor \ + -replace go.opentelemetry.io/collector/processor/memorylimiterprocessor=$(CURDIR)/processor/memorylimiterprocessor \ + -replace go.opentelemetry.io/collector/receiver=$(CURDIR)/receiver \ + -replace go.opentelemetry.io/collector/receiver/otlpreceiver=$(CURDIR)/receiver/otlpreceiver \ + -replace go.opentelemetry.io/collector/semconv=$(CURDIR)/semconv \ + -replace go.opentelemetry.io/collector/service=$(CURDIR)/service" + @$(MAKE) -C $(CONTRIB_PATH) gotidy + @$(MAKE) -C $(CONTRIB_PATH) gotest @if [ -z "$(SKIP_RESTORE_CONTRIB)" ]; then \ $(MAKE) restore-contrib; \ fi @@ -334,39 +297,49 @@ check-contrib: .PHONY: restore-contrib restore-contrib: @echo Restoring contrib at $(CONTRIB_PATH) to its original state - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/component" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/config/configcompression" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/config/configgrpc" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/config/confighttp" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/config/confignet" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/config/configopaque" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/config/configtelemetry" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/config/configtls" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/config/internal" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/confmap" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/connector" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/connector/forwardconnector" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/consumer" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/exporter" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/exporter/debugexporter" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/exporter/loggingexporter" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/exporter/otlpexporter" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/exporter/otlphttpexporter" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/extension" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/extension/auth" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/extension/ballastextension" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/extension/zpagestextension" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/featuregate" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/otelcol" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/pdata" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/processor" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/processor/batchprocessor" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/processor/memorylimiterprocessor" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/receiver" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/receiver/otlpreceiver" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/semconv" - @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit -dropreplace go.opentelemetry.io/collector/service" + @$(MAKE) -C $(CONTRIB_PATH) for-all CMD="$(GOCMD) mod edit \ + -dropreplace go.opentelemetry.io/collector \ + -dropreplace go.opentelemetry.io/collector/component \ + -dropreplace go.opentelemetry.io/collector/config/configauth \ + -dropreplace go.opentelemetry.io/collector/config/configcompression \ + -dropreplace go.opentelemetry.io/collector/config/configgrpc \ + -dropreplace go.opentelemetry.io/collector/config/confighttp \ + -dropreplace go.opentelemetry.io/collector/config/confignet \ + -dropreplace go.opentelemetry.io/collector/config/configopaque \ + -dropreplace go.opentelemetry.io/collector/config/configretry \ + -dropreplace go.opentelemetry.io/collector/config/configtelemetry \ + -dropreplace go.opentelemetry.io/collector/config/configtls \ + -dropreplace go.opentelemetry.io/collector/config/internal \ + -dropreplace go.opentelemetry.io/collector/confmap \ + -dropreplace go.opentelemetry.io/collector/confmap/converter/expandconverter \ + -dropreplace go.opentelemetry.io/collector/confmap/provider/envprovider \ + -dropreplace go.opentelemetry.io/collector/confmap/provider/fileprovider \ + -dropreplace go.opentelemetry.io/collector/confmap/provider/httpprovider \ + -dropreplace go.opentelemetry.io/collector/confmap/provider/httpsprovider \ + -dropreplace go.opentelemetry.io/collector/confmap/provider/yamlprovider \ + -dropreplace go.opentelemetry.io/collector/connector \ + -dropreplace go.opentelemetry.io/collector/connector/forwardconnector \ + -dropreplace go.opentelemetry.io/collector/consumer \ + -dropreplace go.opentelemetry.io/collector/exporter \ + -dropreplace go.opentelemetry.io/collector/exporter/debugexporter \ + -dropreplace go.opentelemetry.io/collector/exporter/loggingexporter \ + -dropreplace go.opentelemetry.io/collector/exporter/otlpexporter \ + -dropreplace go.opentelemetry.io/collector/exporter/otlphttpexporter \ + -dropreplace go.opentelemetry.io/collector/extension \ + -dropreplace go.opentelemetry.io/collector/extension/auth \ + -dropreplace go.opentelemetry.io/collector/extension/ballastextension \ + -dropreplace go.opentelemetry.io/collector/extension/memorylimiterextension \ + -dropreplace go.opentelemetry.io/collector/extension/zpagesextension \ + -dropreplace go.opentelemetry.io/collector/featuregate \ + -dropreplace go.opentelemetry.io/collector/otelcol \ + -dropreplace go.opentelemetry.io/collector/pdata \ + -dropreplace go.opentelemetry.io/collector/processor \ + -dropreplace go.opentelemetry.io/collector/processor/batchprocessor \ + -dropreplace go.opentelemetry.io/collector/processor/memorylimiterprocessor \ + -dropreplace go.opentelemetry.io/collector/receiver \ + -dropreplace go.opentelemetry.io/collector/receiver/otlpreceiver \ + -dropreplace go.opentelemetry.io/collector/semconv \ + -dropreplace go.opentelemetry.io/collector/service" @$(MAKE) -C $(CONTRIB_PATH) -j2 gotidy # List of directories where certificates are stored for unit tests. @@ -432,44 +405,8 @@ push-tags: $(MULTIMOD) done; .PHONY: check-changes -check-changes: $(YQ) -ifndef MODSET - @echo "MODSET not defined" - @echo "usage: make check-changes PREVIOUS_VERSION= MODSET=beta" - exit 1 -endif -ifndef PREVIOUS_VERSION - @echo "PREVIOUS_VERSION not defined" - @echo "usage: make check-changes PREVIOUS_VERSION= MODSET=beta" - exit 1 -else -ifeq (, $(findstring v,$(PREVIOUS_VERSION))) -NORMALIZED_PREVIOUS_VERSION="v$(PREVIOUS_VERSION)" -else -NORMALIZED_PREVIOUS_VERSION="$(PREVIOUS_VERSION)" -endif -endif - @all_submods=$$($(YQ) e '.module-sets.*.modules[] | select(. != "go.opentelemetry.io/collector")' versions.yaml | sed 's/^go\.opentelemetry\.io\/collector\///'); \ - mods=$$($(YQ) e '.module-sets.$(MODSET).modules[]' versions.yaml | sed 's/^go\.opentelemetry\.io\/collector\///'); \ - changed_files=""; \ - for mod in $${mods}; do \ - if [ "$${mod}" == "go.opentelemetry.io/collector" ]; then \ - changed_files+=$$(git diff --name-only $(NORMALIZED_PREVIOUS_VERSION) -- $$(printf '%s\n' $${all_submods[@]} | sed 's/^/:!/' | paste -sd' ' -) | grep -E '.+\.go$$'); \ - elif ! git rev-parse --quiet --verify $${mod}/$(NORMALIZED_PREVIOUS_VERSION) >/dev/null; then \ - echo "Module $${mod} does not have a $(NORMALIZED_PREVIOUS_VERSION) tag"; \ - echo "$(MODSET) release is required."; \ - exit 0; \ - else \ - changed_files+=$$(git diff --name-only $${mod}/$(NORMALIZED_PREVIOUS_VERSION) -- $${mod} | grep -E '.+\.go$$'); \ - fi; \ - done; \ - if [ -n "$${changed_files}" ]; then \ - echo "The following files changed in $(MODSET) modules since $(NORMALIZED_PREVIOUS_VERSION): $${changed_files}"; \ - else \ - echo "No $(MODSET) modules have changed since $(NORMALIZED_PREVIOUS_VERSION)"; \ - echo "No need to release $(MODSET)."; \ - exit 1; \ - fi +check-changes: $(MULTIMOD) + $(MULTIMOD) diff -p $(PREVIOUS_VERSION) -m $(MODSET) .PHONY: prepare-release prepare-release: @@ -494,8 +431,6 @@ else endif # ensure a clean branch git diff -s --exit-code || (echo "local repository not clean"; exit 1) - # check if any modules have changed since the previous release - $(MAKE) check-changes # update files with new version sed -i.bak 's/$(PREVIOUS_VERSION)/$(RELEASE_CANDIDATE)/g' versions.yaml sed -i.bak 's/$(PREVIOUS_VERSION)/$(RELEASE_CANDIDATE)/g' ./cmd/builder/internal/builder/config.go @@ -550,3 +485,9 @@ chlog-update: $(CHLOGGEN) .PHONY: builder-integration-test builder-integration-test: $(ENVSUBST) cd ./cmd/builder && ./test/test.sh + +.PHONY: mdatagen-test +mdatagen-test: + cd cmd/mdatagen && $(GOCMD) install . + cd cmd/mdatagen && $(GOCMD) generate ./... + cd cmd/mdatagen && $(GOCMD) test ./... diff --git a/Makefile.Common b/Makefile.Common index 6b51e353ec1..195701daf59 100644 --- a/Makefile.Common +++ b/Makefile.Common @@ -1,3 +1,4 @@ +SHELL = /bin/bash # ALL_PKGS is the list of all packages where ALL_SRC files reside. ALL_PKGS := $(sort $(shell go list ./...)) # COVER_PKGS is the list of packages to include in the coverage @@ -9,8 +10,11 @@ GOTEST=$(GOCMD) test GOOS := $(shell $(GOCMD) env GOOS) GOARCH := $(shell $(GOCMD) env GOARCH) -TOOLS_MOD_DIR := $(PWD)/internal/tools -TOOLS_BIN_DIR := $(PWD)/.tools +# SRC_ROOT is the top of the source tree. +SRC_ROOT := $(shell git rev-parse --show-toplevel) + +TOOLS_MOD_DIR := $(SRC_ROOT)/internal/tools +TOOLS_BIN_DIR := $(SRC_ROOT)/.tools TOOLS_MOD_REGEX := "\s+_\s+\".*\"" TOOLS_PKG_NAMES := $(shell grep -E $(TOOLS_MOD_REGEX) < $(TOOLS_MOD_DIR)/tools.go | tr -d " _\"" | grep -vE '/v[0-9]+$$') TOOLS_BIN_NAMES := $(addprefix $(TOOLS_BIN_DIR)/, $(notdir $(shell echo $(TOOLS_PKG_NAMES)))) @@ -23,19 +27,17 @@ CHLOGGEN := $(TOOLS_BIN_DIR)/chloggen CROSSLINK := $(TOOLS_BIN_DIR)/crosslink ENVSUBST := $(TOOLS_BIN_DIR)/envsubst GOIMPORTS := $(TOOLS_BIN_DIR)/goimports -GOJSONSCHEMA := $(TOOLS_BIN_DIR)/gojsonschema GOVULNCHECK := $(TOOLS_BIN_DIR)/govulncheck LINT := $(TOOLS_BIN_DIR)/golangci-lint IMPI := $(TOOLS_BIN_DIR)/impi MISSPELL := $(TOOLS_BIN_DIR)/misspell MULTIMOD := $(TOOLS_BIN_DIR)/multimod PORTO := $(TOOLS_BIN_DIR)/porto -YQ := $(TOOLS_BIN_DIR)/yq - -GH := $(shell which gh) +SEMCONVGEN := $(TOOLS_BIN_DIR)/semconvgen +SEMCONVKIT := $(TOOLS_BIN_DIR)/semconvkit .PHONY: install-tools -install-tools: $(TOOLS_BIN_NAMES) $(YQ) +install-tools: $(TOOLS_BIN_NAMES) $(TOOLS_BIN_DIR): mkdir -p $@ @@ -43,9 +45,6 @@ $(TOOLS_BIN_DIR): $(TOOLS_BIN_NAMES): $(TOOLS_BIN_DIR) $(TOOLS_MOD_DIR)/go.mod cd $(TOOLS_MOD_DIR) && $(GOCMD) build -o $@ -trimpath $(filter %/$(notdir $@),$(TOOLS_PKG_NAMES)) -$(YQ): $(TOOLS_BIN_DIR) $(TOOLS_MOD_DIR)/go.mod - cd $(TOOLS_MOD_DIR) && $(GOCMD) build -o $@ -trimpath github.com/mikefarah/yq/v4 - .PHONY: test test: $(GOTEST) $(GOTEST_OPT) ./... @@ -67,7 +66,7 @@ fmt: $(GOIMPORTS) .PHONY: tidy tidy: rm -fr go.sum - $(GOCMD) mod tidy -compat=1.20 + $(GOCMD) mod tidy -compat=1.21 .PHONY: lint lint: $(LINT) diff --git a/README.md b/README.md index d1ae701b0cd..9736c07a617 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ GitHub release (latest by date including pre-releases) + +

@@ -35,12 +37,8 @@   •   Monitoring   •   - Performance -   •   Security   •   - Roadmap -   •   Package

@@ -63,6 +61,13 @@ Objectives: - Extensible: Customizable without touching the core code. - Unified: Single codebase, deployable as an agent or collector with support for traces, metrics and logs. +## Supported OTLP version + +This code base is currently built against using OTLP protocol v1.1.0, +considered Stable. [See the OpenTelemetry Protocol Stability +definition +here.](https://github.com/open-telemetry/opentelemetry-proto?tab=readme-ov-file#stability-definition) + ## Stability levels The collector components and implementation are in different stages of stability, and usually split between @@ -100,7 +105,7 @@ A component identified as unmaintained does not have an active code owner. Such When used as a library, the OpenTelemetry Collector attempts to track the currently supported versions of Go, as [defined by the Go team](https://go.dev/doc/devel/release#policy). Removing support for an unsupported Go version is not considered a breaking change. -Starting with the release of Go 1.18, support for Go versions on the OpenTelemetry Collector will be updated as follows: +Support for Go versions on the OpenTelemetry Collector is updated as follows: 1. The first release after the release of a new Go minor version `N` will add build and tests steps for the new Go minor version. 2. The first release after the release of a new Go minor version `N` will remove support for Go version `N-2`. @@ -117,6 +122,9 @@ Here is a list of community roles with current and previous members: - [Andrzej Stencel](https://github.com/astencel-sumo), Sumo Logic - [Antoine Toulme](https://github.com/atoulme), Splunk + - [Evan Bradley](https://github.com/evan-bradley), Dynatrace + - [Tyler Helmuth](https://github.com/TylerHelmuth), Honeycomb + - [Yang Song](https://github.com/songy23), Datadog - Actively seeking contributors to triage issues - Emeritus Triagers: @@ -131,7 +139,6 @@ Here is a list of community roles with current and previous members: - [Anthony Mirabella](https://github.com/Aneurysm9), AWS - [Daniel Jaglowski](https://github.com/djaglowski), observIQ - [Juraci Paixão Kröhling](https://github.com/jpkrohling), Grafana Labs - - [Pablo Baeyens](https://github.com/mx-psi), DataDog - Emeritus Approvers: @@ -141,13 +148,13 @@ Here is a list of community roles with current and previous members: - [Owais Lone](https://github.com/owais), Splunk - [Rahul Patel](https://github.com/rghetia), Google - [Steven Karis](https://github.com/sjkaris), Splunk - - [Yang Song](https://github.com/songy23), Google - Maintainers ([@open-telemetry/collector-maintainers](https://github.com/orgs/open-telemetry/teams/collector-maintainers)): - - [Alex Boten](https://github.com/codeboten), Lightstep - - [Bogdan Drutu](https://github.com/BogdanDrutu), Splunk + - [Alex Boten](https://github.com/codeboten), Honeycomb + - [Bogdan Drutu](https://github.com/BogdanDrutu), Snowflake - [Dmitrii Anoshin](https://github.com/dmitryax), Splunk + - [Pablo Baeyens](https://github.com/mx-psi), DataDog - Emeritus Maintainers: diff --git a/VERSIONING.md b/VERSIONING.md index 08e1b9ca547..e0dcc6781b5 100644 --- a/VERSIONING.md +++ b/VERSIONING.md @@ -5,7 +5,55 @@ is designed so that the following goal can be achieved: **Users are provided a codebase of value that is stable and secure.** -## Policy +## Public API expectations + +The following public API expectations apply to all modules in opentelemetry-collector and opentelemetry-collector-contrib. +As a general rule, stability guarantees of modules versioned as `v1` or higher are aligned with [Go 1 compatibility promise](https://go.dev/doc/go1compat). + +### General Go API considerations + +OpenTelemetry authors reserve the right to introduce API changes breaking compatibility between minor versions in the following scenarios: +* **Struct literals.** It may be necessary to add new fields to exported structs in the API. Code that uses unkeyed + struct literals (such as pkg.T{3, "x"}) to create values of these types would fail to compile after such a change. + However, code that uses keyed literals (pkg.T{A: 3, B: "x"}) will continue to compile. We therefore recommend + using OpenTelemetry collector structs with the keyed literals only. +* **Methods.** As with struct fields, it may be necessary to add methods to types. Under some circumstances, + such as when the type is embedded in a struct along with another type, the addition of the new method may + break the struct by creating a conflict with an existing method of the other embedded type. We cannot protect + against this rare case and do not guarantee compatibility in such scenarios. +* **Dot imports.** If a program imports a package using `import .`, additional names defined in the imported package + in future releases may conflict with other names defined in the program. We do not recommend the use of + `import .` with OpenTelemetry Collector modules. + +Unless otherwise specified in the documentation, the following may change in any way between minor versions: +* **String representation**. The `String` method of any struct is intended to be human-readable and may change its output + in any way. +* **Go version compatibility**. Removing support for an unsupported Go version is not considered a breaking change. +* **OS version compatibility**. Removing support for an unsupported OS version is not considered a breaking change. Upgrading or downgrading OS version support per the [platform support](docs/platform-support.md) document is not considered a breaking change. +* **Dependency updates**. Updating dependencies is not considered a breaking change except when their types are part of the +public API or the update may change the behavior of applications in an incompatible way. + +### Configuration structures + +Configuration structures are part of the public API and backwards +compatibility should be maintained through any changes made to configuration structures. + +Unless otherwise specified in the documentation, the following may change in any way between minor versions: +* **Adding new fields to configuration structures**. Because configuration structures are typically instantiated through +unmarshalling a serialized representation of the structure, and not through structure literals, additive changes to +the set of exported fields in a configuration structure are not considered to break backward compatibility. +* **Relaxing validation rules**. An invalid configuration struct as defined by its `Validate` method return value +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. +* **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). + +## Versioning and module schema * Versioning of this project will be idiomatic of a Go project using [Go modules](https://golang.org/ref/mod#versions). @@ -32,7 +80,7 @@ is designed so that the following goal can be achieved: * A single module should exist, rooted at the top level of this repository, that contains all packages provided for use outside this repository. * Additional modules may be created in this repository to provide for - isolation of build-time tools or other commands. Such modules should be + isolation of build-time tools, other commands or independent libraries. Such modules should be versioned in sync with the `go.opentelemetry.io/collector` module. * Experimental modules still under active development will be versioned with a major version of `v0` to imply the stability guarantee defined by @@ -40,16 +88,6 @@ is designed so that the following goal can be achieved: > Major version zero (0.y.z) is for initial development. Anything MAY > change at any time. The public API SHOULD NOT be considered stable. - - * Configuration structures should be considered part of the public API and backward - compatibility maintained through any changes made to configuration structures. - * Because configuration structures are typically instantiated through unmarshalling - a serialized representation of the structure, and not through structure literals, - additive changes to the set of exported fields in a configuration structure are - not considered to break backward compatibility. - * Struct tags used to configure serialization mechanisms (`yaml:`, `mapstructure:`, etc) - are to be considered part of the structure definition and must maintain compatibility - to the same extent as the structure. * Versioning of the associated [contrib repository](https://github.com/open-telemetry/opentelemetry-collector-contrib) of this project will be idiomatic of a Go project using [Go @@ -72,14 +110,8 @@ is designed so that the following goal can be achieved: whenever you are using the module name). * If a module is version `v0` or `v1`, do not include the major version in either the module path or the import path. - * Configuration structures should be considered part of the public API and backward - compatibility maintained through any changes made to configuration structures. - * Because configuration structures are typically instantiated through unmarshalling - a serialized representation of the structure, and not through structure literals, - additive changes to the set of exported fields in a configuration structure are - not considered to break backward compatibility. - * Modules will be used to encapsulate receivers, processor, exporters, - extensions, and any other independent sets of related components. + * Modules will be used to encapsulate receivers, processors, exporters, + extensions, connectors and any other independent sets of related components. * Experimental modules still under active development will be versioned with a major version of `v0` to imply the stability guarantee defined by [semver](https://semver.org/spec/v2.0.0.html#spec-item-4). @@ -102,17 +134,3 @@ is designed so that the following goal can be achieved: * Contrib modules will be kept up to date with this project's releases. * GitHub releases will be made for all releases. * Go modules will be made available at Go package mirrors. -* Stability guaranties of modules versioned as `v1` or higher are aligned with [Go 1 compatibility - promise](https://go.dev/doc/go1compat). OpenTelemetry authors reserve the right to introduce API changes breaking - compatibility between minor versions in the following scenarios: - * **Struct literals.** It may be necessary to add new fields to exported structs in the API. Code that uses unkeyed - struct literals (such as pkg.T{3, "x"}) to create values of these types would fail to compile after such a change. - However, code that uses keyed literals (pkg.T{A: 3, B: "x"}) will continue to compile. We therefore recommend - using OpenTelemetry collector structs with the keyed literals only. - * **Methods.** As with struct fields, it may be necessary to add methods to types. Under some circumstances, - such as when the type is embedded in a struct along with another type, the addition of the new method may - break the struct by creating a conflict with an existing method of the other embedded type. We cannot protect - against this rare case and do not guarantee compatibility in such scenarios. - * **Dot imports.** If a program imports a package using `import .`, additional names defined in the imported package - in future releases may conflict with other names defined in the program. We do not recommend the use of - `import .` with OpenTelemetry Collector modules. diff --git a/client/client.go b/client/client.go index 1f385f6af81..b8775d5a440 100644 --- a/client/client.go +++ b/client/client.go @@ -141,28 +141,24 @@ func FromContext(ctx context.Context) Info { // NewMetadata creates a new Metadata object to use in Info. md is used as-is. func NewMetadata(md map[string][]string) Metadata { + c := make(map[string][]string, len(md)) + for k, v := range md { + c[strings.ToLower(k)] = v + } return Metadata{ - data: md, + data: c, } } // Get gets the value of the key from metadata, returning a copy. func (m Metadata) Get(key string) []string { - vals := m.data[key] + if len(m.data) == 0 { + return nil + } + + vals := m.data[strings.ToLower(key)] if len(vals) == 0 { - // we didn't find the key, but perhaps it just has different cases? - for k, v := range m.data { - if strings.EqualFold(key, k) { - vals = v - // we optimize for the next lookup - m.data[key] = v - } - } - - // if it's still not found, it's really not here - if len(vals) == 0 { - return nil - } + return nil } ret := make([]string, len(vals)) diff --git a/client/client_test.go b/client/client_test.go index f71b7da0728..ddec6bd89dd 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -77,10 +77,11 @@ func TestFromContext(t *testing.T) { } func TestMetadata(t *testing.T) { - source := map[string][]string{"test-key": {"test-val"}} + source := map[string][]string{"test-key": {"test-val"}, "TEST-KEY-2": {"test-val"}} md := NewMetadata(source) assert.Equal(t, []string{"test-val"}, md.Get("test-key")) - assert.Equal(t, []string{"test-val"}, md.Get("test-KEY")) // case insensitive lookup + assert.Equal(t, []string{"test-val"}, md.Get("test-KEY")) // case insensitive lookup + assert.Equal(t, []string{"test-val"}, md.Get("test-key-2")) // case insensitive lookup // test if copy. In regular use, source cannot change val := md.Get("test-key") @@ -89,3 +90,8 @@ func TestMetadata(t *testing.T) { assert.Empty(t, md.Get("non-existent-key")) } + +func TestUninstantiatedMetadata(t *testing.T) { + i := Info{} + assert.Empty(t, i.Metadata.Get("test")) +} diff --git a/client/package_test.go b/client/package_test.go new file mode 100644 index 00000000000..a5731000b98 --- /dev/null +++ b/client/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package client + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/cmd/builder/README.md b/cmd/builder/README.md index d89534565ad..7a4259d59e5 100644 --- a/cmd/builder/README.md +++ b/cmd/builder/README.md @@ -1,5 +1,4 @@ # OpenTelemetry Collector Builder (ocb) -[![CI](https://github.com/open-telemetry/opentelemetry-collector-builder/actions/workflows/go.yaml/badge.svg)](https://github.com/open-telemetry/opentelemetry-collector-builder/actions/workflows/go.yaml?query=branch%3Amain) This program generates a custom OpenTelemetry Collector binary based on a given configuration. @@ -51,8 +50,21 @@ $ /tmp/dist/otelcol-custom --config=/tmp/otelcol.yaml ## Installation -Download the binary for your respective platform under the ["Releases"](https://github.com/open-telemetry/opentelemetry-collector/releases/latest) page. -If install an official release build, the binary is named `ocb`, but if you installed by using `go install`, it will be called `builder`. +There are two supported ways to install the builder: via the official releases (recommended) and through `go install`. + +### Official releases + +This is the recommended installation method. Download the binary for your respective platform under the ["Releases"](https://github.com/open-telemetry/opentelemetry-collector/releases?q=builder) page. + +### `go install` + +You need to have a `go` compiler in your PATH. Run the following command to install the latest version: + +``` +go install go.opentelemetry.io/collector/cmd/builder@latest +``` + +If installing through this method the binary will be called `builder`. Binaries installed through this method [will incorrectly show `dev` as their version](https://github.com/open-telemetry/opentelemetry-collector/issues/8691). ## Running diff --git a/cmd/builder/go.mod b/cmd/builder/go.mod index fabff549794..0c607dd0aab 100644 --- a/cmd/builder/go.mod +++ b/cmd/builder/go.mod @@ -3,33 +3,35 @@ module go.opentelemetry.io/collector/cmd/builder -go 1.20 +go 1.21 require ( + github.com/hashicorp/go-version v1.6.0 github.com/knadh/koanf/parsers/yaml v0.1.0 github.com/knadh/koanf/providers/env v0.1.0 github.com/knadh/koanf/providers/file v0.1.0 github.com/knadh/koanf/providers/fs v0.1.0 - github.com/knadh/koanf/v2 v2.0.1 - github.com/spf13/cobra v1.7.0 + github.com/knadh/koanf/v2 v2.1.0 + github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.4 + go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 - go.uber.org/zap v1.26.0 + go.uber.org/zap v1.27.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect - golang.org/x/sys v0.12.0 // indirect + golang.org/x/sys v0.14.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/cmd/builder/go.sum b/cmd/builder/go.sum index d5cbd3af3aa..c2ebb096a71 100644 --- a/cmd/builder/go.sum +++ b/cmd/builder/go.sum @@ -1,9 +1,13 @@ -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= @@ -16,8 +20,8 @@ github.com/knadh/koanf/providers/file v0.1.0 h1:fs6U7nrV58d3CFAFh8VTde8TM262ObYf github.com/knadh/koanf/providers/file v0.1.0/go.mod h1:rjJ/nHQl64iYCtAW2QQnF0eSmDEX/YZ/eNFj5yR6BvA= github.com/knadh/koanf/providers/fs v0.1.0 h1:9Hln9GS3bWTItAnGVFYyfkoAIxAFq7pvlF64pTNiDdQ= github.com/knadh/koanf/providers/fs v0.1.0/go.mod h1:Cva1yH8NBxkEeVZx8CUmF5TunbgO72E+GwqDbqpP2sE= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -27,8 +31,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -38,20 +40,20 @@ github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/f github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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/internal/builder/config.go b/cmd/builder/internal/builder/config.go index 4128fc32344..bbdbaefc432 100644 --- a/cmd/builder/internal/builder/config.go +++ b/cmd/builder/internal/builder/config.go @@ -11,11 +11,12 @@ import ( "path/filepath" "strings" + "github.com/hashicorp/go-version" "go.uber.org/multierr" "go.uber.org/zap" ) -const defaultOtelColVersion = "0.85.0" +const defaultOtelColVersion = "0.96.0" // ErrInvalidGoMod indicates an invalid gomod var ErrInvalidGoMod = errors.New("invalid gomod specification for module") @@ -27,6 +28,7 @@ type Config struct { SkipCompilation bool `mapstructure:"-"` SkipGetModules bool `mapstructure:"-"` LDFlags string `mapstructure:"-"` + Verbose bool `mapstructure:"-"` Distribution Distribution `mapstructure:"dist"` Exporters []Module `mapstructure:"exporters"` @@ -40,15 +42,16 @@ type Config struct { // Distribution holds the parameters for the final binary type Distribution struct { - Module string `mapstructure:"module"` - Name string `mapstructure:"name"` - Go string `mapstructure:"go"` - Description string `mapstructure:"description"` - OtelColVersion string `mapstructure:"otelcol_version"` - OutputPath string `mapstructure:"output_path"` - Version string `mapstructure:"version"` - BuildTags string `mapstructure:"build_tags"` - DebugCompilation bool `mapstructure:"debug_compilation"` + Module string `mapstructure:"module"` + Name string `mapstructure:"name"` + Go string `mapstructure:"go"` + Description string `mapstructure:"description"` + OtelColVersion string `mapstructure:"otelcol_version"` + RequireOtelColModule bool `mapstructure:"-"` // required for backwards-compatibility with builds older than 0.86.0 + OutputPath string `mapstructure:"output_path"` + Version string `mapstructure:"version"` + BuildTags string `mapstructure:"build_tags"` + DebugCompilation bool `mapstructure:"debug_compilation"` } // Module represents a receiver, exporter, processor or extension for the distribution @@ -96,7 +99,7 @@ func (c *Config) Validate() error { func (c *Config) SetGoPath() error { if !c.SkipCompilation || !c.SkipGetModules { // #nosec G204 - if _, err := exec.Command(c.Distribution.Go, "env").CombinedOutput(); err != nil { + if _, err := exec.Command(c.Distribution.Go, "env").CombinedOutput(); err != nil { // nolint G204 path, err := exec.LookPath("go") if err != nil { return ErrGoNotFound @@ -108,6 +111,21 @@ func (c *Config) SetGoPath() error { return nil } +func (c *Config) SetRequireOtelColModule() error { + constraint, err := version.NewConstraint(">= 0.86.0") + if err != nil { + return err + } + + otelColVersion, err := version.NewVersion(c.Distribution.OtelColVersion) + if err != nil { + return err + } + + c.Distribution.RequireOtelColModule = constraint.Check(otelColVersion) + return nil +} + // ParseModules will parse the Modules entries and populate the missing values func (c *Config) ParseModules() error { var err error diff --git a/cmd/builder/internal/builder/config_test.go b/cmd/builder/internal/builder/config_test.go index 7c8766bdffe..dccee464fe4 100644 --- a/cmd/builder/internal/builder/config_test.go +++ b/cmd/builder/internal/builder/config_test.go @@ -192,3 +192,36 @@ func TestDebugOptionSetConfig(t *testing.T) { assert.NoError(t, cfg.Validate()) assert.True(t, cfg.Distribution.DebugCompilation) } + +func TestRequireOtelColModule(t *testing.T) { + tests := []struct { + Version string + ExpectedRequireOtelColModule bool + }{ + { + Version: "0.85.0", + ExpectedRequireOtelColModule: false, + }, + { + Version: "0.86.0", + ExpectedRequireOtelColModule: true, + }, + { + Version: "0.86.1", + ExpectedRequireOtelColModule: true, + }, + { + Version: "1.0.0", + ExpectedRequireOtelColModule: true, + }, + } + + for _, tt := range tests { + t.Run(tt.Version, func(t *testing.T) { + cfg := NewDefaultConfig() + cfg.Distribution.OtelColVersion = tt.Version + require.NoError(t, cfg.SetRequireOtelColModule()) + assert.Equal(t, tt.ExpectedRequireOtelColModule, cfg.Distribution.RequireOtelColModule) + }) + } +} diff --git a/cmd/builder/internal/builder/main.go b/cmd/builder/internal/builder/main.go index 0267b071c52..3b22300be2e 100644 --- a/cmd/builder/internal/builder/main.go +++ b/cmd/builder/internal/builder/main.go @@ -13,6 +13,7 @@ import ( "time" "go.uber.org/zap" + "go.uber.org/zap/zapio" ) var ( @@ -20,6 +21,27 @@ var ( ErrGoNotFound = errors.New("go binary not found") ) +func runGoCommand(cfg Config, args ...string) error { + cfg.Logger.Info("Running go subcommand.", zap.Any("arguments", args)) + // #nosec G204 -- cfg.Distribution.Go is trusted to be a safe path and the caller is assumed to have carried out necessary input validation + cmd := exec.Command(cfg.Distribution.Go, args...) + cmd.Dir = cfg.Distribution.OutputPath + + if cfg.Verbose { + writer := &zapio.Writer{Log: cfg.Logger} + defer func() { _ = writer.Close() }() + cmd.Stdout = writer + cmd.Stderr = writer + return cmd.Run() + } + + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("go subcommand failed with args '%v': %w. Output:\n%s", args, err, out) + } + + return nil +} + // GenerateAndCompile will generate the source files based on the given configuration, update go mod, and will compile into a binary func GenerateAndCompile(cfg Config) error { if err := Generate(cfg); err != nil { @@ -93,11 +115,8 @@ func Compile(cfg Config) error { if cfg.Distribution.BuildTags != "" { args = append(args, "-tags", cfg.Distribution.BuildTags) } - // #nosec G204 -- cfg.Distribution.Go is trusted to be a safe path and the caller is assumed to have carried out necessary input validation - cmd := exec.Command(cfg.Distribution.Go, args...) - cmd.Dir = cfg.Distribution.OutputPath - if out, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("failed to compile the OpenTelemetry Collector distribution: %w. Output:\n%s", err, out) + if err := runGoCommand(cfg, args...); err != nil { + return fmt.Errorf("failed to compile the OpenTelemetry Collector distribution: %w", err) } cfg.Logger.Info("Compiled", zap.String("binary", fmt.Sprintf("%s/%s", cfg.Distribution.OutputPath, cfg.Distribution.Name))) @@ -111,11 +130,13 @@ func GetModules(cfg Config) error { return nil } - // #nosec G204 -- cfg.Distribution.Go is trusted to be a safe path - cmd := exec.Command(cfg.Distribution.Go, "mod", "tidy", "-compat=1.20") - cmd.Dir = cfg.Distribution.OutputPath - if out, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("failed to update go.mod: %w. Output:\n%s", err, out) + // ambiguous import: found package cloud.google.com/go/compute/metadata in multiple modules + if err := runGoCommand(cfg, "get", "cloud.google.com/go"); err != nil { + return fmt.Errorf("failed to go get: %w", err) + } + + if err := runGoCommand(cfg, "mod", "tidy", "-compat=1.21"); err != nil { + return fmt.Errorf("failed to update go.mod: %w", err) } cfg.Logger.Info("Getting go modules") @@ -124,11 +145,8 @@ func GetModules(cfg Config) error { retries := 3 failReason := "unknown" for i := 1; i <= retries; i++ { - // #nosec G204 - cmd := exec.Command(cfg.Distribution.Go, "mod", "download") - cmd.Dir = cfg.Distribution.OutputPath - if out, err := cmd.CombinedOutput(); err != nil { - failReason = fmt.Sprintf("%s. Output:\n%s", err, out) + if err := runGoCommand(cfg, "mod", "download"); err != nil { + failReason = err.Error() cfg.Logger.Info("Failed modules download", zap.String("retry", fmt.Sprintf("%d/%d", i, retries))) time.Sleep(5 * time.Second) continue @@ -144,5 +162,6 @@ func processAndWrite(cfg Config, tmpl *template.Template, outFile string, tmplPa return err } + defer out.Close() return tmpl.Execute(out, tmplParams) } diff --git a/cmd/builder/internal/builder/main_test.go b/cmd/builder/internal/builder/main_test.go index e9f2fbbd303..6a237743b29 100644 --- a/cmd/builder/internal/builder/main_test.go +++ b/cmd/builder/internal/builder/main_test.go @@ -10,7 +10,6 @@ import ( "path/filepath" "runtime" "testing" - "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -36,25 +35,21 @@ func TestGenerateInvalidOutputPath(t *testing.T) { } func TestSkipGenerate(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("skipping the test on Windows, see https://github.com/open-telemetry/opentelemetry-collector/issues/5403") - } - cfg := NewDefaultConfig() cfg.Distribution.OutputPath = t.TempDir() cfg.SkipGenerate = true err := Generate(cfg) require.NoError(t, err) outputFile, err := os.Open(cfg.Distribution.OutputPath) + defer func() { + require.NoError(t, outputFile.Close()) + }() require.NoError(t, err) _, err = outputFile.Readdirnames(1) require.ErrorIs(t, err, io.EOF, "skip generate should leave output directory empty") } func TestGenerateAndCompile(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("skipping the test on Windows, see https://github.com/open-telemetry/opentelemetry-collector/issues/5403") - } // This test is dependent on the current file structure. // The goal is find the root of the repo so we can replace the root module. _, thisFile, _, _ := runtime.Caller(0) @@ -64,6 +59,12 @@ func TestGenerateAndCompile(t *testing.T) { fmt.Sprintf("go.opentelemetry.io/collector/config/confignet => %s/config/confignet", workspaceDir), fmt.Sprintf("go.opentelemetry.io/collector/config/configtelemetry => %s/config/configtelemetry", workspaceDir), fmt.Sprintf("go.opentelemetry.io/collector/confmap => %s/confmap", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/confmap/converter/expandconverter => %s/confmap/converter/expandconverter", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/confmap/provider/envprovider => %s/confmap/provider/envprovider", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/confmap/provider/fileprovider => %s/confmap/provider/fileprovider", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/confmap/provider/httpprovider => %s/confmap/provider/httpprovider", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/confmap/provider/httpsprovider => %s/confmap/provider/httpsprovider", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/confmap/provider/yamlprovider => %s/confmap/provider/yamlprovider", workspaceDir), fmt.Sprintf("go.opentelemetry.io/collector/consumer => %s/consumer", workspaceDir), fmt.Sprintf("go.opentelemetry.io/collector/connector => %s/connector", workspaceDir), fmt.Sprintf("go.opentelemetry.io/collector/exporter => %s/exporter", workspaceDir), @@ -129,8 +130,4 @@ func TestGenerateAndCompile(t *testing.T) { require.NoError(t, GenerateAndCompile(cfg)) }) } - - // Sleep for 1 second to make sure all processes using the files are completed - // (on Windows fail to delete temp dir otherwise). - time.Sleep(1 * time.Second) } diff --git a/cmd/builder/internal/builder/package_test.go b/cmd/builder/internal/builder/package_test.go new file mode 100644 index 00000000000..f5e333a7095 --- /dev/null +++ b/cmd/builder/internal/builder/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package builder + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/cmd/builder/internal/builder/templates/go.mod.tmpl b/cmd/builder/internal/builder/templates/go.mod.tmpl index b134bf4b3cb..f70306ae95b 100644 --- a/cmd/builder/internal/builder/templates/go.mod.tmpl +++ b/cmd/builder/internal/builder/templates/go.mod.tmpl @@ -2,7 +2,7 @@ module {{.Distribution.Module}} -go 1.20 +go 1.21 require ( {{- range .Connectors}} @@ -20,7 +20,7 @@ require ( {{- range .Processors}} {{if .GoMod}}{{.GoMod}}{{end}} {{- end}} - go.opentelemetry.io/collector v{{.Distribution.OtelColVersion}} + go.opentelemetry.io/collector{{if .Distribution.RequireOtelColModule}}/otelcol{{end}} v{{.Distribution.OtelColVersion}} ) require ( @@ -49,6 +49,3 @@ replace {{.}} {{- range .Excludes}} exclude {{.}} {{- end}} - -// ambiguous import: found package cloud.google.com/go/compute/metadata in multiple modules -replace cloud.google.com/go => cloud.google.com/go v0.110.2 diff --git a/cmd/builder/internal/builder/templates/main.go.tmpl b/cmd/builder/internal/builder/templates/main.go.tmpl index 2def32ffe0b..64a81295bcb 100644 --- a/cmd/builder/internal/builder/templates/main.go.tmpl +++ b/cmd/builder/internal/builder/templates/main.go.tmpl @@ -5,23 +5,19 @@ package main import ( "log" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/otelcol" ) func main() { - factories, err := components() - if err != nil { - log.Fatalf("failed to build components: %v", err) - } - info := component.BuildInfo{ Command: "{{ .Distribution.Name }}", Description: "{{ .Distribution.Description }}", Version: "{{ .Distribution.Version }}", } - if err := run(otelcol.CollectorSettings{BuildInfo: info, Factories: factories}); err != nil { + if err := run(otelcol.CollectorSettings{BuildInfo: info, Factories: components}); err != nil { log.Fatal(err) } } diff --git a/cmd/builder/internal/builder/templates/main_others.go.tmpl b/cmd/builder/internal/builder/templates/main_others.go.tmpl index e80a51cd4e0..3735aecb586 100644 --- a/cmd/builder/internal/builder/templates/main_others.go.tmpl +++ b/cmd/builder/internal/builder/templates/main_others.go.tmpl @@ -1,7 +1,6 @@ // Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT. //go:build !windows -// +build !windows package main diff --git a/cmd/builder/internal/builder/templates/main_windows.go.tmpl b/cmd/builder/internal/builder/templates/main_windows.go.tmpl index ba327180578..a4930afdca1 100644 --- a/cmd/builder/internal/builder/templates/main_windows.go.tmpl +++ b/cmd/builder/internal/builder/templates/main_windows.go.tmpl @@ -1,46 +1,27 @@ // Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT. //go:build windows -// +build windows package main import ( + "errors" "fmt" - "os" + "golang.org/x/sys/windows" "golang.org/x/sys/windows/svc" "go.opentelemetry.io/collector/otelcol" ) func run(params otelcol.CollectorSettings) error { - if useInteractiveMode, err := checkUseInteractiveMode(); err != nil { - return err - } else if useInteractiveMode { - return runInteractive(params) - } else { - return runService(params) - } -} - -func checkUseInteractiveMode() (bool, error) { - // If environment variable NO_WINDOWS_SERVICE is set with any value other - // than 0, use interactive mode instead of running as a service. This should - // be set in case running as a service is not possible or desired even - // though the current session is not detected to be interactive - if value, present := os.LookupEnv("NO_WINDOWS_SERVICE"); present && value != "0" { - return true, nil - } - - isInteractiveSession, err := svc.IsAnInteractiveSession() - if err != nil { - return false, fmt.Errorf("failed to determine if we are running in an interactive session: %w", err) - } - return isInteractiveSession, nil -} - -func runService(params otelcol.CollectorSettings) error { - // do not need to supply service name when startup is invoked through Service Control Manager directly + // No need to supply service name when startup is invoked through + // the Service Control Manager directly. if err := svc.Run("", otelcol.NewSvcHandler(params)); err != nil { + if errors.Is(err, windows.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { + // Per https://learn.microsoft.com/en-us/windows/win32/api/winsvc/nf-winsvc-startservicectrldispatchera#return-value + // this means that the process is not running as a service, so run interactively. + return runInteractive(params) + } + return fmt.Errorf("failed to start collector server: %w", err) } diff --git a/cmd/builder/internal/command.go b/cmd/builder/internal/command.go index 35c086d3d54..34d1b0b13b9 100644 --- a/cmd/builder/internal/command.go +++ b/cmd/builder/internal/command.go @@ -31,6 +31,7 @@ const ( distributionOutputPathFlag = "output-path" distributionGoFlag = "go" distributionModuleFlag = "module" + verboseFlag = "verbose" ) var ( @@ -52,7 +53,7 @@ build configuration given by the "--config" argument. If no build configuration is provided, ocb will generate a default Collector. `, Args: cobra.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { if err := initConfig(cmd.Flags()); err != nil { return err } @@ -64,6 +65,10 @@ configuration is provided, ocb will generate a default Collector. return fmt.Errorf("go not found: %w", err) } + if err := cfg.SetRequireOtelColModule(); err != nil { + return fmt.Errorf("unable to compare otelcol version: %w", err) + } + if err := cfg.ParseModules(); err != nil { return fmt.Errorf("invalid module configuration: %w", err) } @@ -78,6 +83,7 @@ configuration is provided, ocb will generate a default Collector. cmd.Flags().BoolVar(&cfg.SkipGenerate, skipGenerateFlag, false, "Whether builder should skip generating go code (default false)") cmd.Flags().BoolVar(&cfg.SkipCompilation, skipCompilationFlag, false, "Whether builder should only generate go code with no compile of the collector (default false)") cmd.Flags().BoolVar(&cfg.SkipGetModules, skipGetModulesFlag, false, "Whether builder should skip updating go.mod and retrieve Go module list (default false)") + cmd.Flags().BoolVar(&cfg.Verbose, verboseFlag, false, "Whether builder should print verbose output (default false)") cmd.Flags().StringVar(&cfg.LDFlags, ldflagsFlag, "", `ldflags to include in the "go build" command`) cmd.Flags().StringVar(&cfg.Distribution.Name, distributionNameFlag, "otelcol-custom", "The executable name for the OpenTelemetry Collector distribution") if err := cmd.Flags().MarkDeprecated(distributionNameFlag, "use config distribution::name"); err != nil { diff --git a/cmd/builder/internal/config/default.yaml b/cmd/builder/internal/config/default.yaml index 4fc54f5a09e..1aee339e91b 100644 --- a/cmd/builder/internal/config/default.yaml +++ b/cmd/builder/internal/config/default.yaml @@ -2,22 +2,23 @@ dist: module: go.opentelemetry.io/collector/cmd/otelcorecol name: otelcorecol description: Local OpenTelemetry Collector binary, testing only. - version: 0.85.0-dev - otelcol_version: 0.85.0 + version: 0.96.0-dev + otelcol_version: 0.96.0 receivers: - - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.85.0 + - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.96.0 exporters: - - gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.85.0 - - gomod: go.opentelemetry.io/collector/exporter/loggingexporter v0.85.0 - - gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.85.0 - - gomod: go.opentelemetry.io/collector/exporter/otlphttpexporter v0.85.0 + - gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.96.0 + - gomod: go.opentelemetry.io/collector/exporter/loggingexporter v0.96.0 + - gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.96.0 + - gomod: go.opentelemetry.io/collector/exporter/otlphttpexporter v0.96.0 extensions: - - gomod: go.opentelemetry.io/collector/extension/ballastextension v0.85.0 - - gomod: go.opentelemetry.io/collector/extension/zpagesextension v0.85.0 + - gomod: go.opentelemetry.io/collector/extension/ballastextension v0.96.0 + - gomod: go.opentelemetry.io/collector/extension/memorylimiterextension v0.96.0 + - gomod: go.opentelemetry.io/collector/extension/zpagesextension v0.96.0 processors: - - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.85.0 - - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.85.0 + - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.96.0 + - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.96.0 connectors: - - gomod: go.opentelemetry.io/collector/connector/forwardconnector v0.85.0 + - gomod: go.opentelemetry.io/collector/connector/forwardconnector v0.96.0 diff --git a/cmd/builder/internal/package_test.go b/cmd/builder/internal/package_test.go new file mode 100644 index 00000000000..4486cdb28aa --- /dev/null +++ b/cmd/builder/internal/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package internal + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/cmd/builder/internal/version.go b/cmd/builder/internal/version.go index be1fe805b2b..9ffbbf30955 100644 --- a/cmd/builder/internal/version.go +++ b/cmd/builder/internal/version.go @@ -5,22 +5,42 @@ package internal // import "go.opentelemetry.io/collector/cmd/builder/internal" import ( "fmt" + "runtime/debug" "github.com/spf13/cobra" ) var ( - version = "dev" + version = "" date = "unknown" ) +// binVersion returns the version of the binary. +// If the version is not set, it attempts to read the build information. +// Returns an error if the build information cannot be read. +func binVersion() (string, error) { + if version != "" { + return version, nil + } + info, ok := debug.ReadBuildInfo() + if !ok { + return "", fmt.Errorf("failed to read build info") + } + return info.Main.Version, nil +} + func versionCommand() *cobra.Command { return &cobra.Command{ Use: "version", Short: "Version of ocb", Long: "Prints the version of the ocb binary", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, _ []string) error { + version, err := binVersion() + if err != nil { + return err + } cmd.Println(fmt.Sprintf("%s version %s", cmd.Parent().Name(), version)) + return nil }, } } diff --git a/cmd/builder/test/core.builder.yaml b/cmd/builder/test/core.builder.yaml index 719c653bc3a..0f4fe8e9df4 100644 --- a/cmd/builder/test/core.builder.yaml +++ b/cmd/builder/test/core.builder.yaml @@ -1,20 +1,20 @@ dist: module: go.opentelemetry.io/collector/builder/test/core - otelcol_version: 0.85.0 + otelcol_version: 0.94.0 extensions: - import: go.opentelemetry.io/collector/extension/zpagesextension - gomod: go.opentelemetry.io/collector v0.85.0 + gomod: go.opentelemetry.io/collector v0.94.0 path: ${WORKSPACE_DIR} receivers: - import: go.opentelemetry.io/collector/receiver/otlpreceiver - gomod: go.opentelemetry.io/collector v0.85.0 + gomod: go.opentelemetry.io/collector v0.94.0 path: ${WORKSPACE_DIR} exporters: - import: go.opentelemetry.io/collector/exporter/debugexporter - gomod: go.opentelemetry.io/collector v0.85.0 + gomod: go.opentelemetry.io/collector v0.94.0 path: ${WORKSPACE_DIR} replaces: @@ -26,10 +26,17 @@ replaces: - go.opentelemetry.io/collector/config/confighttp => ${WORKSPACE_DIR}/config/confighttp - go.opentelemetry.io/collector/config/confignet => ${WORKSPACE_DIR}/config/confignet - go.opentelemetry.io/collector/config/configopaque => ${WORKSPACE_DIR}/config/configopaque + - go.opentelemetry.io/collector/config/configretry => ${WORKSPACE_DIR}/config/configretry - go.opentelemetry.io/collector/config/configtelemetry => ${WORKSPACE_DIR}/config/configtelemetry - go.opentelemetry.io/collector/config/configtls => ${WORKSPACE_DIR}/config/configtls - go.opentelemetry.io/collector/config/internal => ${WORKSPACE_DIR}/config/internal - go.opentelemetry.io/collector/confmap => ${WORKSPACE_DIR}/confmap + - go.opentelemetry.io/collector/confmap/converter/expandconverter => ${WORKSPACE_DIR}/confmap/converter/expandconverter + - go.opentelemetry.io/collector/confmap/provider/envprovider => ${WORKSPACE_DIR}/confmap/provider/envprovider + - go.opentelemetry.io/collector/confmap/provider/fileprovider => ${WORKSPACE_DIR}/confmap/provider/fileprovider + - go.opentelemetry.io/collector/confmap/provider/httpprovider => ${WORKSPACE_DIR}/confmap/provider/httpprovider + - go.opentelemetry.io/collector/confmap/provider/httpsprovider => ${WORKSPACE_DIR}/confmap/provider/httpsprovider + - go.opentelemetry.io/collector/confmap/provider/yamlprovider => ${WORKSPACE_DIR}/confmap/provider/yamlprovider - go.opentelemetry.io/collector/consumer => ${WORKSPACE_DIR}/consumer - go.opentelemetry.io/collector/connector => ${WORKSPACE_DIR}/connector - go.opentelemetry.io/collector/exporter => ${WORKSPACE_DIR}/exporter diff --git a/cmd/builder/test/default.otel.yaml b/cmd/builder/test/default.otel.yaml deleted file mode 100644 index e87c0fc6784..00000000000 --- a/cmd/builder/test/default.otel.yaml +++ /dev/null @@ -1,22 +0,0 @@ -extensions: - zpages: - -receivers: - otlp: - protocols: - grpc: - -processors: - -exporters: - debug: - -service: - extensions: [zpages] - pipelines: - traces: - receivers: - - otlp - processors: [] - exporters: - - debug diff --git a/cmd/mdatagen/Makefile b/cmd/mdatagen/Makefile new file mode 100644 index 00000000000..ded7a36092d --- /dev/null +++ b/cmd/mdatagen/Makefile @@ -0,0 +1 @@ +include ../../Makefile.Common diff --git a/cmd/mdatagen/README.md b/cmd/mdatagen/README.md new file mode 100644 index 00000000000..b2affa6c780 --- /dev/null +++ b/cmd/mdatagen/README.md @@ -0,0 +1,56 @@ +# Metadata Generator + +Every component's documentation should include a brief description of the component and guidance on how to use it. +There is also some information about the component (or metadata) that should be included to help end-users understand the current state of the component and whether it is right for their use case. +Examples of this metadata about a component are: + +* its stability level +* the distributions containing it +* the types of pipelines it supports +* metrics emitted in the case of a scraping receiver + +The metadata generator defines a schema for specifying this information to ensure it is complete and well-formed. +The metadata generator is then able to ingest the metadata, validate it against the schema and produce documentation in a standardized format. +An example of how this generated documentation looks can be found in [documentation.md](./documentation.md). + +## Using the Metadata Generator + +In order for a component to benefit from the metadata generator (`mdatagen`) these requirements need to be met: +1. A `metadata.yaml` file containing the metadata needs to be included in the component +2. The component should declare a `go:generate mdatagen` directive which tells `mdatagen` what to generate + +As an example, here is a minimal `metadata.yaml` for the [OTLP receiver](https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver/otlpreceiver): +```yaml +type: otlp +status: + class: receiver + stability: + beta: [logs] + stable: [metrics, traces] +``` + +Detailed information about the schema of `metadata.yaml` can be found in [metadata-schema.yaml](./metadata-schema.yaml). + +The `go:generate mdatagen` directive is usually defined in a `doc.go` file in the same package as the component, for example: +```go +//go:generate mdatagen metadata.yaml + +package main +``` + +Below are some more examples that can be used for reference: + +* The ElasticSearch receiver has an extensive [metadata.yaml](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/elasticsearchreceiver/metadata.yaml) +* The host metrics receiver has internal subcomponents, each with their own `metadata.yaml` and `doc.go`. See [cpuscraper](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/hostmetricsreceiver/internal/scraper/cpuscraper) for example. + +You can run `cd cmd/mdatagen && $(GOCMD) install .` to install the `mdatagen` tool in `GOBIN` and then run `mdatagen metadata.yaml` to generate documentation for a specific component or you can run `make generate` to generate documentation for all components. + +## Contributing to the Metadata Generator + +The code for generating the documentation can be found in [loader.go](./loader.go) and the templates for rendering the documentation can be found in [templates](./templates). +When making updates to the metadata generator or introducing support for new functionality: + +1. Ensure the [metadata-schema.yaml](./metadata-schema.yaml) and [./metadata.yaml](metadata.yaml) files reflect the changes. +2. Run `make mdatagen-test`. +3. Make sure all tests are passing including [generated tests](./internal/metadata/generated_metrics_test.go). +4. Run `make generate`. diff --git a/cmd/mdatagen/doc.go b/cmd/mdatagen/doc.go new file mode 100644 index 00000000000..8f1fc6a7176 --- /dev/null +++ b/cmd/mdatagen/doc.go @@ -0,0 +1,7 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Generate a test metrics builder from a sample metrics set covering all configuration options. +//go:generate mdatagen metadata-sample.yaml + +package main diff --git a/cmd/mdatagen/documentation.md b/cmd/mdatagen/documentation.md new file mode 100644 index 00000000000..1955e081535 --- /dev/null +++ b/cmd/mdatagen/documentation.md @@ -0,0 +1,96 @@ +[comment]: <> (Code generated by mdatagen. DO NOT EDIT.) + +# file + +## Default Metrics + +The following metrics are emitted by default. Each of them can be disabled by applying the following configuration: + +```yaml +metrics: + : + enabled: false +``` + +### default.metric + +Monotonic cumulative sum int metric enabled by default. + +The metric will be become optional soon. + +| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic | +| ---- | ----------- | ---------- | ----------------------- | --------- | +| s | Sum | Int | Cumulative | true | + +#### Attributes + +| Name | Description | Values | +| ---- | ----------- | ------ | +| string_attr | Attribute with any string value. | Any Str | +| state | Integer attribute with overridden name. | Any Int | +| enum_attr | Attribute with a known set of string values. | Str: ``red``, ``green``, ``blue`` | +| slice_attr | Attribute with a slice value. | Any Slice | +| map_attr | Attribute with a map value. | Any Map | + +### default.metric.to_be_removed + +[DEPRECATED] Non-monotonic delta sum double metric enabled by default. + +The metric will be will be removed soon. + +| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic | +| ---- | ----------- | ---------- | ----------------------- | --------- | +| s | Sum | Double | Delta | false | + +## Optional Metrics + +The following metrics are not emitted by default. Each of them can be enabled by applying the following configuration: + +```yaml +metrics: + : + enabled: true +``` + +### optional.metric + +[DEPRECATED] Gauge double metric disabled by default. + +| Unit | Metric Type | Value Type | +| ---- | ----------- | ---------- | +| 1 | Gauge | Double | + +#### Attributes + +| Name | Description | Values | +| ---- | ----------- | ------ | +| string_attr | Attribute with any string value. | Any Str | +| boolean_attr | Attribute with a boolean value. | Any Bool | + +### optional.metric.empty_unit + +[DEPRECATED] Gauge double metric disabled by default. + +| Unit | Metric Type | Value Type | +| ---- | ----------- | ---------- | +| | Gauge | Double | + +#### Attributes + +| Name | Description | Values | +| ---- | ----------- | ------ | +| string_attr | Attribute with any string value. | Any Str | +| boolean_attr | Attribute with a boolean value. | Any Bool | + +## Resource Attributes + +| Name | Description | Values | Enabled | +| ---- | ----------- | ------ | ------- | +| map.resource.attr | Resource attribute with a map value. | Any Map | true | +| optional.resource.attr | Explicitly disabled ResourceAttribute. | Any Str | false | +| slice.resource.attr | Resource attribute with a slice value. | Any Slice | true | +| string.enum.resource.attr | Resource attribute with a known set of string values. | Str: ``one``, ``two`` | true | +| string.resource.attr | Resource attribute with any string value. | Any Str | true | +| string.resource.attr_disable_warning | Resource attribute with any string value. | Any Str | true | +| string.resource.attr_remove_warning | Resource attribute with any string value. | Any Str | false | +| string.resource.attr_to_be_removed | Resource attribute with any string value. | Any Str | true | diff --git a/cmd/mdatagen/embeded_templates.go b/cmd/mdatagen/embeded_templates.go new file mode 100644 index 00000000000..dace6c43f32 --- /dev/null +++ b/cmd/mdatagen/embeded_templates.go @@ -0,0 +1,13 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import "embed" + +// templateFS ensures that the files needed +// to generate metadata as an embedded filesystem since +// `go get` doesn't require these files to be downloaded. +// +//go:embed templates/*.tmpl templates/testdata/*.tmpl +var templateFS embed.FS diff --git a/cmd/mdatagen/embeded_templates_test.go b/cmd/mdatagen/embeded_templates_test.go new file mode 100644 index 00000000000..1f4c4684e4e --- /dev/null +++ b/cmd/mdatagen/embeded_templates_test.go @@ -0,0 +1,47 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "io/fs" + "path" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestEnsureTemplatesLoaded(t *testing.T) { + t.Parallel() + + const ( + rootDir = "templates" + ) + + var ( + templateFiles = map[string]struct{}{ + path.Join(rootDir, "component_test.go.tmpl"): {}, + path.Join(rootDir, "documentation.md.tmpl"): {}, + path.Join(rootDir, "metrics.go.tmpl"): {}, + path.Join(rootDir, "metrics_test.go.tmpl"): {}, + path.Join(rootDir, "resource.go.tmpl"): {}, + path.Join(rootDir, "resource_test.go.tmpl"): {}, + path.Join(rootDir, "config.go.tmpl"): {}, + path.Join(rootDir, "config_test.go.tmpl"): {}, + path.Join(rootDir, "readme.md.tmpl"): {}, + path.Join(rootDir, "status.go.tmpl"): {}, + path.Join(rootDir, "testdata", "config.yaml.tmpl"): {}, + } + count = 0 + ) + assert.NoError(t, fs.WalkDir(templateFS, ".", func(path string, d fs.DirEntry, _ error) error { + if d != nil && d.IsDir() { + return nil + } + count++ + assert.Contains(t, templateFiles, path) + return nil + })) + assert.Equal(t, len(templateFiles), count, "Must match the expected number of calls") + +} diff --git a/cmd/mdatagen/go.mod b/cmd/mdatagen/go.mod new file mode 100644 index 00000000000..e654d0832c7 --- /dev/null +++ b/cmd/mdatagen/go.mod @@ -0,0 +1,81 @@ +module go.opentelemetry.io/collector/cmd/mdatagen + +go 1.21 + +require ( + github.com/google/go-cmp v0.6.0 + github.com/stretchr/testify v1.8.4 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/confmap v0.96.0 + go.opentelemetry.io/collector/confmap/provider/fileprovider v0.96.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/collector/receiver v0.96.0 + go.opentelemetry.io/collector/semconv v0.96.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/multierr v1.11.0 + go.uber.org/zap v1.27.0 + golang.org/x/text v0.14.0 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/consumer v0.96.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace go.opentelemetry.io/collector/component => ../../component + +replace go.opentelemetry.io/collector/confmap => ../../confmap + +replace go.opentelemetry.io/collector/confmap/provider/fileprovider => ../../confmap/provider/fileprovider + +replace go.opentelemetry.io/collector/pdata => ../../pdata + +replace go.opentelemetry.io/collector/receiver => ../../receiver + +replace go.opentelemetry.io/collector/semconv => ../../semconv + +replace go.opentelemetry.io/collector/featuregate => ../../featuregate + +replace go.opentelemetry.io/collector/consumer => ../../consumer + +replace go.opentelemetry.io/collector => ../.. + +replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry + +retract ( + v0.76.2 + v0.76.1 + v0.65.0 +) diff --git a/cmd/mdatagen/go.sum b/cmd/mdatagen/go.sum new file mode 100644 index 00000000000..06616cda85d --- /dev/null +++ b/cmd/mdatagen/go.sum @@ -0,0 +1,126 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +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= +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/cmd/mdatagen/internal/metadata/generated_config.go b/cmd/mdatagen/internal/metadata/generated_config.go new file mode 100644 index 00000000000..92937f48dbf --- /dev/null +++ b/cmd/mdatagen/internal/metadata/generated_config.go @@ -0,0 +1,122 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import "go.opentelemetry.io/collector/confmap" + +// MetricConfig provides common config for a particular metric. +type MetricConfig struct { + Enabled bool `mapstructure:"enabled"` + + enabledSetByUser bool +} + +func (ms *MetricConfig) Unmarshal(parser *confmap.Conf) error { + if parser == nil { + return nil + } + err := parser.Unmarshal(ms) + if err != nil { + return err + } + ms.enabledSetByUser = parser.IsSet("enabled") + return nil +} + +// MetricsConfig provides config for file metrics. +type MetricsConfig struct { + DefaultMetric MetricConfig `mapstructure:"default.metric"` + DefaultMetricToBeRemoved MetricConfig `mapstructure:"default.metric.to_be_removed"` + OptionalMetric MetricConfig `mapstructure:"optional.metric"` + OptionalMetricEmptyUnit MetricConfig `mapstructure:"optional.metric.empty_unit"` +} + +func DefaultMetricsConfig() MetricsConfig { + return MetricsConfig{ + DefaultMetric: MetricConfig{ + Enabled: true, + }, + DefaultMetricToBeRemoved: MetricConfig{ + Enabled: true, + }, + OptionalMetric: MetricConfig{ + Enabled: false, + }, + OptionalMetricEmptyUnit: MetricConfig{ + Enabled: false, + }, + } +} + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` + + enabledSetByUser bool +} + +func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error { + if parser == nil { + return nil + } + err := parser.Unmarshal(rac) + if err != nil { + return err + } + rac.enabledSetByUser = parser.IsSet("enabled") + return nil +} + +// ResourceAttributesConfig provides config for file resource attributes. +type ResourceAttributesConfig struct { + MapResourceAttr ResourceAttributeConfig `mapstructure:"map.resource.attr"` + OptionalResourceAttr ResourceAttributeConfig `mapstructure:"optional.resource.attr"` + SliceResourceAttr ResourceAttributeConfig `mapstructure:"slice.resource.attr"` + StringEnumResourceAttr ResourceAttributeConfig `mapstructure:"string.enum.resource.attr"` + StringResourceAttr ResourceAttributeConfig `mapstructure:"string.resource.attr"` + StringResourceAttrDisableWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_disable_warning"` + StringResourceAttrRemoveWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_remove_warning"` + StringResourceAttrToBeRemoved ResourceAttributeConfig `mapstructure:"string.resource.attr_to_be_removed"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + MapResourceAttr: ResourceAttributeConfig{ + Enabled: true, + }, + OptionalResourceAttr: ResourceAttributeConfig{ + Enabled: false, + }, + SliceResourceAttr: ResourceAttributeConfig{ + Enabled: true, + }, + StringEnumResourceAttr: ResourceAttributeConfig{ + Enabled: true, + }, + StringResourceAttr: ResourceAttributeConfig{ + Enabled: true, + }, + StringResourceAttrDisableWarning: ResourceAttributeConfig{ + Enabled: true, + }, + StringResourceAttrRemoveWarning: ResourceAttributeConfig{ + Enabled: false, + }, + StringResourceAttrToBeRemoved: ResourceAttributeConfig{ + Enabled: true, + }, + } +} + +// MetricsBuilderConfig is a configuration for file metrics builder. +type MetricsBuilderConfig struct { + Metrics MetricsConfig `mapstructure:"metrics"` + ResourceAttributes ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func DefaultMetricsBuilderConfig() MetricsBuilderConfig { + return MetricsBuilderConfig{ + Metrics: DefaultMetricsConfig(), + ResourceAttributes: DefaultResourceAttributesConfig(), + } +} diff --git a/cmd/mdatagen/internal/metadata/generated_config_test.go b/cmd/mdatagen/internal/metadata/generated_config_test.go new file mode 100644 index 00000000000..bfb90940386 --- /dev/null +++ b/cmd/mdatagen/internal/metadata/generated_config_test.go @@ -0,0 +1,145 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestMetricsBuilderConfig(t *testing.T) { + tests := []struct { + name string + want MetricsBuilderConfig + }{ + { + name: "default", + want: DefaultMetricsBuilderConfig(), + }, + { + name: "all_set", + want: MetricsBuilderConfig{ + Metrics: MetricsConfig{ + DefaultMetric: MetricConfig{Enabled: true}, + DefaultMetricToBeRemoved: MetricConfig{Enabled: true}, + OptionalMetric: MetricConfig{Enabled: true}, + OptionalMetricEmptyUnit: MetricConfig{Enabled: true}, + }, + ResourceAttributes: ResourceAttributesConfig{ + MapResourceAttr: ResourceAttributeConfig{Enabled: true}, + OptionalResourceAttr: ResourceAttributeConfig{Enabled: true}, + SliceResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringEnumResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: true}, + }, + }, + }, + { + name: "none_set", + want: MetricsBuilderConfig{ + Metrics: MetricsConfig{ + DefaultMetric: MetricConfig{Enabled: false}, + DefaultMetricToBeRemoved: MetricConfig{Enabled: false}, + OptionalMetric: MetricConfig{Enabled: false}, + OptionalMetricEmptyUnit: MetricConfig{Enabled: false}, + }, + ResourceAttributes: ResourceAttributesConfig{ + MapResourceAttr: ResourceAttributeConfig{Enabled: false}, + OptionalResourceAttr: ResourceAttributeConfig{Enabled: false}, + SliceResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringEnumResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: false}, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg := loadMetricsBuilderConfig(t, tt.name) + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(MetricConfig{}, ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} + +func loadMetricsBuilderConfig(t *testing.T, name string) MetricsBuilderConfig { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(name) + require.NoError(t, err) + cfg := DefaultMetricsBuilderConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + return cfg +} + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + MapResourceAttr: ResourceAttributeConfig{Enabled: true}, + OptionalResourceAttr: ResourceAttributeConfig{Enabled: true}, + SliceResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringEnumResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + MapResourceAttr: ResourceAttributeConfig{Enabled: false}, + OptionalResourceAttr: ResourceAttributeConfig{Enabled: false}, + SliceResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringEnumResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg := loadResourceAttributesConfig(t, tt.name) + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} + +func loadResourceAttributesConfig(t *testing.T, name string) ResourceAttributesConfig { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + return cfg +} diff --git a/cmd/mdatagen/internal/metadata/generated_metrics.go b/cmd/mdatagen/internal/metadata/generated_metrics.go new file mode 100644 index 00000000000..a6d8a7e4169 --- /dev/null +++ b/cmd/mdatagen/internal/metadata/generated_metrics.go @@ -0,0 +1,425 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "time" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/receiver" + conventions "go.opentelemetry.io/collector/semconv/v1.9.0" +) + +// AttributeEnumAttr specifies the a value enum_attr attribute. +type AttributeEnumAttr int + +const ( + _ AttributeEnumAttr = iota + AttributeEnumAttrRed + AttributeEnumAttrGreen + AttributeEnumAttrBlue +) + +// String returns the string representation of the AttributeEnumAttr. +func (av AttributeEnumAttr) String() string { + switch av { + case AttributeEnumAttrRed: + return "red" + case AttributeEnumAttrGreen: + return "green" + case AttributeEnumAttrBlue: + return "blue" + } + return "" +} + +// MapAttributeEnumAttr is a helper map of string to AttributeEnumAttr attribute value. +var MapAttributeEnumAttr = map[string]AttributeEnumAttr{ + "red": AttributeEnumAttrRed, + "green": AttributeEnumAttrGreen, + "blue": AttributeEnumAttrBlue, +} + +type metricDefaultMetric struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills default.metric metric with initial data. +func (m *metricDefaultMetric) init() { + m.data.SetName("default.metric") + m.data.SetDescription("Monotonic cumulative sum int metric enabled by default.") + m.data.SetUnit("s") + m.data.SetEmptySum() + m.data.Sum().SetIsMonotonic(true) + m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative) + m.data.Sum().DataPoints().EnsureCapacity(m.capacity) +} + +func (m *metricDefaultMetric) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue string, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any) { + if !m.config.Enabled { + return + } + dp := m.data.Sum().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetIntValue(val) + dp.Attributes().PutStr("string_attr", stringAttrAttributeValue) + dp.Attributes().PutInt("state", overriddenIntAttrAttributeValue) + dp.Attributes().PutStr("enum_attr", enumAttrAttributeValue) + dp.Attributes().PutEmptySlice("slice_attr").FromRaw(sliceAttrAttributeValue) + dp.Attributes().PutEmptyMap("map_attr").FromRaw(mapAttrAttributeValue) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricDefaultMetric) updateCapacity() { + if m.data.Sum().DataPoints().Len() > m.capacity { + m.capacity = m.data.Sum().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricDefaultMetric) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricDefaultMetric(cfg MetricConfig) metricDefaultMetric { + m := metricDefaultMetric{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricDefaultMetricToBeRemoved struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills default.metric.to_be_removed metric with initial data. +func (m *metricDefaultMetricToBeRemoved) init() { + m.data.SetName("default.metric.to_be_removed") + m.data.SetDescription("[DEPRECATED] Non-monotonic delta sum double metric enabled by default.") + m.data.SetUnit("s") + m.data.SetEmptySum() + m.data.Sum().SetIsMonotonic(false) + m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityDelta) +} + +func (m *metricDefaultMetricToBeRemoved) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) { + if !m.config.Enabled { + return + } + dp := m.data.Sum().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricDefaultMetricToBeRemoved) updateCapacity() { + if m.data.Sum().DataPoints().Len() > m.capacity { + m.capacity = m.data.Sum().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricDefaultMetricToBeRemoved) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricDefaultMetricToBeRemoved(cfg MetricConfig) metricDefaultMetricToBeRemoved { + m := metricDefaultMetricToBeRemoved{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricOptionalMetric struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills optional.metric metric with initial data. +func (m *metricOptionalMetric) init() { + m.data.SetName("optional.metric") + m.data.SetDescription("[DEPRECATED] Gauge double metric disabled by default.") + m.data.SetUnit("1") + m.data.SetEmptyGauge() + m.data.Gauge().DataPoints().EnsureCapacity(m.capacity) +} + +func (m *metricOptionalMetric) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) + dp.Attributes().PutStr("string_attr", stringAttrAttributeValue) + dp.Attributes().PutBool("boolean_attr", booleanAttrAttributeValue) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricOptionalMetric) updateCapacity() { + if m.data.Gauge().DataPoints().Len() > m.capacity { + m.capacity = m.data.Gauge().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricOptionalMetric) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricOptionalMetric(cfg MetricConfig) metricOptionalMetric { + m := metricOptionalMetric{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricOptionalMetricEmptyUnit struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills optional.metric.empty_unit metric with initial data. +func (m *metricOptionalMetricEmptyUnit) init() { + m.data.SetName("optional.metric.empty_unit") + m.data.SetDescription("[DEPRECATED] Gauge double metric disabled by default.") + m.data.SetUnit("") + m.data.SetEmptyGauge() + m.data.Gauge().DataPoints().EnsureCapacity(m.capacity) +} + +func (m *metricOptionalMetricEmptyUnit) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) + dp.Attributes().PutStr("string_attr", stringAttrAttributeValue) + dp.Attributes().PutBool("boolean_attr", booleanAttrAttributeValue) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricOptionalMetricEmptyUnit) updateCapacity() { + if m.data.Gauge().DataPoints().Len() > m.capacity { + m.capacity = m.data.Gauge().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricOptionalMetricEmptyUnit) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricOptionalMetricEmptyUnit(cfg MetricConfig) metricOptionalMetricEmptyUnit { + m := metricOptionalMetricEmptyUnit{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +// MetricsBuilder provides an interface for scrapers to report metrics while taking care of all the transformations +// required to produce metric representation defined in metadata and user config. +type MetricsBuilder struct { + config MetricsBuilderConfig // config of the metrics builder. + startTime pcommon.Timestamp // start time that will be applied to all recorded data points. + metricsCapacity int // maximum observed number of metrics per resource. + metricsBuffer pmetric.Metrics // accumulates metrics data before emitting. + buildInfo component.BuildInfo // contains version information. + metricDefaultMetric metricDefaultMetric + metricDefaultMetricToBeRemoved metricDefaultMetricToBeRemoved + metricOptionalMetric metricOptionalMetric + metricOptionalMetricEmptyUnit metricOptionalMetricEmptyUnit +} + +// metricBuilderOption applies changes to default metrics builder. +type metricBuilderOption func(*MetricsBuilder) + +// WithStartTime sets startTime on the metrics builder. +func WithStartTime(startTime pcommon.Timestamp) metricBuilderOption { + return func(mb *MetricsBuilder) { + mb.startTime = startTime + } +} + +func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.CreateSettings, options ...metricBuilderOption) *MetricsBuilder { + if !mbc.Metrics.DefaultMetric.enabledSetByUser { + settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `default.metric`: This metric will be disabled by default soon.") + } + if mbc.Metrics.DefaultMetricToBeRemoved.Enabled { + settings.Logger.Warn("[WARNING] `default.metric.to_be_removed` should not be enabled: This metric is deprecated and will be removed soon.") + } + if mbc.Metrics.OptionalMetric.enabledSetByUser { + settings.Logger.Warn("[WARNING] `optional.metric` should not be configured: This metric is deprecated and will be removed soon.") + } + if mbc.Metrics.OptionalMetricEmptyUnit.enabledSetByUser { + settings.Logger.Warn("[WARNING] `optional.metric.empty_unit` should not be configured: This metric is deprecated and will be removed soon.") + } + if !mbc.ResourceAttributes.StringResourceAttrDisableWarning.enabledSetByUser { + settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `string.resource.attr_disable_warning`: This resource_attribute will be disabled by default soon.") + } + if mbc.ResourceAttributes.StringResourceAttrRemoveWarning.enabledSetByUser { + settings.Logger.Warn("[WARNING] `string.resource.attr_remove_warning` should not be configured: This resource_attribute is deprecated and will be removed soon.") + } + if mbc.ResourceAttributes.StringResourceAttrToBeRemoved.Enabled { + settings.Logger.Warn("[WARNING] `string.resource.attr_to_be_removed` should not be enabled: This resource_attribute is deprecated and will be removed soon.") + } + mb := &MetricsBuilder{ + config: mbc, + startTime: pcommon.NewTimestampFromTime(time.Now()), + metricsBuffer: pmetric.NewMetrics(), + buildInfo: settings.BuildInfo, + metricDefaultMetric: newMetricDefaultMetric(mbc.Metrics.DefaultMetric), + metricDefaultMetricToBeRemoved: newMetricDefaultMetricToBeRemoved(mbc.Metrics.DefaultMetricToBeRemoved), + metricOptionalMetric: newMetricOptionalMetric(mbc.Metrics.OptionalMetric), + metricOptionalMetricEmptyUnit: newMetricOptionalMetricEmptyUnit(mbc.Metrics.OptionalMetricEmptyUnit), + } + for _, op := range options { + op(mb) + } + return mb +} + +// NewResourceBuilder returns a new resource builder that should be used to build a resource associated with for the emitted metrics. +func (mb *MetricsBuilder) NewResourceBuilder() *ResourceBuilder { + return NewResourceBuilder(mb.config.ResourceAttributes) +} + +// updateCapacity updates max length of metrics and resource attributes that will be used for the slice capacity. +func (mb *MetricsBuilder) updateCapacity(rm pmetric.ResourceMetrics) { + if mb.metricsCapacity < rm.ScopeMetrics().At(0).Metrics().Len() { + mb.metricsCapacity = rm.ScopeMetrics().At(0).Metrics().Len() + } +} + +// ResourceMetricsOption applies changes to provided resource metrics. +type ResourceMetricsOption func(pmetric.ResourceMetrics) + +// WithResource sets the provided resource on the emitted ResourceMetrics. +// It's recommended to use ResourceBuilder to create the resource. +func WithResource(res pcommon.Resource) ResourceMetricsOption { + return func(rm pmetric.ResourceMetrics) { + res.CopyTo(rm.Resource()) + } +} + +// WithStartTimeOverride overrides start time for all the resource metrics data points. +// This option should be only used if different start time has to be set on metrics coming from different resources. +func WithStartTimeOverride(start pcommon.Timestamp) ResourceMetricsOption { + return func(rm pmetric.ResourceMetrics) { + var dps pmetric.NumberDataPointSlice + metrics := rm.ScopeMetrics().At(0).Metrics() + for i := 0; i < metrics.Len(); i++ { + switch metrics.At(i).Type() { + case pmetric.MetricTypeGauge: + dps = metrics.At(i).Gauge().DataPoints() + case pmetric.MetricTypeSum: + dps = metrics.At(i).Sum().DataPoints() + } + for j := 0; j < dps.Len(); j++ { + dps.At(j).SetStartTimestamp(start) + } + } + } +} + +// EmitForResource saves all the generated metrics under a new resource and updates the internal state to be ready for +// recording another set of data points as part of another resource. This function can be helpful when one scraper +// needs to emit metrics from several resources. Otherwise calling this function is not required, +// just `Emit` function can be called instead. +// Resource attributes should be provided as ResourceMetricsOption arguments. +func (mb *MetricsBuilder) EmitForResource(rmo ...ResourceMetricsOption) { + rm := pmetric.NewResourceMetrics() + rm.SetSchemaUrl(conventions.SchemaURL) + ils := rm.ScopeMetrics().AppendEmpty() + ils.Scope().SetName("go.opentelemetry.io/collector") + ils.Scope().SetVersion(mb.buildInfo.Version) + ils.Metrics().EnsureCapacity(mb.metricsCapacity) + mb.metricDefaultMetric.emit(ils.Metrics()) + mb.metricDefaultMetricToBeRemoved.emit(ils.Metrics()) + mb.metricOptionalMetric.emit(ils.Metrics()) + mb.metricOptionalMetricEmptyUnit.emit(ils.Metrics()) + + for _, op := range rmo { + op(rm) + } + if ils.Metrics().Len() > 0 { + mb.updateCapacity(rm) + rm.MoveTo(mb.metricsBuffer.ResourceMetrics().AppendEmpty()) + } +} + +// Emit returns all the metrics accumulated by the metrics builder and updates the internal state to be ready for +// recording another set of metrics. This function will be responsible for applying all the transformations required to +// produce metric representation defined in metadata and user config, e.g. delta or cumulative. +func (mb *MetricsBuilder) Emit(rmo ...ResourceMetricsOption) pmetric.Metrics { + mb.EmitForResource(rmo...) + metrics := mb.metricsBuffer + mb.metricsBuffer = pmetric.NewMetrics() + return metrics +} + +// RecordDefaultMetricDataPoint adds a data point to default.metric metric. +func (mb *MetricsBuilder) RecordDefaultMetricDataPoint(ts pcommon.Timestamp, val int64, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue AttributeEnumAttr, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any) { + mb.metricDefaultMetric.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, overriddenIntAttrAttributeValue, enumAttrAttributeValue.String(), sliceAttrAttributeValue, mapAttrAttributeValue) +} + +// RecordDefaultMetricToBeRemovedDataPoint adds a data point to default.metric.to_be_removed metric. +func (mb *MetricsBuilder) RecordDefaultMetricToBeRemovedDataPoint(ts pcommon.Timestamp, val float64) { + mb.metricDefaultMetricToBeRemoved.recordDataPoint(mb.startTime, ts, val) +} + +// RecordOptionalMetricDataPoint adds a data point to optional.metric metric. +func (mb *MetricsBuilder) RecordOptionalMetricDataPoint(ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool) { + mb.metricOptionalMetric.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, booleanAttrAttributeValue) +} + +// RecordOptionalMetricEmptyUnitDataPoint adds a data point to optional.metric.empty_unit metric. +func (mb *MetricsBuilder) RecordOptionalMetricEmptyUnitDataPoint(ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool) { + mb.metricOptionalMetricEmptyUnit.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, booleanAttrAttributeValue) +} + +// Reset resets metrics builder to its initial state. It should be used when external metrics source is restarted, +// and metrics builder should update its startTime and reset it's internal state accordingly. +func (mb *MetricsBuilder) Reset(options ...metricBuilderOption) { + mb.startTime = pcommon.NewTimestampFromTime(time.Now()) + for _, op := range options { + op(mb) + } +} diff --git a/cmd/mdatagen/internal/metadata/generated_metrics_test.go b/cmd/mdatagen/internal/metadata/generated_metrics_test.go new file mode 100644 index 00000000000..4860ac1ba2b --- /dev/null +++ b/cmd/mdatagen/internal/metadata/generated_metrics_test.go @@ -0,0 +1,215 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "go.uber.org/zap" + "go.uber.org/zap/zaptest/observer" + + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +type testConfigCollection int + +const ( + testSetDefault testConfigCollection = iota + testSetAll + testSetNone +) + +func TestMetricsBuilder(t *testing.T) { + tests := []struct { + name string + configSet testConfigCollection + }{ + { + name: "default", + configSet: testSetDefault, + }, + { + name: "all_set", + configSet: testSetAll, + }, + { + name: "none_set", + configSet: testSetNone, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + start := pcommon.Timestamp(1_000_000_000) + ts := pcommon.Timestamp(1_000_001_000) + observedZapCore, observedLogs := observer.New(zap.WarnLevel) + settings := receivertest.NewNopCreateSettings() + settings.Logger = zap.New(observedZapCore) + mb := NewMetricsBuilder(loadMetricsBuilderConfig(t, test.name), settings, WithStartTime(start)) + + expectedWarnings := 0 + if test.configSet == testSetDefault { + assert.Equal(t, "[WARNING] Please set `enabled` field explicitly for `default.metric`: This metric will be disabled by default soon.", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + if test.configSet == testSetDefault || test.configSet == testSetAll { + assert.Equal(t, "[WARNING] `default.metric.to_be_removed` should not be enabled: This metric is deprecated and will be removed soon.", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + if test.configSet == testSetAll || test.configSet == testSetNone { + assert.Equal(t, "[WARNING] `optional.metric` should not be configured: This metric is deprecated and will be removed soon.", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + if test.configSet == testSetAll || test.configSet == testSetNone { + assert.Equal(t, "[WARNING] `optional.metric.empty_unit` should not be configured: This metric is deprecated and will be removed soon.", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + if test.configSet == testSetDefault { + assert.Equal(t, "[WARNING] Please set `enabled` field explicitly for `string.resource.attr_disable_warning`: This resource_attribute will be disabled by default soon.", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + if test.configSet == testSetAll || test.configSet == testSetNone { + assert.Equal(t, "[WARNING] `string.resource.attr_remove_warning` should not be configured: This resource_attribute is deprecated and will be removed soon.", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + if test.configSet == testSetDefault || test.configSet == testSetAll { + assert.Equal(t, "[WARNING] `string.resource.attr_to_be_removed` should not be enabled: This resource_attribute is deprecated and will be removed soon.", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + + assert.Equal(t, expectedWarnings, observedLogs.Len()) + + defaultMetricsCount := 0 + allMetricsCount := 0 + + defaultMetricsCount++ + allMetricsCount++ + mb.RecordDefaultMetricDataPoint(ts, 1, "string_attr-val", 19, AttributeEnumAttrRed, []any{"slice_attr-item1", "slice_attr-item2"}, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}) + + defaultMetricsCount++ + allMetricsCount++ + mb.RecordDefaultMetricToBeRemovedDataPoint(ts, 1) + + allMetricsCount++ + mb.RecordOptionalMetricDataPoint(ts, 1, "string_attr-val", true) + + allMetricsCount++ + mb.RecordOptionalMetricEmptyUnitDataPoint(ts, 1, "string_attr-val", true) + + rb := mb.NewResourceBuilder() + rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"}) + rb.SetOptionalResourceAttr("optional.resource.attr-val") + rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"}) + rb.SetStringEnumResourceAttrOne() + rb.SetStringResourceAttr("string.resource.attr-val") + rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val") + rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val") + rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val") + res := rb.Emit() + metrics := mb.Emit(WithResource(res)) + + if test.configSet == testSetNone { + assert.Equal(t, 0, metrics.ResourceMetrics().Len()) + return + } + + assert.Equal(t, 1, metrics.ResourceMetrics().Len()) + rm := metrics.ResourceMetrics().At(0) + assert.Equal(t, res, rm.Resource()) + assert.Equal(t, 1, rm.ScopeMetrics().Len()) + ms := rm.ScopeMetrics().At(0).Metrics() + if test.configSet == testSetDefault { + assert.Equal(t, defaultMetricsCount, ms.Len()) + } + if test.configSet == testSetAll { + assert.Equal(t, allMetricsCount, ms.Len()) + } + validatedMetrics := make(map[string]bool) + for i := 0; i < ms.Len(); i++ { + switch ms.At(i).Name() { + case "default.metric": + assert.False(t, validatedMetrics["default.metric"], "Found a duplicate in the metrics slice: default.metric") + validatedMetrics["default.metric"] = true + assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len()) + assert.Equal(t, "Monotonic cumulative sum int metric enabled by default.", ms.At(i).Description()) + assert.Equal(t, "s", ms.At(i).Unit()) + assert.Equal(t, true, ms.At(i).Sum().IsMonotonic()) + assert.Equal(t, pmetric.AggregationTemporalityCumulative, ms.At(i).Sum().AggregationTemporality()) + dp := ms.At(i).Sum().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeInt, dp.ValueType()) + assert.Equal(t, int64(1), dp.IntValue()) + attrVal, ok := dp.Attributes().Get("string_attr") + assert.True(t, ok) + assert.EqualValues(t, "string_attr-val", attrVal.Str()) + attrVal, ok = dp.Attributes().Get("state") + assert.True(t, ok) + assert.EqualValues(t, 19, attrVal.Int()) + attrVal, ok = dp.Attributes().Get("enum_attr") + assert.True(t, ok) + assert.EqualValues(t, "red", attrVal.Str()) + attrVal, ok = dp.Attributes().Get("slice_attr") + assert.True(t, ok) + assert.EqualValues(t, []any{"slice_attr-item1", "slice_attr-item2"}, attrVal.Slice().AsRaw()) + attrVal, ok = dp.Attributes().Get("map_attr") + assert.True(t, ok) + assert.EqualValues(t, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}, attrVal.Map().AsRaw()) + case "default.metric.to_be_removed": + assert.False(t, validatedMetrics["default.metric.to_be_removed"], "Found a duplicate in the metrics slice: default.metric.to_be_removed") + validatedMetrics["default.metric.to_be_removed"] = true + assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len()) + assert.Equal(t, "[DEPRECATED] Non-monotonic delta sum double metric enabled by default.", ms.At(i).Description()) + assert.Equal(t, "s", ms.At(i).Unit()) + assert.Equal(t, false, ms.At(i).Sum().IsMonotonic()) + assert.Equal(t, pmetric.AggregationTemporalityDelta, ms.At(i).Sum().AggregationTemporality()) + dp := ms.At(i).Sum().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.Equal(t, float64(1), dp.DoubleValue()) + case "optional.metric": + assert.False(t, validatedMetrics["optional.metric"], "Found a duplicate in the metrics slice: optional.metric") + validatedMetrics["optional.metric"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "[DEPRECATED] Gauge double metric disabled by default.", ms.At(i).Description()) + assert.Equal(t, "1", ms.At(i).Unit()) + dp := ms.At(i).Gauge().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.Equal(t, float64(1), dp.DoubleValue()) + attrVal, ok := dp.Attributes().Get("string_attr") + assert.True(t, ok) + assert.EqualValues(t, "string_attr-val", attrVal.Str()) + attrVal, ok = dp.Attributes().Get("boolean_attr") + assert.True(t, ok) + assert.EqualValues(t, true, attrVal.Bool()) + case "optional.metric.empty_unit": + assert.False(t, validatedMetrics["optional.metric.empty_unit"], "Found a duplicate in the metrics slice: optional.metric.empty_unit") + validatedMetrics["optional.metric.empty_unit"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "[DEPRECATED] Gauge double metric disabled by default.", ms.At(i).Description()) + assert.Equal(t, "", ms.At(i).Unit()) + dp := ms.At(i).Gauge().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.Equal(t, float64(1), dp.DoubleValue()) + attrVal, ok := dp.Attributes().Get("string_attr") + assert.True(t, ok) + assert.EqualValues(t, "string_attr-val", attrVal.Str()) + attrVal, ok = dp.Attributes().Get("boolean_attr") + assert.True(t, ok) + assert.EqualValues(t, true, attrVal.Bool()) + } + } + }) + } +} diff --git a/cmd/mdatagen/internal/metadata/generated_resource.go b/cmd/mdatagen/internal/metadata/generated_resource.go new file mode 100644 index 00000000000..da69b3c0841 --- /dev/null +++ b/cmd/mdatagen/internal/metadata/generated_resource.go @@ -0,0 +1,92 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/pdata/pcommon" +) + +// ResourceBuilder is a helper struct to build resources predefined in metadata.yaml. +// The ResourceBuilder is not thread-safe and must not to be used in multiple goroutines. +type ResourceBuilder struct { + config ResourceAttributesConfig + res pcommon.Resource +} + +// NewResourceBuilder creates a new ResourceBuilder. This method should be called on the start of the application. +func NewResourceBuilder(rac ResourceAttributesConfig) *ResourceBuilder { + return &ResourceBuilder{ + config: rac, + res: pcommon.NewResource(), + } +} + +// SetMapResourceAttr sets provided value as "map.resource.attr" attribute. +func (rb *ResourceBuilder) SetMapResourceAttr(val map[string]any) { + if rb.config.MapResourceAttr.Enabled { + rb.res.Attributes().PutEmptyMap("map.resource.attr").FromRaw(val) + } +} + +// SetOptionalResourceAttr sets provided value as "optional.resource.attr" attribute. +func (rb *ResourceBuilder) SetOptionalResourceAttr(val string) { + if rb.config.OptionalResourceAttr.Enabled { + rb.res.Attributes().PutStr("optional.resource.attr", val) + } +} + +// SetSliceResourceAttr sets provided value as "slice.resource.attr" attribute. +func (rb *ResourceBuilder) SetSliceResourceAttr(val []any) { + if rb.config.SliceResourceAttr.Enabled { + rb.res.Attributes().PutEmptySlice("slice.resource.attr").FromRaw(val) + } +} + +// SetStringEnumResourceAttrOne sets "string.enum.resource.attr=one" attribute. +func (rb *ResourceBuilder) SetStringEnumResourceAttrOne() { + if rb.config.StringEnumResourceAttr.Enabled { + rb.res.Attributes().PutStr("string.enum.resource.attr", "one") + } +} + +// SetStringEnumResourceAttrTwo sets "string.enum.resource.attr=two" attribute. +func (rb *ResourceBuilder) SetStringEnumResourceAttrTwo() { + if rb.config.StringEnumResourceAttr.Enabled { + rb.res.Attributes().PutStr("string.enum.resource.attr", "two") + } +} + +// SetStringResourceAttr sets provided value as "string.resource.attr" attribute. +func (rb *ResourceBuilder) SetStringResourceAttr(val string) { + if rb.config.StringResourceAttr.Enabled { + rb.res.Attributes().PutStr("string.resource.attr", val) + } +} + +// SetStringResourceAttrDisableWarning sets provided value as "string.resource.attr_disable_warning" attribute. +func (rb *ResourceBuilder) SetStringResourceAttrDisableWarning(val string) { + if rb.config.StringResourceAttrDisableWarning.Enabled { + rb.res.Attributes().PutStr("string.resource.attr_disable_warning", val) + } +} + +// SetStringResourceAttrRemoveWarning sets provided value as "string.resource.attr_remove_warning" attribute. +func (rb *ResourceBuilder) SetStringResourceAttrRemoveWarning(val string) { + if rb.config.StringResourceAttrRemoveWarning.Enabled { + rb.res.Attributes().PutStr("string.resource.attr_remove_warning", val) + } +} + +// SetStringResourceAttrToBeRemoved sets provided value as "string.resource.attr_to_be_removed" attribute. +func (rb *ResourceBuilder) SetStringResourceAttrToBeRemoved(val string) { + if rb.config.StringResourceAttrToBeRemoved.Enabled { + rb.res.Attributes().PutStr("string.resource.attr_to_be_removed", val) + } +} + +// Emit returns the built resource and resets the internal builder state. +func (rb *ResourceBuilder) Emit() pcommon.Resource { + r := rb.res + rb.res = pcommon.NewResource() + return r +} diff --git a/cmd/mdatagen/internal/metadata/generated_resource_test.go b/cmd/mdatagen/internal/metadata/generated_resource_test.go new file mode 100644 index 00000000000..c0bde40a087 --- /dev/null +++ b/cmd/mdatagen/internal/metadata/generated_resource_test.go @@ -0,0 +1,82 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestResourceBuilder(t *testing.T) { + for _, test := range []string{"default", "all_set", "none_set"} { + t.Run(test, func(t *testing.T) { + cfg := loadResourceAttributesConfig(t, test) + rb := NewResourceBuilder(cfg) + rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"}) + rb.SetOptionalResourceAttr("optional.resource.attr-val") + rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"}) + rb.SetStringEnumResourceAttrOne() + rb.SetStringResourceAttr("string.resource.attr-val") + rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val") + rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val") + rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val") + + res := rb.Emit() + assert.Equal(t, 0, rb.Emit().Attributes().Len()) // Second call should return empty Resource + + switch test { + case "default": + assert.Equal(t, 6, res.Attributes().Len()) + case "all_set": + assert.Equal(t, 8, res.Attributes().Len()) + case "none_set": + assert.Equal(t, 0, res.Attributes().Len()) + return + default: + assert.Failf(t, "unexpected test case: %s", test) + } + + val, ok := res.Attributes().Get("map.resource.attr") + assert.True(t, ok) + if ok { + assert.EqualValues(t, map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"}, val.Map().AsRaw()) + } + val, ok = res.Attributes().Get("optional.resource.attr") + assert.Equal(t, test == "all_set", ok) + if ok { + assert.EqualValues(t, "optional.resource.attr-val", val.Str()) + } + val, ok = res.Attributes().Get("slice.resource.attr") + assert.True(t, ok) + if ok { + assert.EqualValues(t, []any{"slice.resource.attr-item1", "slice.resource.attr-item2"}, val.Slice().AsRaw()) + } + val, ok = res.Attributes().Get("string.enum.resource.attr") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "one", val.Str()) + } + val, ok = res.Attributes().Get("string.resource.attr") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "string.resource.attr-val", val.Str()) + } + val, ok = res.Attributes().Get("string.resource.attr_disable_warning") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "string.resource.attr_disable_warning-val", val.Str()) + } + val, ok = res.Attributes().Get("string.resource.attr_remove_warning") + assert.Equal(t, test == "all_set", ok) + if ok { + assert.EqualValues(t, "string.resource.attr_remove_warning-val", val.Str()) + } + val, ok = res.Attributes().Get("string.resource.attr_to_be_removed") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "string.resource.attr_to_be_removed-val", val.Str()) + } + }) + } +} diff --git a/cmd/mdatagen/internal/metadata/generated_status.go b/cmd/mdatagen/internal/metadata/generated_status.go new file mode 100644 index 00000000000..7e332e5ba4a --- /dev/null +++ b/cmd/mdatagen/internal/metadata/generated_status.go @@ -0,0 +1,29 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("file") + scopeName = "go.opentelemetry.io/collector" +) + +const ( + TracesStability = component.StabilityLevelBeta + LogsStability = component.StabilityLevelDevelopment + MetricsStability = component.StabilityLevelStable +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} diff --git a/cmd/mdatagen/internal/metadata/testdata/config.yaml b/cmd/mdatagen/internal/metadata/testdata/config.yaml new file mode 100644 index 00000000000..8283dc2dd70 --- /dev/null +++ b/cmd/mdatagen/internal/metadata/testdata/config.yaml @@ -0,0 +1,55 @@ +default: +all_set: + metrics: + default.metric: + enabled: true + default.metric.to_be_removed: + enabled: true + optional.metric: + enabled: true + optional.metric.empty_unit: + enabled: true + resource_attributes: + map.resource.attr: + enabled: true + optional.resource.attr: + enabled: true + slice.resource.attr: + enabled: true + string.enum.resource.attr: + enabled: true + string.resource.attr: + enabled: true + string.resource.attr_disable_warning: + enabled: true + string.resource.attr_remove_warning: + enabled: true + string.resource.attr_to_be_removed: + enabled: true +none_set: + metrics: + default.metric: + enabled: false + default.metric.to_be_removed: + enabled: false + optional.metric: + enabled: false + optional.metric.empty_unit: + enabled: false + resource_attributes: + map.resource.attr: + enabled: false + optional.resource.attr: + enabled: false + slice.resource.attr: + enabled: false + string.enum.resource.attr: + enabled: false + string.resource.attr: + enabled: false + string.resource.attr_disable_warning: + enabled: false + string.resource.attr_remove_warning: + enabled: false + string.resource.attr_to_be_removed: + enabled: false diff --git a/cmd/mdatagen/lint.go b/cmd/mdatagen/lint.go new file mode 100644 index 00000000000..f169ac4fdbb --- /dev/null +++ b/cmd/mdatagen/lint.go @@ -0,0 +1,63 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "errors" + "strings" + "unicode" + + "go.opentelemetry.io/collector/cmd/mdatagen/third_party/golint" +) + +// formatIdentifier variable in a go-safe way +func formatIdentifier(s string, exported bool) (string, error) { + if s == "" { + return "", errors.New("string cannot be empty") + } + // Convert various characters to . for strings.Title to operate on. + replace := strings.NewReplacer("_", ".", "-", ".", "<", ".", ">", ".", "/", ".", ":", ".") + str := replace.Replace(s) + str = strings.Title(str) // nolint SA1019 + str = strings.ReplaceAll(str, ".", "") + + var word string + var output string + + // Fixup acronyms to make lint happy. + for idx, r := range str { + if idx == 0 { + if exported { + r = unicode.ToUpper(r) + } else { + r = unicode.ToLower(r) + } + } + + if unicode.IsUpper(r) || unicode.IsNumber(r) { + // If the current word is an acronym and it's either exported or it's not the + // beginning of an unexported variable then upper case it. + if golint.Acronyms[strings.ToUpper(word)] && (exported || output != "") { + output += strings.ToUpper(word) + word = string(r) + } else { + output += word + word = string(r) + } + } else { + word += string(r) + } + } + + if golint.Acronyms[strings.ToUpper(word)] && output != "" { + output += strings.ToUpper(word) + } else { + output += word + } + + // Remove white spaces + output = strings.Join(strings.Fields(output), "") + + return output, nil +} diff --git a/cmd/mdatagen/lint_test.go b/cmd/mdatagen/lint_test.go new file mode 100644 index 00000000000..5c470f302d7 --- /dev/null +++ b/cmd/mdatagen/lint_test.go @@ -0,0 +1,50 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_formatIdentifier(t *testing.T) { + var tests = []struct { + input string + want string + exported bool + wantErr string + }{ + // Unexported. + {input: "max.cpu", want: "maxCPU"}, + {input: "max.foo", want: "maxFoo"}, + {input: "cpu.utilization", want: "cpuUtilization"}, + {input: "cpu", want: "cpu"}, + {input: "max.ip.addr", want: "maxIPAddr"}, + {input: "some_metric", want: "someMetric"}, + {input: "some-metric", want: "someMetric"}, + {input: "Upper.Case", want: "upperCase"}, + {input: "max.ip6", want: "maxIP6"}, + {input: "max.ip6.idle", want: "maxIP6Idle"}, + {input: "node_netstat_IpExt_OutOctets", want: "nodeNetstatIPExtOutOctets"}, + + // Exported. + {input: "cpu.state", want: "CPUState", exported: true}, + + // Errors + {input: "", want: "", wantErr: "string cannot be empty"}, + } + for _, tt := range tests { + t.Run(tt.input, func(t *testing.T) { + got, err := formatIdentifier(tt.input, tt.exported) + + if tt.wantErr != "" { + require.EqualError(t, err, tt.wantErr) + } else { + require.NoError(t, err) + require.Equal(t, tt.want, got) + } + }) + } +} diff --git a/cmd/mdatagen/loader.go b/cmd/mdatagen/loader.go new file mode 100644 index 00000000000..8b4b996a5e2 --- /dev/null +++ b/cmd/mdatagen/loader.go @@ -0,0 +1,300 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "context" + "errors" + "fmt" + "os" + "path/filepath" + "strings" + + "go.opentelemetry.io/collector/confmap" + "go.opentelemetry.io/collector/confmap/provider/fileprovider" + "go.opentelemetry.io/collector/pdata/pcommon" +) + +type metricName string + +func (mn metricName) Render() (string, error) { + return formatIdentifier(string(mn), true) +} + +func (mn metricName) RenderUnexported() (string, error) { + return formatIdentifier(string(mn), false) +} + +type attributeName string + +func (mn attributeName) Render() (string, error) { + return formatIdentifier(string(mn), true) +} + +func (mn attributeName) RenderUnexported() (string, error) { + return formatIdentifier(string(mn), false) +} + +// ValueType defines an attribute value type. +type ValueType struct { + // ValueType is type of the attribute value. + ValueType pcommon.ValueType +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +func (mvt *ValueType) UnmarshalText(text []byte) error { + switch vtStr := string(text); vtStr { + case "string": + mvt.ValueType = pcommon.ValueTypeStr + case "int": + mvt.ValueType = pcommon.ValueTypeInt + case "double": + mvt.ValueType = pcommon.ValueTypeDouble + case "bool": + mvt.ValueType = pcommon.ValueTypeBool + case "bytes": + mvt.ValueType = pcommon.ValueTypeBytes + case "slice": + mvt.ValueType = pcommon.ValueTypeSlice + case "map": + mvt.ValueType = pcommon.ValueTypeMap + default: + return fmt.Errorf("invalid type: %q", vtStr) + } + return nil +} + +// String returns capitalized name of the ValueType. +func (mvt ValueType) String() string { + return strings.Title(strings.ToLower(mvt.ValueType.String())) // nolint SA1019 +} + +// Primitive returns name of primitive type for the ValueType. +func (mvt ValueType) Primitive() string { + switch mvt.ValueType { + case pcommon.ValueTypeStr: + return "string" + case pcommon.ValueTypeInt: + return "int64" + case pcommon.ValueTypeDouble: + return "float64" + case pcommon.ValueTypeBool: + return "bool" + case pcommon.ValueTypeBytes: + return "[]byte" + case pcommon.ValueTypeSlice: + return "[]any" + case pcommon.ValueTypeMap: + return "map[string]any" + case pcommon.ValueTypeEmpty: + return "" + default: + return "" + } +} + +type metric struct { + // Enabled defines whether the metric is enabled by default. + Enabled bool `mapstructure:"enabled"` + + // Warnings that will be shown to user under specified conditions. + Warnings warnings `mapstructure:"warnings"` + + // Description of the metric. + Description string `mapstructure:"description"` + + // ExtendedDocumentation of the metric. If specified, this will + // be appended to the description used in generated documentation. + ExtendedDocumentation string `mapstructure:"extended_documentation"` + + // Unit of the metric. + Unit *string `mapstructure:"unit"` + + // Sum stores metadata for sum metric type + Sum *sum `mapstructure:"sum,omitempty"` + // Gauge stores metadata for gauge metric type + Gauge *gauge `mapstructure:"gauge,omitempty"` + + // Attributes is the list of attributes that the metric emits. + Attributes []attributeName `mapstructure:"attributes"` +} + +func (m *metric) Unmarshal(parser *confmap.Conf) error { + if !parser.IsSet("enabled") { + return errors.New("missing required field: `enabled`") + } + err := parser.Unmarshal(m) + if err != nil { + return err + } + return nil +} +func (m metric) Data() MetricData { + if m.Sum != nil { + return m.Sum + } + if m.Gauge != nil { + return m.Gauge + } + return nil +} + +type warnings struct { + // A warning that will be displayed if the field is enabled in user config. + IfEnabled string `mapstructure:"if_enabled"` + // A warning that will be displayed if `enabled` field is not set explicitly in user config. + IfEnabledNotSet string `mapstructure:"if_enabled_not_set"` + // A warning that will be displayed if the field is configured by user in any way. + IfConfigured string `mapstructure:"if_configured"` +} + +type attribute struct { + // Description describes the purpose of the attribute. + Description string `mapstructure:"description"` + // NameOverride can be used to override the attribute name. + NameOverride string `mapstructure:"name_override"` + // Enabled defines whether the attribute is enabled by default. + Enabled bool `mapstructure:"enabled"` + // Enum can optionally describe the set of values to which the attribute can belong. + Enum []string `mapstructure:"enum"` + // Type is an attribute type. + Type ValueType `mapstructure:"type"` + // FullName is the attribute name populated from the map key. + FullName attributeName `mapstructure:"-"` + // Warnings that will be shown to user under specified conditions. + Warnings warnings `mapstructure:"warnings"` +} + +// Name returns actual name of the attribute that is set on the metric after applying NameOverride. +func (a attribute) Name() attributeName { + if a.NameOverride != "" { + return attributeName(a.NameOverride) + } + return a.FullName +} + +func (a attribute) TestValue() string { + if a.Enum != nil { + return fmt.Sprintf(`"%s"`, a.Enum[0]) + } + switch a.Type.ValueType { + case pcommon.ValueTypeEmpty: + return "" + case pcommon.ValueTypeStr: + return fmt.Sprintf(`"%s-val"`, a.FullName) + case pcommon.ValueTypeInt: + return fmt.Sprintf("%d", len(a.FullName)) + case pcommon.ValueTypeDouble: + return fmt.Sprintf("%f", 0.1+float64(len(a.FullName))) + case pcommon.ValueTypeBool: + return fmt.Sprintf("%t", len(a.FullName)%2 == 0) + case pcommon.ValueTypeMap: + return fmt.Sprintf(`map[string]any{"key1": "%s-val1", "key2": "%s-val2"}`, a.FullName, a.FullName) + case pcommon.ValueTypeSlice: + return fmt.Sprintf(`[]any{"%s-item1", "%s-item2"}`, a.FullName, a.FullName) + case pcommon.ValueTypeBytes: + return fmt.Sprintf(`[]byte("%s-val")`, a.FullName) + } + return "" +} + +type tests struct { + Config any `mapstructure:"config"` + SkipLifecycle bool `mapstructure:"skip_lifecycle"` + ExpectConsumerError bool `mapstructure:"expect_consumer_error"` +} + +type metadata struct { + // Type of the component. + Type string `mapstructure:"type"` + // Type of the parent component (applicable to subcomponents). + Parent string `mapstructure:"parent"` + // Status information for the component. + Status *Status `mapstructure:"status"` + // SemConvVersion is a version number of OpenTelemetry semantic conventions applied to the scraped metrics. + SemConvVersion string `mapstructure:"sem_conv_version"` + // ResourceAttributes that can be emitted by the component. + ResourceAttributes map[attributeName]attribute `mapstructure:"resource_attributes"` + // Attributes emitted by one or more metrics. + Attributes map[attributeName]attribute `mapstructure:"attributes"` + // Metrics that can be emitted by the component. + Metrics map[metricName]metric `mapstructure:"metrics"` + // ScopeName of the metrics emitted by the component. + ScopeName string `mapstructure:"-"` + // ShortFolderName is the shortened folder name of the component, removing class if present + ShortFolderName string `mapstructure:"-"` + + Tests *tests `mapstructure:"tests"` +} + +func setAttributesFullName(attrs map[attributeName]attribute) { + for k, v := range attrs { + v.FullName = k + attrs[k] = v + } +} + +type templateContext struct { + metadata + // Package name for generated code. + Package string +} + +func loadMetadata(filePath string) (metadata, error) { + cp, err := fileprovider.New().Retrieve(context.Background(), "file:"+filePath, nil) + if err != nil { + return metadata{}, err + } + + conf, err := cp.AsConf() + if err != nil { + return metadata{}, err + } + + md := metadata{ScopeName: scopeName(filePath), ShortFolderName: shortFolderName(filePath)} + if err := conf.Unmarshal(&md); err != nil { + return md, err + } + + if err := md.Validate(); err != nil { + return md, err + } + + setAttributesFullName(md.Attributes) + setAttributesFullName(md.ResourceAttributes) + + return md, nil +} + +var componentTypes = []string{ + "connector", + "exporter", + "extension", + "processor", + "scraper", + "receiver", +} + +func shortFolderName(filePath string) string { + parentFolder := filepath.Base(filepath.Dir(filePath)) + for _, cType := range componentTypes { + if strings.HasSuffix(parentFolder, cType) { + return strings.TrimSuffix(parentFolder, cType) + } + } + return parentFolder +} + +func scopeName(filePath string) string { + sn := "go.opentelemetry.io/collector" + dirs := strings.Split(filepath.Dir(filePath), string(os.PathSeparator)) + for _, dir := range dirs { + for _, cType := range componentTypes { + if strings.HasSuffix(dir, cType) { + sn += "/" + dir + } + } + } + return sn +} diff --git a/cmd/mdatagen/loader_test.go b/cmd/mdatagen/loader_test.go new file mode 100644 index 00000000000..aafacc8f252 --- /dev/null +++ b/cmd/mdatagen/loader_test.go @@ -0,0 +1,282 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/pmetric" +) + +func Test_loadMetadata(t *testing.T) { + tests := []struct { + name string + want metadata + wantErr string + }{ + { + name: "metadata-sample.yaml", + want: metadata{ + Type: "file", + SemConvVersion: "1.9.0", + Status: &Status{ + Class: "receiver", + Stability: map[string][]string{ + "development": {"logs"}, + "beta": {"traces"}, + "stable": {"metrics"}, + }, + Distributions: []string{"contrib"}, + Warnings: []string{"Any additional information that should be brought to the consumer's attention"}, + }, + ResourceAttributes: map[attributeName]attribute{ + "string.resource.attr": { + Description: "Resource attribute with any string value.", + Enabled: true, + Type: ValueType{ + ValueType: pcommon.ValueTypeStr, + }, + FullName: "string.resource.attr", + }, + "string.enum.resource.attr": { + Description: "Resource attribute with a known set of string values.", + Enabled: true, + Enum: []string{"one", "two"}, + Type: ValueType{ + ValueType: pcommon.ValueTypeStr, + }, + FullName: "string.enum.resource.attr", + }, + "optional.resource.attr": { + Description: "Explicitly disabled ResourceAttribute.", + Enabled: false, + Type: ValueType{ + ValueType: pcommon.ValueTypeStr, + }, + FullName: "optional.resource.attr", + }, + "slice.resource.attr": { + Description: "Resource attribute with a slice value.", + Enabled: true, + Type: ValueType{ + ValueType: pcommon.ValueTypeSlice, + }, + FullName: "slice.resource.attr", + }, + "map.resource.attr": { + Description: "Resource attribute with a map value.", + Enabled: true, + Type: ValueType{ + ValueType: pcommon.ValueTypeMap, + }, + FullName: "map.resource.attr", + }, + "string.resource.attr_disable_warning": { + Description: "Resource attribute with any string value.", + Warnings: warnings{ + IfEnabledNotSet: "This resource_attribute will be disabled by default soon.", + }, + Enabled: true, + Type: ValueType{ + ValueType: pcommon.ValueTypeStr, + }, + FullName: "string.resource.attr_disable_warning", + }, + "string.resource.attr_remove_warning": { + Description: "Resource attribute with any string value.", + Warnings: warnings{ + IfConfigured: "This resource_attribute is deprecated and will be removed soon.", + }, + Enabled: false, + Type: ValueType{ + ValueType: pcommon.ValueTypeStr, + }, + FullName: "string.resource.attr_remove_warning", + }, + "string.resource.attr_to_be_removed": { + Description: "Resource attribute with any string value.", + Warnings: warnings{ + IfEnabled: "This resource_attribute is deprecated and will be removed soon.", + }, + Enabled: true, + Type: ValueType{ + ValueType: pcommon.ValueTypeStr, + }, + FullName: "string.resource.attr_to_be_removed", + }, + }, + + Attributes: map[attributeName]attribute{ + "enum_attr": { + Description: "Attribute with a known set of string values.", + NameOverride: "", + Enum: []string{"red", "green", "blue"}, + Type: ValueType{ + ValueType: pcommon.ValueTypeStr, + }, + FullName: "enum_attr", + }, + "string_attr": { + Description: "Attribute with any string value.", + NameOverride: "", + Type: ValueType{ + ValueType: pcommon.ValueTypeStr, + }, + FullName: "string_attr", + }, + "overridden_int_attr": { + Description: "Integer attribute with overridden name.", + NameOverride: "state", + Type: ValueType{ + ValueType: pcommon.ValueTypeInt, + }, + FullName: "overridden_int_attr", + }, + "boolean_attr": { + Description: "Attribute with a boolean value.", + Type: ValueType{ + ValueType: pcommon.ValueTypeBool, + }, + FullName: "boolean_attr", + }, + "slice_attr": { + Description: "Attribute with a slice value.", + Type: ValueType{ + ValueType: pcommon.ValueTypeSlice, + }, + FullName: "slice_attr", + }, + "map_attr": { + Description: "Attribute with a map value.", + Type: ValueType{ + ValueType: pcommon.ValueTypeMap, + }, + FullName: "map_attr", + }, + }, + Metrics: map[metricName]metric{ + "default.metric": { + Enabled: true, + Description: "Monotonic cumulative sum int metric enabled by default.", + ExtendedDocumentation: "The metric will be become optional soon.", + Warnings: warnings{ + IfEnabledNotSet: "This metric will be disabled by default soon.", + }, + Unit: strPtr("s"), + Sum: &sum{ + MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeInt}, + AggregationTemporality: AggregationTemporality{Aggregation: pmetric.AggregationTemporalityCumulative}, + Mono: Mono{Monotonic: true}, + }, + Attributes: []attributeName{"string_attr", "overridden_int_attr", "enum_attr", "slice_attr", "map_attr"}, + }, + "optional.metric": { + Enabled: false, + Description: "[DEPRECATED] Gauge double metric disabled by default.", + Warnings: warnings{ + IfConfigured: "This metric is deprecated and will be removed soon.", + }, + Unit: strPtr("1"), + Gauge: &gauge{ + MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeDouble}, + }, + Attributes: []attributeName{"string_attr", "boolean_attr"}, + }, + "optional.metric.empty_unit": { + Enabled: false, + Description: "[DEPRECATED] Gauge double metric disabled by default.", + Warnings: warnings{ + IfConfigured: "This metric is deprecated and will be removed soon.", + }, + Unit: strPtr(""), + Gauge: &gauge{ + MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeDouble}, + }, + Attributes: []attributeName{"string_attr", "boolean_attr"}, + }, + + "default.metric.to_be_removed": { + Enabled: true, + Description: "[DEPRECATED] Non-monotonic delta sum double metric enabled by default.", + ExtendedDocumentation: "The metric will be will be removed soon.", + Warnings: warnings{ + IfEnabled: "This metric is deprecated and will be removed soon.", + }, + Unit: strPtr("s"), + Sum: &sum{ + MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeDouble}, + AggregationTemporality: AggregationTemporality{Aggregation: pmetric.AggregationTemporalityDelta}, + Mono: Mono{Monotonic: false}, + }, + }, + }, + ScopeName: "go.opentelemetry.io/collector", + ShortFolderName: ".", + }, + }, + { + name: "testdata/parent.yaml", + want: metadata{ + Type: "subcomponent", + Parent: "parentComponent", + ScopeName: "go.opentelemetry.io/collector", + ShortFolderName: "testdata", + }, + }, + { + name: "testdata/invalid_type_rattr.yaml", + want: metadata{}, + wantErr: "1 error(s) decoding:\n\n* error decoding 'resource_attributes[string.resource.attr].type': invalid type: \"invalidtype\"", + }, + { + name: "testdata/no_enabled.yaml", + want: metadata{}, + wantErr: "1 error(s) decoding:\n\n* error decoding 'metrics[system.cpu.time]': missing required field: `enabled`", + }, + { + name: "testdata/no_value_type.yaml", + want: metadata{}, + wantErr: "1 error(s) decoding:\n\n* error decoding 'metrics[system.cpu.time]': 1 error(s) decoding:\n\n" + + "* error decoding 'sum': missing required field: `value_type`", + }, + { + name: "testdata/unknown_value_type.yaml", + wantErr: "1 error(s) decoding:\n\n* error decoding 'metrics[system.cpu.time]': 1 error(s) decoding:\n\n* error decoding 'sum': 1 error(s) decoding:\n\n* error decoding 'value_type': invalid value_type: \"unknown\"", + }, + { + name: "testdata/no_aggregation.yaml", + want: metadata{}, + wantErr: "1 error(s) decoding:\n\n* error decoding 'metrics[default.metric]': 1 error(s) decoding:\n\n* error decoding 'sum': missing required field: `aggregation_temporality`", + }, + { + name: "testdata/invalid_aggregation.yaml", + want: metadata{}, + wantErr: "1 error(s) decoding:\n\n* error decoding 'metrics[default.metric]': 1 error(s) decoding:\n\n* error decoding 'sum': 1 error(s) decoding:\n\n* error decoding 'aggregation_temporality': invalid aggregation: \"invalidaggregation\"", + }, + { + name: "testdata/invalid_type_attr.yaml", + want: metadata{}, + wantErr: "1 error(s) decoding:\n\n* error decoding 'attributes[used_attr].type': invalid type: \"invalidtype\"", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := loadMetadata(tt.name) + if tt.wantErr != "" { + require.Error(t, err) + require.EqualError(t, err, tt.wantErr) + } else { + require.NoError(t, err) + require.Equal(t, tt.want, got) + } + }) + } +} + +func strPtr(s string) *string { + return &s +} diff --git a/cmd/mdatagen/main.go b/cmd/mdatagen/main.go new file mode 100644 index 00000000000..4d04bd0696f --- /dev/null +++ b/cmd/mdatagen/main.go @@ -0,0 +1,385 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "bytes" + "errors" + "flag" + "fmt" + "go/format" + "log" + "os" + "path/filepath" + "regexp" + "strings" + "text/template" + + "golang.org/x/text/cases" + "golang.org/x/text/language" +) + +const ( + statusStart = "" + statusEnd = "" +) + +func main() { + flag.Parse() + yml := flag.Arg(0) + if err := run(yml); err != nil { + log.Fatal(err) + } +} + +func run(ymlPath string) error { + if ymlPath == "" { + return errors.New("argument must be metadata.yaml file") + } + ymlPath, err := filepath.Abs(ymlPath) + if err != nil { + return fmt.Errorf("failed to get absolute path for %v: %w", ymlPath, err) + } + + ymlDir := filepath.Dir(ymlPath) + + md, err := loadMetadata(ymlPath) + if err != nil { + return fmt.Errorf("failed loading %v: %w", ymlPath, err) + } + + tmplDir := "templates" + + codeDir := filepath.Join(ymlDir, "internal", "metadata") + if err = os.MkdirAll(codeDir, 0700); err != nil { + return fmt.Errorf("unable to create output directory %q: %w", codeDir, err) + } + if md.Status != nil { + if md.Status.Class != "cmd" && md.Status.Class != "pkg" { + if err = generateFile(filepath.Join(tmplDir, "status.go.tmpl"), + filepath.Join(codeDir, "generated_status.go"), md, "metadata"); err != nil { + return err + } + } + + if _, err = os.Stat(filepath.Join(ymlDir, "README.md")); err == nil { + if err = inlineReplace( + filepath.Join(tmplDir, "readme.md.tmpl"), + filepath.Join(ymlDir, "README.md"), + md, statusStart, statusEnd); err != nil { + return err + } + } + } + + if md.Tests != nil { + if err = generateFile(filepath.Join(tmplDir, "component_test.go.tmpl"), + filepath.Join(ymlDir, "generated_component_test.go"), md, md.ShortFolderName+md.Status.Class); err != nil { + return err + } + } + + if len(md.Metrics) == 0 && len(md.ResourceAttributes) == 0 { + return nil + } + + if err = os.MkdirAll(filepath.Join(codeDir, "testdata"), 0700); err != nil { + return fmt.Errorf("unable to create output directory %q: %w", filepath.Join(codeDir, "testdata"), err) + } + if err = generateFile(filepath.Join(tmplDir, "testdata", "config.yaml.tmpl"), + filepath.Join(codeDir, "testdata", "config.yaml"), md, "metadata"); err != nil { + return err + } + + if err = generateFile(filepath.Join(tmplDir, "config.go.tmpl"), + filepath.Join(codeDir, "generated_config.go"), md, "metadata"); err != nil { + return err + } + if err = generateFile(filepath.Join(tmplDir, "config_test.go.tmpl"), + filepath.Join(codeDir, "generated_config_test.go"), md, "metadata"); err != nil { + return err + } + + if len(md.ResourceAttributes) > 0 { + if err = generateFile(filepath.Join(tmplDir, "resource.go.tmpl"), + filepath.Join(codeDir, "generated_resource.go"), md, "metadata"); err != nil { + return err + } + if err = generateFile(filepath.Join(tmplDir, "resource_test.go.tmpl"), + filepath.Join(codeDir, "generated_resource_test.go"), md, "metadata"); err != nil { + return err + } + } + + if len(md.Metrics) == 0 { + return nil + } + + if err = generateFile(filepath.Join(tmplDir, "metrics.go.tmpl"), + filepath.Join(codeDir, "generated_metrics.go"), md, "metadata"); err != nil { + return err + } + if err = generateFile(filepath.Join(tmplDir, "metrics_test.go.tmpl"), + filepath.Join(codeDir, "generated_metrics_test.go"), md, "metadata"); err != nil { + return err + } + + return generateFile(filepath.Join(tmplDir, "documentation.md.tmpl"), filepath.Join(ymlDir, "documentation.md"), md, "metadata") +} + +func templatize(tmplFile string, md metadata) *template.Template { + return template.Must( + template. + New(filepath.Base(tmplFile)). + Option("missingkey=error"). + Funcs(map[string]any{ + "publicVar": func(s string) (string, error) { + return formatIdentifier(s, true) + }, + "attributeInfo": func(an attributeName) attribute { + return md.Attributes[an] + }, + "metricInfo": func(mn metricName) metric { + return md.Metrics[mn] + }, + "parseImportsRequired": func(metrics map[metricName]metric) bool { + for _, m := range metrics { + if m.Data().HasMetricInputType() { + return true + } + } + return false + }, + "stringsJoin": strings.Join, + "stringsSplit": strings.Split, + "userLinks": func(elems []string) []string { + result := make([]string, len(elems)) + for i, elem := range elems { + if elem == "open-telemetry/collector-approvers" { + result[i] = "[@open-telemetry/collector-approvers](https://github.com/orgs/open-telemetry/teams/collector-approvers)" + } else { + result[i] = fmt.Sprintf("[@%s](https://www.github.com/%s)", elem, elem) + } + } + return result + }, + "casesTitle": cases.Title(language.English).String, + "toCamelCase": func(s string) string { + caser := cases.Title(language.English).String + parts := strings.Split(s, "_") + result := "" + for _, part := range parts { + result += caser(part) + } + return result + }, + "inc": func(i int) int { return i + 1 }, + "distroURL": func(name string) string { + return distros[name] + }, + "isExporter": func() bool { + return md.Status.Class == "exporter" + }, + "isProcessor": func() bool { + return md.Status.Class == "processor" + }, + "isReceiver": func() bool { + return md.Status.Class == "receiver" + }, + "isExtension": func() bool { + return md.Status.Class == "extension" + }, + "isConnector": func() bool { + return md.Status.Class == "connector" + }, + "skipLifecycle": func() bool { + return md.Tests.SkipLifecycle + }, + "supportsLogs": func() bool { + for _, signals := range md.Status.Stability { + for _, s := range signals { + if s == "logs" { + return true + } + } + } + return false + }, + "supportsMetrics": func() bool { + for _, signals := range md.Status.Stability { + for _, s := range signals { + if s == "metrics" { + return true + } + } + } + return false + }, + "supportsTraces": func() bool { + for _, signals := range md.Status.Stability { + for _, s := range signals { + if s == "traces" { + return true + } + } + } + return false + }, + "supportsLogsToLogs": func() bool { + for _, signals := range md.Status.Stability { + for _, s := range signals { + if s == "logs_to_logs" { + return true + } + } + } + return false + }, + "supportsLogsToMetrics": func() bool { + for _, signals := range md.Status.Stability { + for _, s := range signals { + if s == "logs_to_metrics" { + return true + } + } + } + return false + }, + "supportsLogsToTraces": func() bool { + for _, signals := range md.Status.Stability { + for _, s := range signals { + if s == "logs_to_traces" { + return true + } + } + } + return false + }, + "supportsMetricsToLogs": func() bool { + for _, signals := range md.Status.Stability { + for _, s := range signals { + if s == "metrics_to_logs" { + return true + } + } + } + return false + }, + "supportsMetricsToMetrics": func() bool { + for _, signals := range md.Status.Stability { + for _, s := range signals { + if s == "metrics_to_metrics" { + return true + } + } + } + return false + }, + "supportsMetricsToTraces": func() bool { + for _, signals := range md.Status.Stability { + for _, s := range signals { + if s == "metrics_to_traces" { + return true + } + } + } + return false + }, + "supportsTracesToLogs": func() bool { + for _, signals := range md.Status.Stability { + for _, s := range signals { + if s == "traces_to_logs" { + return true + } + } + } + return false + }, + "supportsTracesToMetrics": func() bool { + for _, signals := range md.Status.Stability { + for _, s := range signals { + if s == "traces_to_metrics" { + return true + } + } + } + return false + }, + "supportsTracesToTraces": func() bool { + for _, signals := range md.Status.Stability { + for _, s := range signals { + if s == "traces_to_traces" { + return true + } + } + } + return false + }, + "expectConsumerError": func() bool { + return md.Tests.ExpectConsumerError + }, + // ParseFS delegates the parsing of the files to `Glob` + // which uses the `\` as a special character. + // Meaning on windows based machines, the `\` needs to be replaced + // with a `/` for it to find the file. + }).ParseFS(templateFS, strings.ReplaceAll(tmplFile, "\\", "/"))) +} + +func inlineReplace(tmplFile string, outputFile string, md metadata, start string, end string) error { + var readmeContents []byte + var err error + if readmeContents, err = os.ReadFile(outputFile); err != nil { // nolint: gosec + return err + } + + var re = regexp.MustCompile(fmt.Sprintf("%s[\\s\\S]*%s", start, end)) + if !re.Match(readmeContents) { + return nil + } + + tmpl := templatize(tmplFile, md) + buf := bytes.Buffer{} + + if err := tmpl.Execute(&buf, templateContext{metadata: md, Package: "metadata"}); err != nil { + return fmt.Errorf("failed executing template: %w", err) + } + + result := buf.String() + + s := re.ReplaceAllString(string(readmeContents), result) + if err := os.WriteFile(outputFile, []byte(s), 0600); err != nil { + return fmt.Errorf("failed writing %q: %w", outputFile, err) + } + + return nil +} + +func generateFile(tmplFile string, outputFile string, md metadata, goPackage string) error { + tmpl := templatize(tmplFile, md) + buf := bytes.Buffer{} + + if err := tmpl.Execute(&buf, templateContext{metadata: md, Package: goPackage}); err != nil { + return fmt.Errorf("failed executing template: %w", err) + } + + if err := os.Remove(outputFile); err != nil && !errors.Is(err, os.ErrNotExist) { + return fmt.Errorf("unable to remove genererated file %q: %w", outputFile, err) + } + + result := buf.Bytes() + var formatErr error + if strings.HasSuffix(outputFile, ".go") { + if formatted, err := format.Source(buf.Bytes()); err == nil { + result = formatted + } else { + formatErr = fmt.Errorf("failed formatting %s:%w", outputFile, err) + } + } + + if err := os.WriteFile(outputFile, result, 0600); err != nil { + return fmt.Errorf("failed writing %q: %w", outputFile, err) + } + + return formatErr +} diff --git a/cmd/mdatagen/main_test.go b/cmd/mdatagen/main_test.go new file mode 100644 index 00000000000..df3387fd167 --- /dev/null +++ b/cmd/mdatagen/main_test.go @@ -0,0 +1,461 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "bytes" + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + + md "go.opentelemetry.io/collector/cmd/mdatagen/internal/metadata" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +func Test_runContents(t *testing.T) { + tests := []struct { + yml string + wantMetricsGenerated bool + wantConfigGenerated bool + wantStatusGenerated bool + wantTestsGenerated bool + wantErr bool + }{ + { + yml: "invalid.yaml", + wantErr: true, + }, + { + yml: "metrics_and_type.yaml", + wantMetricsGenerated: true, + wantConfigGenerated: true, + wantStatusGenerated: true, + }, + { + yml: "resource_attributes_only.yaml", + wantConfigGenerated: true, + wantStatusGenerated: true, + }, + { + yml: "status_only.yaml", + wantStatusGenerated: true, + }, + { + yml: "with_tests_receiver.yaml", + wantTestsGenerated: true, + wantStatusGenerated: true, + }, + { + yml: "with_tests_exporter.yaml", + wantTestsGenerated: true, + wantStatusGenerated: true, + }, + { + yml: "with_tests_processor.yaml", + wantTestsGenerated: true, + wantStatusGenerated: true, + }, + { + yml: "with_tests_extension.yaml", + wantTestsGenerated: true, + wantStatusGenerated: true, + }, + { + yml: "with_tests_connector.yaml", + wantTestsGenerated: true, + wantStatusGenerated: true, + }, + } + for _, tt := range tests { + t.Run(tt.yml, func(t *testing.T) { + tmpdir := filepath.Join(t.TempDir(), "shortname") + err := os.MkdirAll(tmpdir, 0750) + require.NoError(t, err) + ymlContent, err := os.ReadFile(filepath.Join("testdata", tt.yml)) + require.NoError(t, err) + metadataFile := filepath.Join(tmpdir, "metadata.yaml") + require.NoError(t, os.WriteFile(metadataFile, ymlContent, 0600)) + require.NoError(t, os.WriteFile(filepath.Join(tmpdir, "README.md"), []byte(` + +foo +`), 0600)) + + err = run(metadataFile) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + + if tt.wantMetricsGenerated { + require.FileExists(t, filepath.Join(tmpdir, "internal/metadata/generated_metrics.go")) + require.FileExists(t, filepath.Join(tmpdir, "internal/metadata/generated_metrics_test.go")) + require.FileExists(t, filepath.Join(tmpdir, "documentation.md")) + } else { + require.NoFileExists(t, filepath.Join(tmpdir, "internal/metadata/generated_metrics.go")) + require.NoFileExists(t, filepath.Join(tmpdir, "internal/metadata/generated_metrics_test.go")) + require.NoFileExists(t, filepath.Join(tmpdir, "documentation.md")) + } + + if tt.wantConfigGenerated { + require.FileExists(t, filepath.Join(tmpdir, "internal/metadata/generated_config.go")) + require.FileExists(t, filepath.Join(tmpdir, "internal/metadata/generated_config_test.go")) + } else { + require.NoFileExists(t, filepath.Join(tmpdir, "internal/metadata/generated_config.go")) + require.NoFileExists(t, filepath.Join(tmpdir, "internal/metadata/generated_config_test.go")) + } + + if tt.wantStatusGenerated { + require.FileExists(t, filepath.Join(tmpdir, "internal/metadata/generated_status.go")) + contents, err := os.ReadFile(filepath.Join(tmpdir, "README.md")) // nolint: gosec + require.NoError(t, err) + require.NotContains(t, string(contents), "foo") + } else { + require.NoFileExists(t, filepath.Join(tmpdir, "internal/metadata/generated_status.go")) + contents, err := os.ReadFile(filepath.Join(tmpdir, "README.md")) // nolint: gosec + require.NoError(t, err) + require.Contains(t, string(contents), "foo") + } + + if tt.wantTestsGenerated { + require.FileExists(t, filepath.Join(tmpdir, "generated_component_test.go")) + contents, err := os.ReadFile(filepath.Join(tmpdir, "generated_component_test.go")) // nolint: gosec + require.NoError(t, err) + require.Contains(t, string(contents), "func Test") + } else { + require.NoFileExists(t, filepath.Join(tmpdir, "generated_component_test.go")) + } + }) + } +} + +func Test_run(t *testing.T) { + type args struct { + ymlPath string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "no argument", + args: args{""}, + wantErr: true, + }, + { + name: "no such file", + args: args{"/no/such/file"}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := run(tt.args.ymlPath); (err != nil) != tt.wantErr { + t.Errorf("run() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_inlineReplace(t *testing.T) { + tests := []struct { + name string + markdown string + outputFile string + componentClass string + warnings []string + stability map[string][]string + distros []string + codeowners *Codeowners + }{ + { + name: "readme with empty status", + markdown: `# Some component + + + + +Some info about a component +`, + outputFile: "readme_with_status.md", + componentClass: "receiver", + distros: []string{"contrib"}, + }, + { + name: "readme with status for extension", + markdown: `# Some component + + + + +Some info about a component +`, + outputFile: "readme_with_status_extension.md", + componentClass: "extension", + distros: []string{"contrib"}, + }, + { + name: "readme with status with codeowners and seeking new", + markdown: `# Some component + + + + +Some info about a component +`, + outputFile: "readme_with_status_codeowners_and_seeking_new.md", + componentClass: "receiver", + distros: []string{"contrib"}, + codeowners: &Codeowners{ + Active: []string{"foo"}, + SeekingNew: true, + }, + }, + { + name: "readme with status with codeowners and emeritus", + markdown: `# Some component + + + + +Some info about a component +`, + outputFile: "readme_with_status_codeowners_and_emeritus.md", + componentClass: "receiver", + distros: []string{"contrib"}, + codeowners: &Codeowners{ + Active: []string{"foo"}, + Emeritus: []string{"bar"}, + }, + }, + { + name: "readme with status with codeowners", + markdown: `# Some component + + + + +Some info about a component +`, + outputFile: "readme_with_status_codeowners.md", + componentClass: "receiver", + distros: []string{"contrib"}, + codeowners: &Codeowners{ + Active: []string{"foo"}, + }, + }, + { + name: "readme with status table", + markdown: `# Some component + + +| Status | | +| ------------------------ |-----------| + + +Some info about a component +`, + outputFile: "readme_with_status.md", + componentClass: "receiver", + distros: []string{"contrib"}, + }, + { + name: "readme with no status", + markdown: `# Some component + +Some info about a component +`, + outputFile: "readme_without_status.md", + distros: []string{"contrib"}, + }, + { + name: "component with warnings", + markdown: `# Some component + + + + +Some info about a component +### warnings +Some warning there. +`, + outputFile: "readme_with_warnings.md", + warnings: []string{"warning1"}, + distros: []string{"contrib"}, + }, + { + name: "readme with multiple signals", + markdown: `# Some component + + + + +Some info about a component +`, + outputFile: "readme_with_multiple_signals.md", + stability: map[string][]string{"beta": {"metrics"}, "alpha": {"logs"}}, + distros: []string{"contrib"}, + }, + { + name: "readme with cmd class", + markdown: `# Some component + + + + +Some info about a component +`, + outputFile: "readme_with_cmd_class.md", + stability: map[string][]string{"beta": {"metrics"}, "alpha": {"logs"}}, + componentClass: "cmd", + distros: []string{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + stability := map[string][]string{"beta": {"metrics"}} + if len(tt.stability) > 0 { + stability = tt.stability + } + md := metadata{ + Type: "foo", + ShortFolderName: "foo", + Status: &Status{ + Stability: stability, + Distributions: tt.distros, + Class: tt.componentClass, + Warnings: tt.warnings, + Codeowners: tt.codeowners, + }, + } + tmpdir := t.TempDir() + + readmeFile := filepath.Join(tmpdir, "README.md") + require.NoError(t, os.WriteFile(readmeFile, []byte(tt.markdown), 0600)) + + err := inlineReplace("templates/readme.md.tmpl", readmeFile, md, statusStart, statusEnd) + require.NoError(t, err) + + require.FileExists(t, filepath.Join(tmpdir, "README.md")) + got, err := os.ReadFile(filepath.Join(tmpdir, "README.md")) // nolint: gosec + require.NoError(t, err) + got = bytes.ReplaceAll(got, []byte("\r\n"), []byte("\n")) + expected, err := os.ReadFile(filepath.Join("testdata", tt.outputFile)) + require.NoError(t, err) + expected = bytes.ReplaceAll(expected, []byte("\r\n"), []byte("\n")) + fmt.Println(string(got)) + fmt.Println(string(expected)) + require.Equal(t, string(expected), string(got)) + }) + } +} + +func TestGenerateStatusMetadata(t *testing.T) { + tests := []struct { + name string + output string + md metadata + expected string + }{ + { + name: "foo component with beta status", + md: metadata{ + Type: "foo", + Status: &Status{ + Stability: map[string][]string{"beta": {"metrics"}}, + Distributions: []string{"contrib"}, + Class: "receiver", + }, + }, + expected: `// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" +) + +var ( + Type = component.MustNewType("foo") + scopeName = "" +) + +const ( + MetricsStability = component.StabilityLevelBeta +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} +`, + }, + { + name: "foo component with alpha status", + md: metadata{ + Type: "foo", + Status: &Status{ + Stability: map[string][]string{"alpha": {"metrics"}}, + Distributions: []string{"contrib"}, + Class: "receiver", + }, + }, + expected: `// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" +) + +var ( + Type = component.MustNewType("foo") + scopeName = "" +) + +const ( + MetricsStability = component.StabilityLevelAlpha +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} +`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tmpdir := t.TempDir() + err := generateFile("templates/status.go.tmpl", + filepath.Join(tmpdir, "generated_status.go"), tt.md, "metadata") + require.NoError(t, err) + actual, err := os.ReadFile(filepath.Join(tmpdir, "generated_status.go")) // nolint: gosec + require.NoError(t, err) + require.Equal(t, tt.expected, string(actual)) + }) + } +} + +// TestGenerated verifies that the internal/metadata API is generated correctly. +func TestGenerated(t *testing.T) { + mb := md.NewMetricsBuilder(md.DefaultMetricsBuilderConfig(), receivertest.NewNopCreateSettings()) + m := mb.Emit() + require.Equal(t, 0, m.ResourceMetrics().Len()) +} diff --git a/cmd/mdatagen/metadata-sample.yaml b/cmd/mdatagen/metadata-sample.yaml new file mode 100644 index 00000000000..b9a5f8f6c90 --- /dev/null +++ b/cmd/mdatagen/metadata-sample.yaml @@ -0,0 +1,136 @@ +# Sample metric metadata file with all available configurations. + +type: file + +sem_conv_version: 1.9.0 + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + distributions: [contrib] + warnings: + - Any additional information that should be brought to the consumer's attention + +resource_attributes: + string.resource.attr: + description: Resource attribute with any string value. + type: string + enabled: true + + string.enum.resource.attr: + description: Resource attribute with a known set of string values. + type: string + enum: [one, two] + enabled: true + + optional.resource.attr: + description: Explicitly disabled ResourceAttribute. + type: string + enabled: false + + slice.resource.attr: + description: Resource attribute with a slice value. + type: slice + enabled: true + + map.resource.attr: + description: Resource attribute with a map value. + type: map + enabled: true + + string.resource.attr_disable_warning: + description: Resource attribute with any string value. + type: string + enabled: true + warnings: + if_enabled_not_set: This resource_attribute will be disabled by default soon. + + string.resource.attr_remove_warning: + description: Resource attribute with any string value. + type: string + enabled: false + warnings: + if_configured: This resource_attribute is deprecated and will be removed soon. + + string.resource.attr_to_be_removed: + description: Resource attribute with any string value. + type: string + enabled: true + warnings: + if_enabled: This resource_attribute is deprecated and will be removed soon. + +attributes: + string_attr: + description: Attribute with any string value. + type: string + + overridden_int_attr: + name_override: state + description: Integer attribute with overridden name. + type: int + + enum_attr: + description: Attribute with a known set of string values. + type: string + enum: [red, green, blue] + + boolean_attr: + description: Attribute with a boolean value. + type: bool + + slice_attr: + description: Attribute with a slice value. + type: slice + + map_attr: + description: Attribute with a map value. + type: map + +metrics: + default.metric: + enabled: true + description: Monotonic cumulative sum int metric enabled by default. + extended_documentation: The metric will be become optional soon. + unit: s + sum: + value_type: int + monotonic: true + aggregation_temporality: cumulative + attributes: [string_attr, overridden_int_attr, enum_attr, slice_attr, map_attr] + warnings: + if_enabled_not_set: This metric will be disabled by default soon. + + optional.metric: + enabled: false + description: "[DEPRECATED] Gauge double metric disabled by default." + unit: 1 + gauge: + value_type: double + attributes: [string_attr, boolean_attr] + warnings: + if_configured: This metric is deprecated and will be removed soon. + + optional.metric.empty_unit: + enabled: false + description: "[DEPRECATED] Gauge double metric disabled by default." + unit: "" + gauge: + value_type: double + attributes: [string_attr, boolean_attr] + warnings: + if_configured: This metric is deprecated and will be removed soon. + + default.metric.to_be_removed: + enabled: true + description: "[DEPRECATED] Non-monotonic delta sum double metric enabled by default." + extended_documentation: The metric will be will be removed soon. + unit: s + sum: + value_type: double + monotonic: false + aggregation_temporality: delta + warnings: + if_enabled: This metric is deprecated and will be removed soon. diff --git a/cmd/mdatagen/metadata-schema.yaml b/cmd/mdatagen/metadata-schema.yaml new file mode 100644 index 00000000000..879307fdd3d --- /dev/null +++ b/cmd/mdatagen/metadata-schema.yaml @@ -0,0 +1,113 @@ +# Required: The type of the component - Usually the name. The type and class combined uniquely identify the component (eg. receiver/otlp) or subcomponent (eg. receiver/hostmetricsreceiver/cpu) +type: + +# Required for subcomponents: The type of the parent component. +parent: string + +# Required for components (Optional for subcomponents): A high-level view of the development status and use of this component +status: + # Required: The class of the component (For example receiver) + class: + # Required: The stability of the component - See https://github.com/open-telemetry/opentelemetry-collector#stability-levels + stability: + development: [] + alpha: [] + beta: [] + stable: [] + deprecated: [] + unmaintained: [] + # Optional: The distributions that this component is bundled with (For example core or contrib). See statusdata.go for a list of common distros. + distributions: [string] + # Optional: A list of warnings that should be brought to the attention of users looking to use this component + warnings: [string] + # Optional: Metadata related to codeowners of the component + codeowners: + active: [string] + emeritus: [string] + unsupported_platforms: [] + +# Optional: OTel Semantic Conventions version that will be associated with the scraped metrics. +# This attribute should be set for metrics compliant with OTel Semantic Conventions. +sem_conv_version: 1.9.0 + +# Optional: map of resource attribute definitions with the key being the attribute name. +resource_attributes: + : + # Required: whether the resource attribute is added the emitted metrics by default. + enabled: bool + # Required: description of the attribute. + description: + # Optional: array of attribute values if they are static values (currently, only string type is supported). + enum: [string] + # Required: attribute value type. + type: + # Optional: warnings that will be shown to user under specified conditions. + warnings: + # A warning that will be displayed if the resource_attribute is enabled in user config. + # Should be used for deprecated default resource_attributes that will be removed soon. + if_enabled: + # A warning that will be displayed if `enabled` field is not set explicitly in user config. + # Should be used for resource_attributes that will be turned from default to optional or vice versa. + if_enabled_not_set: + # A warning that will be displayed if the resource_attribute is configured by user in any way. + # Should be used for deprecated optional resource_attributes that will be removed soon. + if_configured: + + +# Optional: map of attribute definitions with the key being the attribute name and value +# being described below. +attributes: + : + # Optional: this field can be used to override the actual attribute name defined by the key. + # It should be used if multiple metrics have different attributes with the same name. + name_override: + # Required: description of the attribute. + description: + # Optional: array of attribute values if they are static values (currently, only string type is supported). + enum: [string] + # Required: attribute value type. + type: + +# Optional: map of metric names with the key being the metric name and value +# being described below. +metrics: + : + # Required: whether the metric is collected by default. + enabled: bool + # Required: metric description. + description: + # Optional: extended documentation of the metric. + extended_documentation: + # Optional: warnings that will be shown to user under specified conditions. + warnings: + # A warning that will be displayed if the metric is enabled in user config. + # Should be used for deprecated default metrics that will be removed soon. + if_enabled: + # A warning that will be displayed if `enabled` field is not set explicitly in user config. + # Should be used for metrics that will be turned from default to optional or vice versa. + if_enabled_not_set: + # A warning that will be displayed if the metrics is configured by user in any way. + # Should be used for deprecated optional metrics that will be removed soon. + if_configured: + # Required: metric unit as defined by https://ucum.org/ucum.html. + unit: + # Required: metric type with its settings. + : + # Required for sum and gauge metrics: type of number data point values. + value_type: + # Required for sum metric: whether the metric is monotonic (no negative delta values). + monotonic: bool + # Required for sum metric: whether reported values incorporate previous measurements + # (cumulative) or not (delta). + aggregation_temporality: + # Optional: Indicates the type the metric needs to be parsed from. If set, the generated + # functions will parse the value from string to value_type. + input_type: string + # Optional: array of attributes that were defined in the attributes section that are emitted by this metric. + attributes: [string] + +# Lifecycle tests generated for this component. +tests: + config: # {} by default, specific testing configuration for lifecycle tests. + skip_lifecycle: false # false by default + expect_consumer_error: true # false by default diff --git a/cmd/mdatagen/metadata.yaml b/cmd/mdatagen/metadata.yaml new file mode 100644 index 00000000000..65bb097a962 --- /dev/null +++ b/cmd/mdatagen/metadata.yaml @@ -0,0 +1,6 @@ +type: mdatagen + +status: + class: cmd + codeowners: + active: [dmitryax] \ No newline at end of file diff --git a/cmd/mdatagen/metricdata.go b/cmd/mdatagen/metricdata.go new file mode 100644 index 00000000000..f4515136aae --- /dev/null +++ b/cmd/mdatagen/metricdata.go @@ -0,0 +1,182 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "errors" + "fmt" + + "go.opentelemetry.io/collector/confmap" + "go.opentelemetry.io/collector/pdata/pmetric" +) + +var ( + _ MetricData = &gauge{} + _ MetricData = &sum{} +) + +// MetricData is generic interface for all metric datatypes. +type MetricData interface { + Type() string + HasMonotonic() bool + HasAggregated() bool + HasMetricInputType() bool +} + +// AggregationTemporality defines a metric aggregation type. +type AggregationTemporality struct { + // Aggregation describes if the aggregator reports delta changes + // since last report time, or cumulative changes since a fixed start time. + Aggregation pmetric.AggregationTemporality +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +func (agg *AggregationTemporality) UnmarshalText(text []byte) error { + switch vtStr := string(text); vtStr { + case "cumulative": + agg.Aggregation = pmetric.AggregationTemporalityCumulative + case "delta": + agg.Aggregation = pmetric.AggregationTemporalityDelta + default: + return fmt.Errorf("invalid aggregation: %q", vtStr) + } + return nil +} + +// String returns string representation of the aggregation temporality. +func (agg *AggregationTemporality) String() string { + return agg.Aggregation.String() +} + +// Mono defines the metric monotonicity. +type Mono struct { + // Monotonic is true if the sum is monotonic. + Monotonic bool `mapstructure:"monotonic"` +} + +// MetricInputType defines the metric input value type +type MetricInputType struct { + // InputType is the type the metric needs to be parsed from, options are "string" + InputType string `mapstructure:"input_type"` +} + +func (mit MetricInputType) HasMetricInputType() bool { + return mit.InputType != "" +} + +// Type returns name of the datapoint type. +func (mit MetricInputType) String() string { + return mit.InputType +} + +// MetricValueType defines the metric number type. +type MetricValueType struct { + // ValueType is type of the metric number, options are "double", "int". + ValueType pmetric.NumberDataPointValueType +} + +func (mvt *MetricValueType) Unmarshal(parser *confmap.Conf) error { + if !parser.IsSet("value_type") { + return errors.New("missing required field: `value_type`") + } + return nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +func (mvt *MetricValueType) UnmarshalText(text []byte) error { + switch vtStr := string(text); vtStr { + case "int": + mvt.ValueType = pmetric.NumberDataPointValueTypeInt + case "double": + mvt.ValueType = pmetric.NumberDataPointValueTypeDouble + default: + return fmt.Errorf("invalid value_type: %q", vtStr) + } + return nil +} + +// Type returns name of the datapoint type. +func (mvt MetricValueType) String() string { + return mvt.ValueType.String() +} + +// BasicType returns name of a golang basic type for the datapoint type. +func (mvt MetricValueType) BasicType() string { + switch mvt.ValueType { + case pmetric.NumberDataPointValueTypeInt: + return "int64" + case pmetric.NumberDataPointValueTypeDouble: + return "float64" + case pmetric.NumberDataPointValueTypeEmpty: + return "" + default: + return "" + } +} + +type gauge struct { + MetricValueType `mapstructure:"value_type"` + MetricInputType `mapstructure:",squash"` +} + +// Unmarshal is a custom unmarshaler for gauge. Needed mostly to avoid MetricValueType.Unmarshal inheritance. +func (d *gauge) Unmarshal(parser *confmap.Conf) error { + if err := d.MetricValueType.Unmarshal(parser); err != nil { + return err + } + return parser.Unmarshal(d) +} + +func (d gauge) Type() string { + return "Gauge" +} + +func (d gauge) HasMonotonic() bool { + return false +} + +func (d gauge) HasAggregated() bool { + return false +} + +type sum struct { + AggregationTemporality `mapstructure:"aggregation_temporality"` + Mono `mapstructure:",squash"` + MetricValueType `mapstructure:"value_type"` + MetricInputType `mapstructure:",squash"` +} + +// Unmarshal is a custom unmarshaler for sum. Needed mostly to avoid MetricValueType.Unmarshal inheritance. +func (d *sum) Unmarshal(parser *confmap.Conf) error { + if !parser.IsSet("aggregation_temporality") { + return errors.New("missing required field: `aggregation_temporality`") + } + if err := d.MetricValueType.Unmarshal(parser); err != nil { + return err + } + return parser.Unmarshal(d) +} + +// TODO: Currently, this func will not be called because of https://github.com/open-telemetry/opentelemetry-collector/issues/6671. Uncomment function and +// add a test case to Test_loadMetadata for file no_monotonic.yaml once the issue is solved. +// +// Unmarshal is a custom unmarshaler for Mono. +// func (m *Mono) Unmarshal(parser *confmap.Conf) error { +// if !parser.IsSet("monotonic") { +// return errors.New("missing required field: `monotonic`") +// } +// return parser.Unmarshal(m) +// } + +func (d sum) Type() string { + return "Sum" +} + +func (d sum) HasMonotonic() bool { + return true +} + +func (d sum) HasAggregated() bool { + return true +} diff --git a/cmd/mdatagen/metricdata_test.go b/cmd/mdatagen/metricdata_test.go new file mode 100644 index 00000000000..10b7f46613e --- /dev/null +++ b/cmd/mdatagen/metricdata_test.go @@ -0,0 +1,26 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMetricData(t *testing.T) { + for _, arg := range []struct { + metricData MetricData + typ string + hasAggregated bool + hasMonotonic bool + }{ + {&gauge{}, "Gauge", false, false}, + {&sum{}, "Sum", true, true}, + } { + assert.Equal(t, arg.typ, arg.metricData.Type()) + assert.Equal(t, arg.hasAggregated, arg.metricData.HasAggregated()) + assert.Equal(t, arg.hasMonotonic, arg.metricData.HasMonotonic()) + } +} diff --git a/cmd/mdatagen/statusdata.go b/cmd/mdatagen/statusdata.go new file mode 100644 index 00000000000..d65a5c20f58 --- /dev/null +++ b/cmd/mdatagen/statusdata.go @@ -0,0 +1,62 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "sort" +) + +// distros is a collection of distributions that can be referenced in the metadata.yaml files. +// The rules below apply to every distribution added to this list: +// - The distribution must be open source. +// - The link must point to a publicly accessible repository. +var distros = map[string]string{ + "core": "https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol", + "contrib": "https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib", + "aws": "https://github.com/aws-observability/aws-otel-collector", + "grafana": "https://github.com/grafana/agent", + "observiq": "https://github.com/observIQ/observiq-otel-collector", + "redhat": "https://github.com/os-observability/redhat-opentelemetry-collector", + "splunk": "https://github.com/signalfx/splunk-otel-collector", + "sumo": "https://github.com/SumoLogic/sumologic-otel-collector", + "liatrio": "https://github.com/liatrio/liatrio-otel-collector", +} + +type Codeowners struct { + // Active codeowners + Active []string `mapstructure:"active"` + // Emeritus codeowners + Emeritus []string `mapstructure:"emeritus"` + // Whether new codeowners are being sought + SeekingNew bool `mapstructure:"seeking_new"` +} + +type Status struct { + Stability map[string][]string `mapstructure:"stability"` + Distributions []string `mapstructure:"distributions"` + Class string `mapstructure:"class"` + Warnings []string `mapstructure:"warnings"` + Codeowners *Codeowners `mapstructure:"codeowners"` + UnsupportedPlatforms []string `mapstructure:"unsupported_platforms"` +} + +func (s *Status) SortedDistributions() []string { + sorted := s.Distributions + sort.Slice(sorted, func(i, j int) bool { + if s.Distributions[i] == "core" { + return true + } + if s.Distributions[i] == "contrib" { + return s.Distributions[j] != "core" + } + if s.Distributions[j] == "core" { + return false + } + if s.Distributions[j] == "contrib" { + return s.Distributions[i] == "core" + } + return s.Distributions[i] < s.Distributions[j] + }) + return sorted +} diff --git a/cmd/mdatagen/statusdata_test.go b/cmd/mdatagen/statusdata_test.go new file mode 100644 index 00000000000..947065b1d6f --- /dev/null +++ b/cmd/mdatagen/statusdata_test.go @@ -0,0 +1,59 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSortedDistributions(t *testing.T) { + tests := []struct { + name string + s Status + result []string + }{ + { + "all combined", + Status{Distributions: []string{"arm", "contrib", "core", "foo", "bar"}}, + []string{"core", "contrib", "arm", "bar", "foo"}, + }, + { + "core only", + Status{Distributions: []string{"core"}}, + []string{"core"}, + }, + { + "core and contrib only", + Status{Distributions: []string{"core", "contrib"}}, + []string{"core", "contrib"}, + }, + { + "core and contrib reversed", + Status{Distributions: []string{"contrib", "core"}}, + []string{"core", "contrib"}, + }, + { + "neither core nor contrib", + Status{Distributions: []string{"foo", "bar"}}, + []string{"bar", "foo"}, + }, + { + "no core, contrib, something else", + Status{Distributions: []string{"foo", "contrib", "bar"}}, + []string{"contrib", "bar", "foo"}, + }, + { + "core, no contrib, something else", + Status{Distributions: []string{"foo", "core", "bar"}}, + []string{"core", "bar", "foo"}, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.result, test.s.SortedDistributions()) + }) + } +} diff --git a/cmd/mdatagen/templates/component_test.go.tmpl b/cmd/mdatagen/templates/component_test.go.tmpl new file mode 100644 index 00000000000..3c82b1ed2d2 --- /dev/null +++ b/cmd/mdatagen/templates/component_test.go.tmpl @@ -0,0 +1,448 @@ +// Code generated by mdatagen. DO NOT EDIT. + +{{ if len .Status.UnsupportedPlatforms -}} +//go:build {{ range $i, $v := .Status.UnsupportedPlatforms }}{{ if $i }} && {{ end }}!{{ . }}{{ end }} +{{- end }} + +package {{ .Package }} + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" +{{ if isExporter }} + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exportertest" +{{ end }} +{{ if isProcessor }} + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/processor" + "go.opentelemetry.io/collector/processor/processortest" +{{ end }} +{{ if isReceiver }} + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/receiver" + "go.opentelemetry.io/collector/receiver/receivertest" +{{ end }} +{{ if isExtension }} + "go.opentelemetry.io/collector/extension/extensiontest" +{{ end }} +{{ if isConnector }} + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/connector" + "go.opentelemetry.io/collector/connector/connectortest" +{{ end }} + "go.opentelemetry.io/collector/confmap/confmaptest" +{{ if or (isExporter) (isProcessor) }} + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/testdata" +{{ end }} +) + +func TestCheckConfigStruct(t *testing.T) { + componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig()) +} + +{{ if isExporter }} +func TestComponentLifecycle(t *testing.T) { + factory := NewFactory() + + tests := []struct{ + name string + createFn func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) + }{ +{{ if supportsLogs }} + { + name: "logs", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsExporter(ctx, set, cfg) + }, + }, +{{ end }} +{{ if supportsMetrics }} + { + name: "metrics", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsExporter(ctx, set, cfg) + }, + }, +{{ end }} +{{ if supportsTraces }} + { + name: "traces", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesExporter(ctx, set, cfg) + }, + }, +{{ end }} + } + + cm, err := confmaptest.LoadConf("metadata.yaml") + require.NoError(t, err) + cfg := factory.CreateDefaultConfig() + sub, err := cm.Sub("tests::config") + require.NoError(t, err) + require.NoError(t, component.UnmarshalConfig(sub, cfg)) + + for _, test := range tests { + t.Run(test.name + "-shutdown", func(t *testing.T) { + c, err := test.createFn(context.Background(), exportertest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + err = c.Shutdown(context.Background()) + require.NoError(t, err) + }) + + t.Run(test.name + "-lifecycle", func(t *testing.T) { + {{ if skipLifecycle }} + // TODO support lifecycle + t.SkipNow() + {{ end }} + c, err := test.createFn(context.Background(), exportertest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + host := componenttest.NewNopHost() + err = c.Start(context.Background(), host) + require.NoError(t, err) + require.NotPanics(t, func() { + switch e := c.(type) { + case exporter.Logs: + logs := testdata.GenerateLogsManyLogRecordsSameResource(2) + if !e.Capabilities().MutatesData { + logs.MarkReadOnly() + } + err = e.ConsumeLogs(context.Background(), logs) + case exporter.Metrics: + metrics := testdata.GenerateMetricsTwoMetrics() + if !e.Capabilities().MutatesData { + metrics.MarkReadOnly() + } + err = e.ConsumeMetrics(context.Background(), metrics) + case exporter.Traces: + traces := testdata.GenerateTracesTwoSpansSameResource() + if !e.Capabilities().MutatesData { + traces.MarkReadOnly() + } + err = e.ConsumeTraces(context.Background(), traces) + } + }) + {{ if not expectConsumerError }} + require.NoError(t, err) + {{ end }} + err = c.Shutdown(context.Background()) + require.NoError(t, err) + }) + } +} +{{ end }} + +{{ if isProcessor }} +func TestComponentLifecycle(t *testing.T) { + factory := NewFactory() + + tests := []struct{ + name string + createFn func(ctx context.Context, set processor.CreateSettings, cfg component.Config) (component.Component, error) + }{ +{{ if supportsLogs }} + { + name: "logs", + createFn: func(ctx context.Context, set processor.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsProcessor(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} +{{ if supportsMetrics }} + { + name: "metrics", + createFn: func(ctx context.Context, set processor.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsProcessor(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} +{{ if supportsTraces }} + { + name: "traces", + createFn: func(ctx context.Context, set processor.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesProcessor(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} + } + + cm, err := confmaptest.LoadConf("metadata.yaml") + require.NoError(t, err) + cfg := factory.CreateDefaultConfig() + sub, err := cm.Sub("tests::config") + require.NoError(t, err) + require.NoError(t, component.UnmarshalConfig(sub, cfg)) + + for _, test := range tests { + t.Run(test.name + "-shutdown", func(t *testing.T) { + c, err := test.createFn(context.Background(), processortest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + err = c.Shutdown(context.Background()) + require.NoError(t, err) + }) + + t.Run(test.name + "-lifecycle", func(t *testing.T) { + {{ if skipLifecycle }} + // TODO support lifecycle + t.SkipNow() + {{ end }} + c, err := test.createFn(context.Background(), processortest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + host := componenttest.NewNopHost() + err = c.Start(context.Background(), host) + require.NoError(t, err) + require.NotPanics(t, func() { + switch e := c.(type) { + case processor.Logs: + logs := testdata.GenerateLogsManyLogRecordsSameResource(2) + if !e.Capabilities().MutatesData { + logs.MarkReadOnly() + } + err = e.ConsumeLogs(context.Background(), logs) + case processor.Metrics: + metrics := testdata.GenerateMetricsTwoMetrics() + if !e.Capabilities().MutatesData { + metrics.MarkReadOnly() + } + err = e.ConsumeMetrics(context.Background(), metrics) + case processor.Traces: + traces := testdata.GenerateTracesTwoSpansSameResource() + if !e.Capabilities().MutatesData { + traces.MarkReadOnly() + } + err = e.ConsumeTraces(context.Background(), traces) + } + }) + require.NoError(t, err) + err = c.Shutdown(context.Background()) + require.NoError(t, err) + }) + } +} +{{ end }} + +{{ if isReceiver }} +func TestComponentLifecycle(t *testing.T) { + factory := NewFactory() + + tests := []struct{ + name string + createFn func(ctx context.Context, set receiver.CreateSettings, cfg component.Config) (component.Component, error) + }{ +{{ if supportsLogs }} + { + name: "logs", + createFn: func(ctx context.Context, set receiver.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsReceiver(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} +{{ if supportsMetrics }} + { + name: "metrics", + createFn: func(ctx context.Context, set receiver.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsReceiver(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} +{{ if supportsTraces }} + { + name: "traces", + createFn: func(ctx context.Context, set receiver.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesReceiver(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} + } + + cm, err := confmaptest.LoadConf("metadata.yaml") + require.NoError(t, err) + cfg := factory.CreateDefaultConfig() + sub, err := cm.Sub("tests::config") + require.NoError(t, err) + require.NoError(t, component.UnmarshalConfig(sub, cfg)) + + for _, test := range tests { + t.Run(test.name + "-shutdown", func(t *testing.T) { + c, err := test.createFn(context.Background(), receivertest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + err = c.Shutdown(context.Background()) + require.NoError(t, err) + }) + + t.Run(test.name + "-lifecycle", func(t *testing.T) { + {{ if skipLifecycle }} + // TODO support lifecycle + t.SkipNow() + {{ end }} + firstRcvr, err := test.createFn(context.Background(), receivertest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + host := componenttest.NewNopHost() + require.NoError(t, err) + require.NoError(t, firstRcvr.Start(context.Background(), host)) + require.NoError(t, firstRcvr.Shutdown(context.Background())) + secondRcvr, err := test.createFn(context.Background(), receivertest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + require.NoError(t, secondRcvr.Start(context.Background(), host)) + require.NoError(t, secondRcvr.Shutdown(context.Background())) + }) + } +} +{{ end }} + +{{ if isExtension }} +func TestComponentLifecycle(t *testing.T) { + factory := NewFactory() + + cm, err := confmaptest.LoadConf("metadata.yaml") + require.NoError(t, err) + cfg := factory.CreateDefaultConfig() + sub, err := cm.Sub("tests::config") + require.NoError(t, err) + require.NoError(t, component.UnmarshalConfig(sub, cfg)) + + t.Run("shutdown", func(t *testing.T) { + e, err := factory.CreateExtension(context.Background(), extensiontest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + err = e.Shutdown(context.Background()) + require.NoError(t, err) + }) + + t.Run("lifecycle", func(t *testing.T) { + {{ if skipLifecycle }} + // TODO support lifecycle + t.SkipNow() + {{ end }} + firstExt, err := factory.CreateExtension(context.Background(), extensiontest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + require.NoError(t, firstExt.Start(context.Background(), componenttest.NewNopHost())) + require.NoError(t, firstExt.Shutdown(context.Background())) + + secondExt, err := factory.CreateExtension(context.Background(), extensiontest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + require.NoError(t, secondExt.Start(context.Background(), componenttest.NewNopHost())) + require.NoError(t, secondExt.Shutdown(context.Background())) + }) +} +{{ end }} + +{{ if isConnector }} +func TestComponentLifecycle(t *testing.T) { + factory := NewFactory() + + tests := []struct{ + name string + createFn func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) + }{ +{{ if supportsLogsToLogs }} + { + name: "logs_to_logs", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsToLogs(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} +{{ if supportsLogsToMetrics }} + { + name: "logs_to_metrics", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsToMetrics(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} +{{ if supportsLogsToTraces }} + { + name: "logs_to_traces", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsToTraces(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} +{{ if supportsMetricsToLogs }} + { + name: "metrics_to_logs", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsToLogs(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} +{{ if supportsMetricsToMetrics }} + { + name: "metrics_to_metrics", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsToMetrics(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} +{{ if supportsMetricsToTraces }} + { + name: "metrics_to_traces", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsToTraces(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} +{{ if supportsTracesToLogs }} + { + name: "traces_to_logs", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesToLogs(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} +{{ if supportsTracesToMetrics }} + { + name: "traces_to_metrics", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesToMetrics(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} +{{ if supportsTracesToTraces }} + { + name: "traces_to_traces", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesToTraces(ctx, set, cfg, consumertest.NewNop()) + }, + }, +{{ end }} + } + + cm, err := confmaptest.LoadConf("metadata.yaml") + require.NoError(t, err) + cfg := factory.CreateDefaultConfig() + sub, err := cm.Sub("tests::config") + require.NoError(t, err) + require.NoError(t, component.UnmarshalConfig(sub, cfg)) + + for _, test := range tests { + t.Run(test.name + "-shutdown", func(t *testing.T) { + c, err := test.createFn(context.Background(), connectortest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + err = c.Shutdown(context.Background()) + require.NoError(t, err) + }) + + t.Run(test.name + "-lifecycle", func(t *testing.T) { + {{ if skipLifecycle }} + // TODO support lifecycle + t.SkipNow() + {{ end }} + firstConnector, err := test.createFn(context.Background(), connectortest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + host := newAssertNoErrorHost(t) + require.NoError(t, err) + require.NoError(t, firstConnector.Start(context.Background(), host)) + require.NoError(t, firstConnector.Shutdown(context.Background())) + secondConnector, err := test.createFn(context.Background(), connectortest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + require.NoError(t, secondConnector.Start(context.Background(), host)) + require.NoError(t, secondConnector.Shutdown(context.Background())) + }) + } +} +{{ end }} \ No newline at end of file diff --git a/cmd/mdatagen/templates/config.go.tmpl b/cmd/mdatagen/templates/config.go.tmpl new file mode 100644 index 00000000000..712602222e7 --- /dev/null +++ b/cmd/mdatagen/templates/config.go.tmpl @@ -0,0 +1,103 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package {{ .Package }} + +{{ if or .Metrics .ResourceAttributes -}} +import "go.opentelemetry.io/collector/confmap" +{{- end }} + +{{ if .Metrics -}} + +// MetricConfig provides common config for a particular metric. +type MetricConfig struct { + Enabled bool `mapstructure:"enabled"` + + enabledSetByUser bool +} + +func (ms *MetricConfig) Unmarshal(parser *confmap.Conf) error { + if parser == nil { + return nil + } + err := parser.Unmarshal(ms) + if err != nil { + return err + } + ms.enabledSetByUser = parser.IsSet("enabled") + return nil +} + +// MetricsConfig provides config for {{ .Type }} metrics. +type MetricsConfig struct { + {{- range $name, $metric := .Metrics }} + {{ $name.Render }} MetricConfig `mapstructure:"{{ $name }}"` + {{- end }} +} + +func DefaultMetricsConfig() MetricsConfig { + return MetricsConfig{ + {{- range $name, $metric := .Metrics }} + {{ $name.Render }}: MetricConfig{ + Enabled: {{ $metric.Enabled }}, + }, + {{- end }} + } +} +{{- end }} + +{{ if .ResourceAttributes -}} +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` + + enabledSetByUser bool +} + +func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error { + if parser == nil { + return nil + } + err := parser.Unmarshal(rac) + if err != nil { + return err + } + rac.enabledSetByUser = parser.IsSet("enabled") + return nil +} + +// ResourceAttributesConfig provides config for {{ .Type }} resource attributes. +type ResourceAttributesConfig struct { + {{- range $name, $attr := .ResourceAttributes }} + {{ $name.Render }} ResourceAttributeConfig `mapstructure:"{{ $name }}"` + {{- end }} +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + {{- range $name, $attr := .ResourceAttributes }} + {{ $name.Render }}: ResourceAttributeConfig { + Enabled: {{ $attr.Enabled }}, + }, + {{- end }} + } +} +{{- end }} + +{{ if .Metrics -}} +// MetricsBuilderConfig is a configuration for {{ .Type }} metrics builder. +type MetricsBuilderConfig struct { + Metrics MetricsConfig `mapstructure:"metrics"` + {{- if .ResourceAttributes }} + ResourceAttributes ResourceAttributesConfig `mapstructure:"resource_attributes"` + {{- end }} +} + +func DefaultMetricsBuilderConfig() MetricsBuilderConfig { + return MetricsBuilderConfig { + Metrics: DefaultMetricsConfig(), + {{- if .ResourceAttributes }} + ResourceAttributes: DefaultResourceAttributesConfig(), + {{- end }} + } +} +{{- end }} diff --git a/cmd/mdatagen/templates/config_test.go.tmpl b/cmd/mdatagen/templates/config_test.go.tmpl new file mode 100644 index 00000000000..3f6a636bc6e --- /dev/null +++ b/cmd/mdatagen/templates/config_test.go.tmpl @@ -0,0 +1,131 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package {{ .Package }} + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +{{ if .Metrics }} +func TestMetricsBuilderConfig(t *testing.T) { + tests := []struct { + name string + want MetricsBuilderConfig + }{ + { + name: "default", + want: DefaultMetricsBuilderConfig(), + }, + { + name: "all_set", + want: MetricsBuilderConfig{ + Metrics: MetricsConfig{ + {{- range $name, $_ := .Metrics }} + {{ $name.Render }}: MetricConfig{Enabled: true}, + {{- end }} + }, + {{- if .ResourceAttributes }} + ResourceAttributes: ResourceAttributesConfig{ + {{- range $name, $_ := .ResourceAttributes }} + {{ $name.Render }}: ResourceAttributeConfig{Enabled: true}, + {{- end }} + }, + {{- end }} + }, + }, + { + name: "none_set", + want: MetricsBuilderConfig{ + Metrics: MetricsConfig{ + {{- range $name, $_ := .Metrics }} + {{ $name.Render }}: MetricConfig{Enabled: false}, + {{- end }} + }, + {{- if .ResourceAttributes }} + ResourceAttributes: ResourceAttributesConfig{ + {{- range $name, $_ := .ResourceAttributes }} + {{ $name.Render }}: ResourceAttributeConfig{Enabled: false}, + {{- end }} + }, + {{- end }} + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg := loadMetricsBuilderConfig(t, tt.name) + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(MetricConfig{} + {{- if .ResourceAttributes }}, ResourceAttributeConfig{}{{ end }})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} + +func loadMetricsBuilderConfig(t *testing.T, name string) MetricsBuilderConfig { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(name) + require.NoError(t, err) + cfg := DefaultMetricsBuilderConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + return cfg +} +{{- end }} + +{{ if .ResourceAttributes -}} +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + {{- range $name, $_ := .ResourceAttributes }} + {{ $name.Render }}: ResourceAttributeConfig{Enabled: true}, + {{- end }} + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + {{- range $name, $_ := .ResourceAttributes }} + {{ $name.Render }}: ResourceAttributeConfig{Enabled: false}, + {{- end }} + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg := loadResourceAttributesConfig(t, tt.name) + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} + +func loadResourceAttributesConfig(t *testing.T, name string) ResourceAttributesConfig { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, component.UnmarshalConfig(sub, &cfg)) + return cfg +} +{{- end }} diff --git a/cmd/mdatagen/templates/documentation.md.tmpl b/cmd/mdatagen/templates/documentation.md.tmpl new file mode 100644 index 00000000000..eda8dc9fffe --- /dev/null +++ b/cmd/mdatagen/templates/documentation.md.tmpl @@ -0,0 +1,98 @@ +{{- define "metric-documenation" -}} +{{- $metricName := . }} +{{- $metric := $metricName | metricInfo -}} + +### {{ $metricName }} + +{{ $metric.Description }} + +{{- if $metric.ExtendedDocumentation }} + +{{ $metric.ExtendedDocumentation }} + +{{- end }} + +| Unit | Metric Type | Value Type |{{ if $metric.Data.HasAggregated }} Aggregation Temporality |{{ end }}{{ if $metric.Data.HasMonotonic }} Monotonic |{{ end }} +| ---- | ----------- | ---------- |{{ if $metric.Data.HasAggregated }} ----------------------- |{{ end }}{{ if $metric.Data.HasMonotonic }} --------- |{{ end }} +| {{ $metric.Unit }} | {{ $metric.Data.Type }} | {{ $metric.Data.MetricValueType }} | +{{- if $metric.Data.HasAggregated }} {{ $metric.Data.AggregationTemporality }} |{{ end }} +{{- if $metric.Data.HasMonotonic }} {{ $metric.Data.Monotonic }} |{{ end }} + +{{- if $metric.Attributes }} + +#### Attributes + +| Name | Description | Values | +| ---- | ----------- | ------ | +{{- range $metric.Attributes }} +{{- $attribute := . | attributeInfo }} +| {{ $attribute.Name }} | {{ $attribute.Description }} | +{{- if $attribute.Enum }} {{ $attribute.Type }}: ``{{ stringsJoin $attribute.Enum "``, ``" }}``{{ else }} Any {{ $attribute.Type }}{{ end }} | +{{- end }} + +{{- end }} + +{{- end -}} + +[comment]: <> (Code generated by mdatagen. DO NOT EDIT.) + +# {{ .Type }} + +{{- if .Parent }} + +**Parent Component:** {{ .Parent }} +{{- end }} + +## Default Metrics + +The following metrics are emitted by default. Each of them can be disabled by applying the following configuration: + +```yaml +metrics: + : + enabled: false +``` + +{{- range $metricName, $metric := .Metrics }} +{{- if $metric.Enabled }} + +{{ template "metric-documenation" $metricName }} + +{{- end }} +{{- end }} + +{{- $optionalMetricSeen := false }} +{{- range $metricName, $metric := .Metrics }} +{{- if not $metric.Enabled }} +{{- if not $optionalMetricSeen }} + +## Optional Metrics + +The following metrics are not emitted by default. Each of them can be enabled by applying the following configuration: + +```yaml +metrics: + : + enabled: true +``` + +{{- end }} +{{- $optionalMetricSeen = true }} + +{{ template "metric-documenation" $metricName }} + +{{- end }} +{{- end }} + +{{- if .ResourceAttributes }} + +## Resource Attributes + +| Name | Description | Values | Enabled | +| ---- | ----------- | ------ | ------- | +{{- range $attributeName, $attribute := .ResourceAttributes }} +| {{ $attributeName }} | {{ $attribute.Description }} | +{{- if $attribute.Enum }} {{ $attribute.Type }}: ``{{ stringsJoin $attribute.Enum "``, ``" }}``{{ else }} Any {{ $attribute.Type }}{{ end }} | {{ $attribute.Enabled }} | +{{- end }} + +{{- end }} diff --git a/cmd/mdatagen/templates/metrics.go.tmpl b/cmd/mdatagen/templates/metrics.go.tmpl new file mode 100644 index 00000000000..c76623c40fc --- /dev/null +++ b/cmd/mdatagen/templates/metrics.go.tmpl @@ -0,0 +1,319 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package {{ .Package }} + +import ( + {{- if .Metrics | parseImportsRequired }} + "strconv" + "fmt" + {{- end }} + "time" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/receiver" + {{- if .SemConvVersion }} + conventions "go.opentelemetry.io/collector/semconv/v{{ .SemConvVersion }}" + {{- end }} +) + +{{ range $name, $info := .Attributes }} +{{- if $info.Enum -}} +// Attribute{{ $name.Render }} specifies the a value {{ $name }} attribute. +type Attribute{{ $name.Render }} int + +const ( + _ Attribute{{ $name.Render }} = iota + {{- range $info.Enum }} + Attribute{{ $name.Render }}{{ . | publicVar }} + {{- end }} +) + +// String returns the string representation of the Attribute{{ $name.Render }}. +func (av Attribute{{ $name.Render }}) String() string { + switch av { + {{- range $info.Enum }} + case Attribute{{ $name.Render }}{{ . | publicVar }}: + return "{{ . }}" + {{- end }} + } + return "" +} + +// MapAttribute{{ $name.Render }} is a helper map of string to Attribute{{ $name.Render }} attribute value. +var MapAttribute{{ $name.Render }} = map[string]Attribute{{ $name.Render }}{ + {{- range $info.Enum }} + "{{ . }}": Attribute{{ $name.Render }}{{ . | publicVar }}, + {{- end }} +} + +{{ end }} +{{- end }} + +{{ range $name, $metric := .Metrics -}} +type metric{{ $name.Render }} struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills {{ $name }} metric with initial data. +func (m *metric{{ $name.Render }}) init() { + m.data.SetName("{{ $name }}") + m.data.SetDescription("{{ $metric.Description }}") + m.data.SetUnit("{{ $metric.Unit }}") + m.data.SetEmpty{{ $metric.Data.Type }}() + {{- if $metric.Data.HasMonotonic }} + m.data.{{ $metric.Data.Type }}().SetIsMonotonic({{ $metric.Data.Monotonic }}) + {{- end }} + {{- if $metric.Data.HasAggregated }} + m.data.{{ $metric.Data.Type }}().SetAggregationTemporality(pmetric.AggregationTemporality{{ $metric.Data.AggregationTemporality }}) + {{- end }} + {{- if $metric.Attributes }} + m.data.{{ $metric.Data.Type }}().DataPoints().EnsureCapacity(m.capacity) + {{- end }} +} + +func (m *metric{{ $name.Render }}) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val {{ $metric.Data.MetricValueType.BasicType }} +{{- range $metric.Attributes -}}, {{ .RenderUnexported }}AttributeValue {{ (attributeInfo .).Type.Primitive }}{{ end }}) { + if !m.config.Enabled { + return + } + dp := m.data.{{ $metric.Data.Type }}().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.Set{{ $metric.Data.MetricValueType }}Value(val) + {{- range $metric.Attributes }} + {{- if eq (attributeInfo .).Type.Primitive "[]byte" }} + dp.Attributes().PutEmptyBytes("{{ (attributeInfo .).Name }}").FromRaw({{ .RenderUnexported }}AttributeValue) + {{- else if eq (attributeInfo .).Type.Primitive "[]any" }} + dp.Attributes().PutEmptySlice("{{ (attributeInfo .).Name }}").FromRaw({{ .RenderUnexported }}AttributeValue) + {{- else if eq (attributeInfo .).Type.Primitive "map[string]any" }} + dp.Attributes().PutEmptyMap("{{ (attributeInfo .).Name }}").FromRaw({{ .RenderUnexported }}AttributeValue) + {{- else }} + dp.Attributes().Put{{ (attributeInfo .).Type }}("{{ (attributeInfo .).Name }}", {{ .RenderUnexported }}AttributeValue) + {{- end }} + {{- end }} +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metric{{ $name.Render }}) updateCapacity() { + if m.data.{{ $metric.Data.Type }}().DataPoints().Len() > m.capacity { + m.capacity = m.data.{{ $metric.Data.Type }}().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metric{{ $name.Render }}) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.{{ $metric.Data.Type }}().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetric{{ $name.Render }}(cfg MetricConfig) metric{{ $name.Render }} { + m := metric{{ $name.Render }}{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +{{ end -}} + +// MetricsBuilder provides an interface for scrapers to report metrics while taking care of all the transformations +// required to produce metric representation defined in metadata and user config. +type MetricsBuilder struct { + config MetricsBuilderConfig // config of the metrics builder. + startTime pcommon.Timestamp // start time that will be applied to all recorded data points. + metricsCapacity int // maximum observed number of metrics per resource. + metricsBuffer pmetric.Metrics // accumulates metrics data before emitting. + buildInfo component.BuildInfo // contains version information. + {{- range $name, $metric := .Metrics }} + metric{{ $name.Render }} metric{{ $name.Render }} + {{- end }} +} + +// metricBuilderOption applies changes to default metrics builder. +type metricBuilderOption func(*MetricsBuilder) + +// WithStartTime sets startTime on the metrics builder. +func WithStartTime(startTime pcommon.Timestamp) metricBuilderOption { + return func(mb *MetricsBuilder) { + mb.startTime = startTime + } +} + +func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.CreateSettings, options ...metricBuilderOption) *MetricsBuilder { + {{- range $name, $metric := .Metrics }} + {{- if $metric.Warnings.IfEnabled }} + if mbc.Metrics.{{ $name.Render }}.Enabled { + settings.Logger.Warn("[WARNING] `{{ $name }}` should not be enabled: {{ $metric.Warnings.IfEnabled }}") + } + {{- end }} + {{- if $metric.Warnings.IfEnabledNotSet }} + if !mbc.Metrics.{{ $name.Render }}.enabledSetByUser { + settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `{{ $name }}`: {{ $metric.Warnings.IfEnabledNotSet }}") + } + {{- end }} + {{- if $metric.Warnings.IfConfigured }} + if mbc.Metrics.{{ $name.Render }}.enabledSetByUser { + settings.Logger.Warn("[WARNING] `{{ $name }}` should not be configured: {{ $metric.Warnings.IfConfigured }}") + } + {{- end }} + {{- end }} + {{- range $name, $attr := .ResourceAttributes }} + {{- if $attr.Warnings.IfEnabled }} + if mbc.ResourceAttributes.{{ $name.Render }}.Enabled { + settings.Logger.Warn("[WARNING] `{{ $name }}` should not be enabled: {{ $attr.Warnings.IfEnabled }}") + } + {{- end }} + {{- if $attr.Warnings.IfEnabledNotSet }} + if !mbc.ResourceAttributes.{{ $name.Render }}.enabledSetByUser { + settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `{{ $name }}`: {{ $attr.Warnings.IfEnabledNotSet }}") + } + {{- end }} + {{- if $attr.Warnings.IfConfigured }} + if mbc.ResourceAttributes.{{ $name.Render }}.enabledSetByUser { + settings.Logger.Warn("[WARNING] `{{ $name }}` should not be configured: {{ $attr.Warnings.IfConfigured }}") + } + {{- end }} + {{- end }} + mb := &MetricsBuilder{ + config: mbc, + startTime: pcommon.NewTimestampFromTime(time.Now()), + metricsBuffer: pmetric.NewMetrics(), + buildInfo: settings.BuildInfo, + {{- range $name, $metric := .Metrics }} + metric{{ $name.Render }}: newMetric{{ $name.Render }}(mbc.Metrics.{{ $name.Render }}), + {{- end }} + } + for _, op := range options { + op(mb) + } + return mb +} + +{{- if .ResourceAttributes }} +// NewResourceBuilder returns a new resource builder that should be used to build a resource associated with for the emitted metrics. +func (mb *MetricsBuilder) NewResourceBuilder() *ResourceBuilder { + return NewResourceBuilder(mb.config.ResourceAttributes) +} +{{- end }} + +// updateCapacity updates max length of metrics and resource attributes that will be used for the slice capacity. +func (mb *MetricsBuilder) updateCapacity(rm pmetric.ResourceMetrics) { + if mb.metricsCapacity < rm.ScopeMetrics().At(0).Metrics().Len() { + mb.metricsCapacity = rm.ScopeMetrics().At(0).Metrics().Len() + } +} + +// ResourceMetricsOption applies changes to provided resource metrics. +type ResourceMetricsOption func(pmetric.ResourceMetrics) + +// WithResource sets the provided resource on the emitted ResourceMetrics. +// It's recommended to use ResourceBuilder to create the resource. +func WithResource(res pcommon.Resource) ResourceMetricsOption { + return func(rm pmetric.ResourceMetrics) { + res.CopyTo(rm.Resource()) + } +} + +// WithStartTimeOverride overrides start time for all the resource metrics data points. +// This option should be only used if different start time has to be set on metrics coming from different resources. +func WithStartTimeOverride(start pcommon.Timestamp) ResourceMetricsOption { + return func(rm pmetric.ResourceMetrics) { + var dps pmetric.NumberDataPointSlice + metrics := rm.ScopeMetrics().At(0).Metrics() + for i := 0; i < metrics.Len(); i++ { + switch metrics.At(i).Type() { + case pmetric.MetricTypeGauge: + dps = metrics.At(i).Gauge().DataPoints() + case pmetric.MetricTypeSum: + dps = metrics.At(i).Sum().DataPoints() + } + for j := 0; j < dps.Len(); j++ { + dps.At(j).SetStartTimestamp(start) + } + } + } +} + +// EmitForResource saves all the generated metrics under a new resource and updates the internal state to be ready for +// recording another set of data points as part of another resource. This function can be helpful when one scraper +// needs to emit metrics from several resources. Otherwise calling this function is not required, +// just `Emit` function can be called instead. +// Resource attributes should be provided as ResourceMetricsOption arguments. +func (mb *MetricsBuilder) EmitForResource(rmo ...ResourceMetricsOption) { + rm := pmetric.NewResourceMetrics() + {{- if .SemConvVersion }} + rm.SetSchemaUrl(conventions.SchemaURL) + {{- end }} + ils := rm.ScopeMetrics().AppendEmpty() + ils.Scope().SetName("{{ .ScopeName }}") + ils.Scope().SetVersion(mb.buildInfo.Version) + ils.Metrics().EnsureCapacity(mb.metricsCapacity) + {{- range $name, $metric := .Metrics }} + mb.metric{{- $name.Render }}.emit(ils.Metrics()) + {{- end }} + + for _, op := range rmo { + op(rm) + } + if ils.Metrics().Len() > 0 { + mb.updateCapacity(rm) + rm.MoveTo(mb.metricsBuffer.ResourceMetrics().AppendEmpty()) + } +} + +// Emit returns all the metrics accumulated by the metrics builder and updates the internal state to be ready for +// recording another set of metrics. This function will be responsible for applying all the transformations required to +// produce metric representation defined in metadata and user config, e.g. delta or cumulative. +func (mb *MetricsBuilder) Emit(rmo ...ResourceMetricsOption) pmetric.Metrics { + mb.EmitForResource(rmo...) + metrics := mb.metricsBuffer + mb.metricsBuffer = pmetric.NewMetrics() + return metrics +} + +{{ range $name, $metric := .Metrics -}} +// Record{{ $name.Render }}DataPoint adds a data point to {{ $name }} metric. +func (mb *MetricsBuilder) Record{{ $name.Render }}DataPoint(ts pcommon.Timestamp + {{- if $metric.Data.HasMetricInputType }}, inputVal {{ $metric.Data.MetricInputType.String }} + {{- else }}, val {{ $metric.Data.MetricValueType.BasicType }} + {{- end }} + {{- range $metric.Attributes -}} + , {{ .RenderUnexported }}AttributeValue {{ if (attributeInfo .).Enum }}Attribute{{ .Render }}{{ else }}{{ (attributeInfo .).Type.Primitive }}{{ end }} + {{- end }}) + {{- if $metric.Data.HasMetricInputType }} error{{ end }} { + {{- if $metric.Data.HasMetricInputType }} + {{- if eq $metric.Data.MetricValueType.BasicType "float64" }} + val, err := strconv.ParseFloat(inputVal, 64) + {{- else if eq $metric.Data.MetricValueType.BasicType "int64" }} + val, err := strconv.ParseInt(inputVal, 10, 64) + {{- end }} + if err != nil { + return fmt.Errorf("failed to parse {{ $metric.Data.MetricValueType.BasicType }} for {{ $name.Render }}, value was %s: %w", inputVal, err) + } + {{- end }} + mb.metric{{ $name.Render }}.recordDataPoint(mb.startTime, ts, val + {{- range $metric.Attributes -}} + , {{ .RenderUnexported }}AttributeValue{{ if (attributeInfo .).Enum }}.String(){{ end }} + {{- end }}) + {{- if $metric.Data.HasMetricInputType }} + return nil + {{- end }} +} +{{ end }} + +// Reset resets metrics builder to its initial state. It should be used when external metrics source is restarted, +// and metrics builder should update its startTime and reset it's internal state accordingly. +func (mb *MetricsBuilder) Reset(options ...metricBuilderOption) { + mb.startTime = pcommon.NewTimestampFromTime(time.Now()) + for _, op := range options { + op(mb) + } +} diff --git a/cmd/mdatagen/templates/metrics_test.go.tmpl b/cmd/mdatagen/templates/metrics_test.go.tmpl new file mode 100644 index 00000000000..bf7b09d05a9 --- /dev/null +++ b/cmd/mdatagen/templates/metrics_test.go.tmpl @@ -0,0 +1,174 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package {{ .Package }} + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/receiver/receivertest" + "go.uber.org/zap" + "go.uber.org/zap/zaptest/observer" +) + + +type testConfigCollection int + +const ( + testSetDefault testConfigCollection = iota + testSetAll + testSetNone +) + +func TestMetricsBuilder(t *testing.T) { + tests := []struct { + name string + configSet testConfigCollection + }{ + { + name: "default", + configSet: testSetDefault, + }, + { + name: "all_set", + configSet: testSetAll, + }, + { + name: "none_set", + configSet: testSetNone, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + start := pcommon.Timestamp(1_000_000_000) + ts := pcommon.Timestamp(1_000_001_000) + observedZapCore, observedLogs := observer.New(zap.WarnLevel) + settings := receivertest.NewNopCreateSettings() + settings.Logger = zap.New(observedZapCore) + mb := NewMetricsBuilder(loadMetricsBuilderConfig(t, test.name), settings, WithStartTime(start)) + + expectedWarnings := 0 + {{- range $name, $metric := .Metrics }} + {{- if and $metric.Enabled $metric.Warnings.IfEnabled }} + if test.configSet == testSetDefault || test.configSet == testSetAll { + assert.Equal(t, "[WARNING] `{{ $name }}` should not be enabled: {{ $metric.Warnings.IfEnabled }}", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + {{- end }} + {{- if $metric.Warnings.IfEnabledNotSet }} + if test.configSet == testSetDefault { + assert.Equal(t, "[WARNING] Please set `enabled` field explicitly for `{{ $name }}`: {{ $metric.Warnings.IfEnabledNotSet }}", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + {{- end }} + {{- if $metric.Warnings.IfConfigured }} + if test.configSet == testSetAll || test.configSet == testSetNone { + assert.Equal(t, "[WARNING] `{{ $name }}` should not be configured: {{ $metric.Warnings.IfConfigured }}", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + {{- end }} + {{- end }} + {{- range $name, $attr := .ResourceAttributes }} + {{- if and $attr.Enabled $attr.Warnings.IfEnabled }} + if test.configSet == testSetDefault || test.configSet == testSetAll { + assert.Equal(t, "[WARNING] `{{ $name }}` should not be enabled: {{ $attr.Warnings.IfEnabled }}", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + {{- end }} + {{- if $attr.Warnings.IfEnabledNotSet }} + if test.configSet == testSetDefault { + assert.Equal(t, "[WARNING] Please set `enabled` field explicitly for `{{ $name }}`: {{ $attr.Warnings.IfEnabledNotSet }}", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + {{- end }} + {{- if $attr.Warnings.IfConfigured }} + if test.configSet == testSetAll || test.configSet == testSetNone { + assert.Equal(t, "[WARNING] `{{ $name }}` should not be configured: {{ $attr.Warnings.IfConfigured }}", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + {{- end }} + {{- end }} + + + assert.Equal(t, expectedWarnings, observedLogs.Len()) + + defaultMetricsCount := 0 + allMetricsCount := 0 + {{- range $name, $metric := .Metrics }} + + {{ if $metric.Enabled }}defaultMetricsCount++{{ end }} + allMetricsCount++ + mb.Record{{ $name.Render }}DataPoint(ts, {{ if $metric.Data.HasMetricInputType }}"1"{{ else }}1{{ end }} + {{- range $metric.Attributes -}} + , {{ if (attributeInfo .).Enum }}Attribute{{ .Render }}{{ (index (attributeInfo .).Enum 0) | publicVar }}{{ else }}{{ (attributeInfo .).TestValue }}{{ end }} + {{- end }}) + {{- end }} + + {{ if .ResourceAttributes }} + rb := mb.NewResourceBuilder() + {{- range $name, $attr := .ResourceAttributes }} + {{- if $attr.Enum }} + rb.Set{{ $attr.Name.Render }}{{ index $attr.Enum 0 | publicVar }}() + {{- else }} + rb.Set{{ $attr.Name.Render }}({{ $attr.TestValue }}) + {{- end }} + {{- end }} + res := rb.Emit() + {{- else }} + res := pcommon.NewResource() + {{- end }} + metrics := mb.Emit(WithResource(res)) + + if test.configSet == testSetNone { + assert.Equal(t, 0, metrics.ResourceMetrics().Len()) + return + } + + assert.Equal(t, 1, metrics.ResourceMetrics().Len()) + rm := metrics.ResourceMetrics().At(0) + assert.Equal(t, res, rm.Resource()) + assert.Equal(t, 1, rm.ScopeMetrics().Len()) + ms := rm.ScopeMetrics().At(0).Metrics() + if test.configSet == testSetDefault { + assert.Equal(t, defaultMetricsCount, ms.Len()) + } + if test.configSet == testSetAll { + assert.Equal(t, allMetricsCount, ms.Len()) + } + validatedMetrics := make(map[string]bool) + for i := 0; i < ms.Len(); i++ { + switch ms.At(i).Name() { + {{- range $name, $metric := .Metrics }} + case "{{ $name }}": + assert.False(t, validatedMetrics["{{ $name }}"], "Found a duplicate in the metrics slice: {{ $name }}") + validatedMetrics["{{ $name }}"] = true + assert.Equal(t, pmetric.MetricType{{ $metric.Data.Type }}, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).{{ $metric.Data.Type }}().DataPoints().Len()) + assert.Equal(t, "{{ $metric.Description }}", ms.At(i).Description()) + assert.Equal(t, "{{ $metric.Unit }}", ms.At(i).Unit()) + {{- if $metric.Data.HasMonotonic }} + assert.Equal(t, {{ $metric.Data.Monotonic }}, ms.At(i).{{ $metric.Data.Type }}().IsMonotonic()) + {{- end }} + {{- if $metric.Data.HasAggregated }} + assert.Equal(t, pmetric.AggregationTemporality{{ $metric.Data.AggregationTemporality }}, ms.At(i).{{ $metric.Data.Type }}().AggregationTemporality()) + {{- end }} + dp := ms.At(i).{{ $metric.Data.Type }}().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueType{{ $metric.Data.MetricValueType }}, dp.ValueType()) + assert.Equal(t, {{ $metric.Data.MetricValueType.BasicType }}(1), dp.{{ $metric.Data.MetricValueType }}Value()) + + {{- range $i, $attr := $metric.Attributes }} + attrVal, ok {{ if eq $i 0 }}:{{ end }}= dp.Attributes().Get("{{ (attributeInfo $attr).Name }}") + assert.True(t, ok) + assert.EqualValues(t, {{ (attributeInfo $attr).TestValue }}, attrVal.{{ (attributeInfo $attr).Type }}() + {{- if or (eq (attributeInfo $attr).Type.String "Slice") (eq (attributeInfo $attr).Type.String "Map")}}.AsRaw(){{ end }}) + {{- end }} + {{- end }} + } + } + }) + } +} diff --git a/cmd/mdatagen/templates/readme.md.tmpl b/cmd/mdatagen/templates/readme.md.tmpl new file mode 100644 index 00000000000..ad41f11dd42 --- /dev/null +++ b/cmd/mdatagen/templates/readme.md.tmpl @@ -0,0 +1,55 @@ + +{{- if len .Status.Stability }} +| Status | | +| ------------- |-----------| +{{- $class := .Status.Class }} +{{- $shortName := .ShortFolderName }} +{{- if ne $class "connector" }} +{{- $idx := 0 }} +{{- range $stability, $value := .Status.Stability }} +| {{ if not $idx }}Stability{{ else }} {{ end }} | [{{ $stability }}]{{ if ne $class "extension" }}: {{ stringsJoin $value ", " }} {{ end }} | +{{- $idx = inc $idx }} +{{- end }} +{{- end}} +{{- if and (ne $class "cmd") (ne $class "pkg") }} +| Distributions | [{{ stringsJoin .Status.SortedDistributions "], [" }}] | +{{- end }} +{{- if .Status.Warnings }} +| Warnings | [{{ stringsJoin .Status.Warnings ", " }}](#warnings) | +{{- end }} +{{- if ne $class "" }} +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3A{{ $class }}%2F{{ $shortName }}%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3A{{ $class }}%2F{{ $shortName }}) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3A{{ $class }}%2F{{ $shortName }}%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3A{{ $class }}%2F{{ $shortName }}) | +{{- end }} +{{- if .Status.Codeowners }} +{{- $codeowners := userLinks .Status.Codeowners.Active }} +{{- $emeritus := userLinks .Status.Codeowners.Emeritus }} +| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | {{ stringsJoin $codeowners ", " }} {{ if .Status.Codeowners.SeekingNew }}\| Seeking more code owners! {{ end }}| +{{- if $emeritus }} +| Emeritus | {{ stringsJoin $emeritus ", " }} | +{{- end }} +{{- end }} +{{range $stability, $val := .Status.Stability}} +[{{ $stability }}]: https://github.com/open-telemetry/opentelemetry-collector#{{ $stability }} +{{- end }} +{{- range .Status.SortedDistributions }} +[{{.}}]: {{ distroURL . }} +{{- end }} +{{- if eq $class "connector"}} + +## Supported Pipeline Types + +| [Exporter Pipeline Type] | [Receiver Pipeline Type] | [Stability Level] | +| ------------------------ | ------------------------ | ----------------- | +{{- range $stability, $pipelines := .Status.Stability }} +{{- range $pipeline := $pipelines }} +{{- $parts := stringsSplit $pipeline "_to_" }} +| {{index $parts 0}} | {{index $parts 1}} | [{{$stability}}] | +{{- end }} +{{- end }} + +[Exporter Pipeline Type]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/connector/README.md#exporter-pipeline-type +[Receiver Pipeline Type]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/connector/README.md#receiver-pipeline-type +[Stability Level]: https://github.com/open-telemetry/opentelemetry-collector#stability-levels +{{- end }} +{{- end }} + \ No newline at end of file diff --git a/cmd/mdatagen/templates/resource.go.tmpl b/cmd/mdatagen/templates/resource.go.tmpl new file mode 100644 index 00000000000..aa6b8e8b685 --- /dev/null +++ b/cmd/mdatagen/templates/resource.go.tmpl @@ -0,0 +1,51 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package {{ .Package }} + +import ( + "go.opentelemetry.io/collector/pdata/pcommon" +) + +// ResourceBuilder is a helper struct to build resources predefined in metadata.yaml. +// The ResourceBuilder is not thread-safe and must not to be used in multiple goroutines. +type ResourceBuilder struct { + config ResourceAttributesConfig + res pcommon.Resource +} + +// NewResourceBuilder creates a new ResourceBuilder. This method should be called on the start of the application. +func NewResourceBuilder(rac ResourceAttributesConfig) *ResourceBuilder { + return &ResourceBuilder{ + config: rac, + res: pcommon.NewResource(), + } +} + +{{- range $name, $attr := .ResourceAttributes }} +{{- range $attr.Enum }} +// Set{{ $name.Render }}{{ . | publicVar }} sets "{{ $name }}={{ . }}" attribute. +func (rb *ResourceBuilder) Set{{ $name.Render }}{{ . | publicVar }}() { + if rb.config.{{ $name.Render }}.Enabled { + rb.res.Attributes().PutStr("{{ $name }}", "{{ . }}") + } +} +{{- else }} +// Set{{ $name.Render }} sets provided value as "{{ $name }}" attribute. +func (rb *ResourceBuilder) Set{{ $name.Render }}(val {{ $attr.Type.Primitive }}) { + if rb.config.{{ $name.Render }}.Enabled { + {{- if or (eq $attr.Type.String "Bytes") (eq $attr.Type.String "Slice") (eq $attr.Type.String "Map") }} + rb.res.Attributes().PutEmpty{{ $attr.Type }}("{{ $name }}").FromRaw(val) + {{- else }} + rb.res.Attributes().Put{{ $attr.Type }}("{{ $name }}", val) + {{- end }} + } +} +{{- end }} +{{ end }} + +// Emit returns the built resource and resets the internal builder state. +func (rb *ResourceBuilder) Emit() pcommon.Resource { + r := rb.res + rb.res = pcommon.NewResource() + return r +} diff --git a/cmd/mdatagen/templates/resource_test.go.tmpl b/cmd/mdatagen/templates/resource_test.go.tmpl new file mode 100644 index 00000000000..7c1422e3d3b --- /dev/null +++ b/cmd/mdatagen/templates/resource_test.go.tmpl @@ -0,0 +1,65 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package {{ .Package }} + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +{{- $enabledAttrCount := 0 }} +{{- range $_, $attr := .ResourceAttributes }} +{{- if $attr.Enabled }} +{{- $enabledAttrCount = inc $enabledAttrCount }} +{{- end }} +{{- end }} + +func TestResourceBuilder(t *testing.T) { + for _, test := range []string{"default", "all_set", "none_set"} { + t.Run(test, func(t *testing.T) { + cfg := loadResourceAttributesConfig(t, test) + rb := NewResourceBuilder(cfg) + {{- range $name, $attr := .ResourceAttributes }} + {{- if $attr.Enum }} + rb.Set{{ $name.Render }}{{ index $attr.Enum 0 | publicVar }}() + {{- else }} + rb.Set{{ $name.Render }}({{ $attr.TestValue }}) + {{- end }} + {{- end }} + + res := rb.Emit() + assert.Equal(t, 0, rb.Emit().Attributes().Len()) // Second call should return empty Resource + + switch test { + case "default": + assert.Equal(t, {{ $enabledAttrCount }}, res.Attributes().Len()) + case "all_set": + assert.Equal(t, {{ len .ResourceAttributes }}, res.Attributes().Len()) + case "none_set": + assert.Equal(t, 0, res.Attributes().Len()) + return + default: + assert.Failf(t, "unexpected test case: %s", test) + } + + {{ $assignSign := ":=" }} + {{- range $name, $attr := .ResourceAttributes }} + val, ok {{ $assignSign }} res.Attributes().Get("{{ $name }}") + {{- if $attr.Enabled }} + assert.True(t, ok) + {{- else }} + assert.Equal(t, test == "all_set", ok) + {{- end }} + if ok { + assert.EqualValues(t, {{ $attr.TestValue }}, val.{{ $attr.Type }}() + {{- if or (eq $attr.Type.String "Bytes") (eq $attr.Type.String "Slice") (eq $attr.Type.String "Map") -}} + .AsRaw() + {{- end -}} + ) + } + {{- $assignSign = "=" }} + {{- end }} + }) + } +} diff --git a/cmd/mdatagen/templates/status.go.tmpl b/cmd/mdatagen/templates/status.go.tmpl new file mode 100644 index 00000000000..d35cf76ff01 --- /dev/null +++ b/cmd/mdatagen/templates/status.go.tmpl @@ -0,0 +1,30 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package {{ .Package }} + +import ( + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" +) + +var ( + Type = component.MustNewType("{{ .Type }}") + scopeName = "{{ .ScopeName }}" +) + +const ( + {{- range $stability, $signals := .Status.Stability }} + {{- range $signal := $signals }} + {{ toCamelCase $signal }}Stability = component.StabilityLevel{{ casesTitle $stability }} + {{- end }} + {{- end }} +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} diff --git a/cmd/mdatagen/templates/testdata/config.yaml.tmpl b/cmd/mdatagen/templates/testdata/config.yaml.tmpl new file mode 100644 index 00000000000..8b32773ec45 --- /dev/null +++ b/cmd/mdatagen/templates/testdata/config.yaml.tmpl @@ -0,0 +1,31 @@ +default: +all_set: + {{- if .Metrics }} + metrics: + {{- range $name, $_ := .Metrics }} + {{ $name }}: + enabled: true + {{- end }} + {{- end }} + {{- if .ResourceAttributes }} + resource_attributes: + {{- range $name, $_ := .ResourceAttributes }} + {{ $name }}: + enabled: true + {{- end }} + {{- end }} +none_set: + {{- if .Metrics }} + metrics: + {{- range $name, $_ := .Metrics }} + {{ $name }}: + enabled: false + {{- end }} + {{- end }} + {{- if .ResourceAttributes }} + resource_attributes: + {{- range $name, $_ := .ResourceAttributes }} + {{ $name }}: + enabled: false + {{- end }} + {{- end }} diff --git a/cmd/mdatagen/testdata/invalid.yaml b/cmd/mdatagen/testdata/invalid.yaml new file mode 100644 index 00000000000..e466dcbd8e8 --- /dev/null +++ b/cmd/mdatagen/testdata/invalid.yaml @@ -0,0 +1 @@ +invalid \ No newline at end of file diff --git a/cmd/mdatagen/testdata/invalid_aggregation.yaml b/cmd/mdatagen/testdata/invalid_aggregation.yaml new file mode 100644 index 00000000000..3165d1a7101 --- /dev/null +++ b/cmd/mdatagen/testdata/invalid_aggregation.yaml @@ -0,0 +1,22 @@ +type: metricreceiver + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + distributions: [contrib] + warnings: + - Any additional information that should be brought to the consumer's attention + +metrics: + default.metric: + enabled: true + description: Monotonic cumulative sum int metric enabled by default. + extended_documentation: The metric will be become optional soon. + unit: s + sum: + value_type: int + monotonic: true + aggregation_temporality: invalidaggregation diff --git a/cmd/mdatagen/testdata/invalid_class.yaml b/cmd/mdatagen/testdata/invalid_class.yaml new file mode 100644 index 00000000000..6fcd9b9d7e7 --- /dev/null +++ b/cmd/mdatagen/testdata/invalid_class.yaml @@ -0,0 +1,8 @@ +type: test + +status: + class: incorrectclass + stability: + development: [logs] + beta: [traces] + stable: [metrics] \ No newline at end of file diff --git a/cmd/mdatagen/testdata/invalid_input_type.yaml b/cmd/mdatagen/testdata/invalid_input_type.yaml new file mode 100644 index 00000000000..9e28b42120d --- /dev/null +++ b/cmd/mdatagen/testdata/invalid_input_type.yaml @@ -0,0 +1,20 @@ +type: metricreceiver + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + +metrics: + system.cpu.time: + enabled: true + description: Total CPU seconds broken down by different states. + unit: s + sum: + value_type: double + monotonic: true + aggregation_temporality: cumulative + input_type: double + attributes: diff --git a/cmd/mdatagen/testdata/invalid_stability.yaml b/cmd/mdatagen/testdata/invalid_stability.yaml new file mode 100644 index 00000000000..259aade2445 --- /dev/null +++ b/cmd/mdatagen/testdata/invalid_stability.yaml @@ -0,0 +1,7 @@ +type: file +status: + class: receiver + stability: + incorrectstability: [logs] + beta: [traces] + stable: [metrics] \ No newline at end of file diff --git a/cmd/mdatagen/testdata/invalid_stability_component.yaml b/cmd/mdatagen/testdata/invalid_stability_component.yaml new file mode 100644 index 00000000000..5aa538865fa --- /dev/null +++ b/cmd/mdatagen/testdata/invalid_stability_component.yaml @@ -0,0 +1,7 @@ +type: file +status: + class: receiver + stability: + development: [incorrectcomponent] + beta: [traces] + stable: [metrics] \ No newline at end of file diff --git a/cmd/mdatagen/testdata/invalid_type_attr.yaml b/cmd/mdatagen/testdata/invalid_type_attr.yaml new file mode 100644 index 00000000000..ed951be6d6d --- /dev/null +++ b/cmd/mdatagen/testdata/invalid_type_attr.yaml @@ -0,0 +1,24 @@ +type: metricreceiver + +sem_conv_version: 1.9.0 + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + +attributes: + used_attr: + description: Used attribute. + type: invalidtype + +metrics: + metric: + enabled: true + description: Metric. + unit: 1 + gauge: + value_type: double + attributes: [used_attr] diff --git a/cmd/mdatagen/testdata/invalid_type_rattr.yaml b/cmd/mdatagen/testdata/invalid_type_rattr.yaml new file mode 100644 index 00000000000..90e9c33dae3 --- /dev/null +++ b/cmd/mdatagen/testdata/invalid_type_rattr.yaml @@ -0,0 +1,19 @@ +type: file + +sem_conv_version: 1.9.0 + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + distributions: [contrib] + warnings: + - Any additional information that should be brought to the consumer's attention + +resource_attributes: + string.resource.attr: + description: Resource attribute with any string value. + type: invalidtype + enabled: true diff --git a/cmd/mdatagen/testdata/metrics_and_type.yaml b/cmd/mdatagen/testdata/metrics_and_type.yaml new file mode 100644 index 00000000000..81d66bde9c1 --- /dev/null +++ b/cmd/mdatagen/testdata/metrics_and_type.yaml @@ -0,0 +1,19 @@ +type: metricreceiver + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + distributions: [contrib] + warnings: + - Any additional information that should be brought to the consumer's attention + +metrics: + metric: + enabled: true + description: Description. + unit: s + gauge: + value_type: double diff --git a/cmd/mdatagen/testdata/no_aggregation.yaml b/cmd/mdatagen/testdata/no_aggregation.yaml new file mode 100644 index 00000000000..02c14b6b1e7 --- /dev/null +++ b/cmd/mdatagen/testdata/no_aggregation.yaml @@ -0,0 +1,22 @@ +type: file + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + distributions: [contrib] + warnings: + - Any additional information that should be brought to the consumer's attention + + +metrics: + default.metric: + enabled: true + description: Monotonic cumulative sum int metric enabled by default. + extended_documentation: The metric will be become optional soon. + unit: s + sum: + value_type: int + monotonic: false \ No newline at end of file diff --git a/cmd/mdatagen/testdata/no_class.yaml b/cmd/mdatagen/testdata/no_class.yaml new file mode 100644 index 00000000000..8d33f9c019a --- /dev/null +++ b/cmd/mdatagen/testdata/no_class.yaml @@ -0,0 +1,7 @@ +type: test + +status: + stability: + development: [logs] + beta: [traces] + stable: [metrics] \ No newline at end of file diff --git a/cmd/mdatagen/testdata/no_description_attr.yaml b/cmd/mdatagen/testdata/no_description_attr.yaml new file mode 100644 index 00000000000..1942f74e111 --- /dev/null +++ b/cmd/mdatagen/testdata/no_description_attr.yaml @@ -0,0 +1,33 @@ +# Sample metric metadata file with all available configurations. + +type: file + +sem_conv_version: 1.9.0 + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + distributions: [contrib] + warnings: + - Any additional information that should be brought to the consumer's attention + +attributes: + string_attr: + type: string + +metrics: + default.metric: + enabled: true + description: Monotonic cumulative sum int metric enabled by default. + extended_documentation: The metric will be become optional soon. + unit: s + sum: + value_type: int + monotonic: true + aggregation_temporality: cumulative + attributes: [string_attr] + warnings: + if_enabled_not_set: This metric will be disabled by default soon. diff --git a/cmd/mdatagen/testdata/no_description_rattr.yaml b/cmd/mdatagen/testdata/no_description_rattr.yaml new file mode 100644 index 00000000000..d489eaa7cb6 --- /dev/null +++ b/cmd/mdatagen/testdata/no_description_rattr.yaml @@ -0,0 +1,12 @@ +type: file +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + +resource_attributes: + string.resource.attr: + type: string + enabled: true diff --git a/cmd/mdatagen/testdata/no_enabled.yaml b/cmd/mdatagen/testdata/no_enabled.yaml new file mode 100644 index 00000000000..ab1dfafed32 --- /dev/null +++ b/cmd/mdatagen/testdata/no_enabled.yaml @@ -0,0 +1,18 @@ +type: metricreceiver + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + +metrics: + system.cpu.time: + description: Total CPU seconds broken down by different states. + unit: s + sum: + value_type: double + monotonic: true + aggregation_temporality: cumulative + attributes: diff --git a/cmd/mdatagen/testdata/no_metric_description.yaml b/cmd/mdatagen/testdata/no_metric_description.yaml new file mode 100644 index 00000000000..de9cbd42087 --- /dev/null +++ b/cmd/mdatagen/testdata/no_metric_description.yaml @@ -0,0 +1,22 @@ +type: file + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + distributions: [contrib] + warnings: + - Any additional information that should be brought to the consumer's attention + + +metrics: + default.metric: + enabled: true + extended_documentation: The metric will be become optional soon. + unit: s + sum: + value_type: int + monotonic: true + aggregation_temporality: cumulative diff --git a/cmd/mdatagen/testdata/no_metric_type.yaml b/cmd/mdatagen/testdata/no_metric_type.yaml new file mode 100644 index 00000000000..1f0e0283f2a --- /dev/null +++ b/cmd/mdatagen/testdata/no_metric_type.yaml @@ -0,0 +1,13 @@ +type: metricreceiver +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] +metrics: + system.cpu.time: + enabled: true + description: Total CPU seconds broken down by different states. + unit: s + attributes: diff --git a/cmd/mdatagen/testdata/no_metric_unit.yaml b/cmd/mdatagen/testdata/no_metric_unit.yaml new file mode 100644 index 00000000000..cc5c49a7c9a --- /dev/null +++ b/cmd/mdatagen/testdata/no_metric_unit.yaml @@ -0,0 +1,22 @@ +type: file + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + distributions: [contrib] + warnings: + - Any additional information that should be brought to the consumer's attention + + +metrics: + default.metric: + enabled: true + description: Monotonic cumulative sum int metric enabled by default. + extended_documentation: The metric will be become optional soon. + sum: + value_type: int + monotonic: true + aggregation_temporality: cumulative diff --git a/cmd/mdatagen/testdata/no_monotonic.yaml b/cmd/mdatagen/testdata/no_monotonic.yaml new file mode 100644 index 00000000000..2f99cecab58 --- /dev/null +++ b/cmd/mdatagen/testdata/no_monotonic.yaml @@ -0,0 +1,22 @@ +type: file + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + distributions: [contrib] + warnings: + - Any additional information that should be brought to the consumer's attention + + +metrics: + default.metric: + enabled: true + description: Monotonic cumulative sum int metric enabled by default. + extended_documentation: The metric will be become optional soon. + unit: s + sum: + value_type: int + aggregation_temporality: cumulative diff --git a/cmd/mdatagen/testdata/no_stability.yaml b/cmd/mdatagen/testdata/no_stability.yaml new file mode 100644 index 00000000000..29b00be6ffa --- /dev/null +++ b/cmd/mdatagen/testdata/no_stability.yaml @@ -0,0 +1,4 @@ +type: test + +status: + class: receiver \ No newline at end of file diff --git a/cmd/mdatagen/testdata/no_stability_component.yaml b/cmd/mdatagen/testdata/no_stability_component.yaml new file mode 100644 index 00000000000..9c0631e8bec --- /dev/null +++ b/cmd/mdatagen/testdata/no_stability_component.yaml @@ -0,0 +1,6 @@ +type: file +status: + class: receiver + stability: + beta: + stable: [metrics] \ No newline at end of file diff --git a/cmd/mdatagen/testdata/no_status.yaml b/cmd/mdatagen/testdata/no_status.yaml new file mode 100644 index 00000000000..75db25c3b05 --- /dev/null +++ b/cmd/mdatagen/testdata/no_status.yaml @@ -0,0 +1 @@ +type: test \ No newline at end of file diff --git a/cmd/mdatagen/testdata/no_type.yaml b/cmd/mdatagen/testdata/no_type.yaml new file mode 100644 index 00000000000..72d92e5dee8 --- /dev/null +++ b/cmd/mdatagen/testdata/no_type.yaml @@ -0,0 +1,6 @@ +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] \ No newline at end of file diff --git a/cmd/mdatagen/testdata/no_type_attr.yaml b/cmd/mdatagen/testdata/no_type_attr.yaml new file mode 100644 index 00000000000..914a9820bda --- /dev/null +++ b/cmd/mdatagen/testdata/no_type_attr.yaml @@ -0,0 +1,23 @@ +type: metricreceiver + +sem_conv_version: 1.9.0 + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + +attributes: + used_attr: + description: Used attribute. + +metrics: + metric: + enabled: true + description: Metric. + unit: 1 + gauge: + value_type: double + attributes: [used_attr] diff --git a/cmd/mdatagen/testdata/no_type_rattr.yaml b/cmd/mdatagen/testdata/no_type_rattr.yaml new file mode 100644 index 00000000000..e6961b1801e --- /dev/null +++ b/cmd/mdatagen/testdata/no_type_rattr.yaml @@ -0,0 +1,18 @@ +type: file + +sem_conv_version: 1.9.0 + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + distributions: [contrib] + warnings: + - Any additional information that should be brought to the consumer's attention + +resource_attributes: + string.resource.attr: + description: Resource attribute with any string value. + enabled: true \ No newline at end of file diff --git a/cmd/mdatagen/testdata/no_value_type.yaml b/cmd/mdatagen/testdata/no_value_type.yaml new file mode 100644 index 00000000000..046f457b510 --- /dev/null +++ b/cmd/mdatagen/testdata/no_value_type.yaml @@ -0,0 +1,22 @@ +type: metricreceiver + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + distributions: [contrib] + warnings: + - Any additional information that should be brought to the consumer's attention + + +metrics: + system.cpu.time: + enabled: true + description: Total CPU seconds broken down by different states. + unit: s + sum: + monotonic: true + aggregation_temporality: cumulative + attributes: diff --git a/cmd/mdatagen/testdata/parent.yaml b/cmd/mdatagen/testdata/parent.yaml new file mode 100644 index 00000000000..1f8fc15ba17 --- /dev/null +++ b/cmd/mdatagen/testdata/parent.yaml @@ -0,0 +1,3 @@ +type: subcomponent + +parent: parentComponent \ No newline at end of file diff --git a/cmd/mdatagen/testdata/readme_with_cmd_class.md b/cmd/mdatagen/testdata/readme_with_cmd_class.md new file mode 100644 index 00000000000..71a8ad7598c --- /dev/null +++ b/cmd/mdatagen/testdata/readme_with_cmd_class.md @@ -0,0 +1,14 @@ +# Some component + + +| Status | | +| ------------- |-----------| +| Stability | [alpha]: logs | +| | [beta]: metrics | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Acmd%2Ffoo%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Acmd%2Ffoo) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Acmd%2Ffoo%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Acmd%2Ffoo) | + +[alpha]: https://github.com/open-telemetry/opentelemetry-collector#alpha +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta + + +Some info about a component diff --git a/cmd/mdatagen/testdata/readme_with_multiple_signals.md b/cmd/mdatagen/testdata/readme_with_multiple_signals.md new file mode 100644 index 00000000000..8de1ed6221a --- /dev/null +++ b/cmd/mdatagen/testdata/readme_with_multiple_signals.md @@ -0,0 +1,15 @@ +# Some component + + +| Status | | +| ------------- |-----------| +| Stability | [alpha]: logs | +| | [beta]: metrics | +| Distributions | [contrib] | + +[alpha]: https://github.com/open-telemetry/opentelemetry-collector#alpha +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + + +Some info about a component diff --git a/cmd/mdatagen/testdata/readme_with_status.md b/cmd/mdatagen/testdata/readme_with_status.md new file mode 100644 index 00000000000..92e0b1f4258 --- /dev/null +++ b/cmd/mdatagen/testdata/readme_with_status.md @@ -0,0 +1,14 @@ +# Some component + + +| Status | | +| ------------- |-----------| +| Stability | [beta]: metrics | +| Distributions | [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Areceiver%2Ffoo%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Areceiver%2Ffoo) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Areceiver%2Ffoo%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Areceiver%2Ffoo) | + +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + + +Some info about a component diff --git a/cmd/mdatagen/testdata/readme_with_status_codeowners.md b/cmd/mdatagen/testdata/readme_with_status_codeowners.md new file mode 100644 index 00000000000..f350b593360 --- /dev/null +++ b/cmd/mdatagen/testdata/readme_with_status_codeowners.md @@ -0,0 +1,15 @@ +# Some component + + +| Status | | +| ------------- |-----------| +| Stability | [beta]: metrics | +| Distributions | [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Areceiver%2Ffoo%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Areceiver%2Ffoo) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Areceiver%2Ffoo%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Areceiver%2Ffoo) | +| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@foo](https://www.github.com/foo) | + +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + + +Some info about a component diff --git a/cmd/mdatagen/testdata/readme_with_status_codeowners_and_emeritus.md b/cmd/mdatagen/testdata/readme_with_status_codeowners_and_emeritus.md new file mode 100644 index 00000000000..203de2f3dd0 --- /dev/null +++ b/cmd/mdatagen/testdata/readme_with_status_codeowners_and_emeritus.md @@ -0,0 +1,16 @@ +# Some component + + +| Status | | +| ------------- |-----------| +| Stability | [beta]: metrics | +| Distributions | [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Areceiver%2Ffoo%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Areceiver%2Ffoo) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Areceiver%2Ffoo%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Areceiver%2Ffoo) | +| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@foo](https://www.github.com/foo) | +| Emeritus | [@bar](https://www.github.com/bar) | + +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + + +Some info about a component diff --git a/cmd/mdatagen/testdata/readme_with_status_codeowners_and_seeking_new.md b/cmd/mdatagen/testdata/readme_with_status_codeowners_and_seeking_new.md new file mode 100644 index 00000000000..f396db459d4 --- /dev/null +++ b/cmd/mdatagen/testdata/readme_with_status_codeowners_and_seeking_new.md @@ -0,0 +1,15 @@ +# Some component + + +| Status | | +| ------------- |-----------| +| Stability | [beta]: metrics | +| Distributions | [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Areceiver%2Ffoo%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Areceiver%2Ffoo) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Areceiver%2Ffoo%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Areceiver%2Ffoo) | +| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@foo](https://www.github.com/foo) \| Seeking more code owners! | + +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + + +Some info about a component diff --git a/cmd/mdatagen/testdata/readme_with_status_extension.md b/cmd/mdatagen/testdata/readme_with_status_extension.md new file mode 100644 index 00000000000..1c454afe9a9 --- /dev/null +++ b/cmd/mdatagen/testdata/readme_with_status_extension.md @@ -0,0 +1,14 @@ +# Some component + + +| Status | | +| ------------- |-----------| +| Stability | [beta] | +| Distributions | [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aextension%2Ffoo%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aextension%2Ffoo) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aextension%2Ffoo%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aextension%2Ffoo) | + +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + + +Some info about a component diff --git a/cmd/mdatagen/testdata/readme_with_warnings.md b/cmd/mdatagen/testdata/readme_with_warnings.md new file mode 100644 index 00000000000..6cf1afa3866 --- /dev/null +++ b/cmd/mdatagen/testdata/readme_with_warnings.md @@ -0,0 +1,16 @@ +# Some component + + +| Status | | +| ------------- |-----------| +| Stability | [beta]: metrics | +| Distributions | [contrib] | +| Warnings | [warning1](#warnings) | + +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + + +Some info about a component +### warnings +Some warning there. diff --git a/cmd/mdatagen/testdata/readme_without_status.md b/cmd/mdatagen/testdata/readme_without_status.md new file mode 100644 index 00000000000..be610f8c087 --- /dev/null +++ b/cmd/mdatagen/testdata/readme_without_status.md @@ -0,0 +1,3 @@ +# Some component + +Some info about a component diff --git a/cmd/mdatagen/testdata/resource_attributes_only.yaml b/cmd/mdatagen/testdata/resource_attributes_only.yaml new file mode 100644 index 00000000000..05e031bcf45 --- /dev/null +++ b/cmd/mdatagen/testdata/resource_attributes_only.yaml @@ -0,0 +1,17 @@ +type: test + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + distributions: [contrib] + warnings: + - Any additional information that should be brought to the consumer's attention + +resource_attributes: + res.attr1: + description: Resource attribute 1. + type: string + enabled: true diff --git a/cmd/mdatagen/testdata/status_only.yaml b/cmd/mdatagen/testdata/status_only.yaml new file mode 100644 index 00000000000..2365b43f1d9 --- /dev/null +++ b/cmd/mdatagen/testdata/status_only.yaml @@ -0,0 +1,6 @@ +type: metricreceiver +status: + class: exporter + stability: + beta: [traces, metrics, logs] + distributions: [contrib] diff --git a/cmd/mdatagen/testdata/two_metric_types.yaml b/cmd/mdatagen/testdata/two_metric_types.yaml new file mode 100644 index 00000000000..572eab2f3bc --- /dev/null +++ b/cmd/mdatagen/testdata/two_metric_types.yaml @@ -0,0 +1,21 @@ +type: metricreceiver + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + +metrics: + system.cpu.time: + enabled: true + description: Total CPU seconds broken down by different states. + unit: s + gauge: + value_type: double + sum: + value_type: double + monotonic: true + aggregation_temporality: cumulative + attributes: diff --git a/cmd/mdatagen/testdata/unknown_metric_attribute.yaml b/cmd/mdatagen/testdata/unknown_metric_attribute.yaml new file mode 100644 index 00000000000..d86b5afe401 --- /dev/null +++ b/cmd/mdatagen/testdata/unknown_metric_attribute.yaml @@ -0,0 +1,19 @@ +type: metricreceiver + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + +metrics: + system.cpu.time: + enabled: true + description: Total CPU seconds broken down by different states. + unit: s + sum: + value_type: double + monotonic: true + aggregation_temporality: cumulative + attributes: [missing] diff --git a/cmd/mdatagen/testdata/unknown_value_type.yaml b/cmd/mdatagen/testdata/unknown_value_type.yaml new file mode 100644 index 00000000000..1a4890045d8 --- /dev/null +++ b/cmd/mdatagen/testdata/unknown_value_type.yaml @@ -0,0 +1,18 @@ +type: metricreceiver + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + +metrics: + system.cpu.time: + enabled: true + description: Total CPU seconds broken down by different states. + unit: s + sum: + value_type: unknown + monotonic: true + aggregation_temporality: cumulative diff --git a/cmd/mdatagen/testdata/unused_attribute.yaml b/cmd/mdatagen/testdata/unused_attribute.yaml new file mode 100644 index 00000000000..cc0eb08f767 --- /dev/null +++ b/cmd/mdatagen/testdata/unused_attribute.yaml @@ -0,0 +1,29 @@ +type: metricreceiver + +sem_conv_version: 1.9.0 + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + +attributes: + used_attr: + description: Used attribute. + type: string + + unused_attr: + name_override: state + description: Unused attribute. + type: string + +metrics: + metric: + enabled: true + description: Metric. + unit: 1 + gauge: + value_type: double + attributes: [used_attr] diff --git a/cmd/mdatagen/testdata/with_tests_connector.yaml b/cmd/mdatagen/testdata/with_tests_connector.yaml new file mode 100644 index 00000000000..ad05872698e --- /dev/null +++ b/cmd/mdatagen/testdata/with_tests_connector.yaml @@ -0,0 +1,9 @@ +type: foobar + +status: + class: connector + stability: + beta: [traces_to_metrics, traces_to_traces, traces_to_logs, metrics_to_logs, metrics_to_metrics, metrics_to_traces, logs_to_logs, logs_to_metrics, logs_to_traces] + +tests: + config: diff --git a/cmd/mdatagen/testdata/with_tests_exporter.yaml b/cmd/mdatagen/testdata/with_tests_exporter.yaml new file mode 100644 index 00000000000..e110f3d10e3 --- /dev/null +++ b/cmd/mdatagen/testdata/with_tests_exporter.yaml @@ -0,0 +1,9 @@ +type: metric + +status: + class: exporter + stability: + beta: [traces, logs, metrics] + +tests: + config: diff --git a/cmd/mdatagen/testdata/with_tests_extension.yaml b/cmd/mdatagen/testdata/with_tests_extension.yaml new file mode 100644 index 00000000000..08eb4d5cf29 --- /dev/null +++ b/cmd/mdatagen/testdata/with_tests_extension.yaml @@ -0,0 +1,9 @@ +type: metric + +status: + class: extension + stability: + beta: [extension] + +tests: + config: diff --git a/cmd/mdatagen/testdata/with_tests_processor.yaml b/cmd/mdatagen/testdata/with_tests_processor.yaml new file mode 100644 index 00000000000..fa6a2238f2c --- /dev/null +++ b/cmd/mdatagen/testdata/with_tests_processor.yaml @@ -0,0 +1,9 @@ +type: metric + +status: + class: processor + stability: + beta: [traces, logs, metrics] + +tests: + config: diff --git a/cmd/mdatagen/testdata/with_tests_receiver.yaml b/cmd/mdatagen/testdata/with_tests_receiver.yaml new file mode 100644 index 00000000000..e55c6190728 --- /dev/null +++ b/cmd/mdatagen/testdata/with_tests_receiver.yaml @@ -0,0 +1,9 @@ +type: metric + +status: + class: receiver + stability: + beta: [traces, logs, metrics] + +tests: + config: diff --git a/cmd/mdatagen/third_party/golint/LICENSE b/cmd/mdatagen/third_party/golint/LICENSE new file mode 100644 index 00000000000..65d761bc9f2 --- /dev/null +++ b/cmd/mdatagen/third_party/golint/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/cmd/mdatagen/third_party/golint/golint.go b/cmd/mdatagen/third_party/golint/golint.go new file mode 100644 index 00000000000..f4898aaebd5 --- /dev/null +++ b/cmd/mdatagen/third_party/golint/golint.go @@ -0,0 +1,51 @@ +// Copyright (c) 2013 The Go Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd. + +package golint + +// See https://github.com/golang/lint/blob/d0100b6bd8b389f0385611eb39152c4d7c3a7905/lint.go#L771 + +// Acronyms is a list of known acronyms that should not be formatted when linting. +var Acronyms = map[string]bool{ + "ACL": true, + "API": true, + "ASCII": true, + "CPU": true, + "CSS": true, + "DNS": true, + "EOF": true, + "GUID": true, + "HTML": true, + "HTTP": true, + "HTTPS": true, + "ID": true, + "IP": true, + "JSON": true, + "LHS": true, + "QPS": true, + "RAM": true, + "RHS": true, + "RPC": true, + "SLA": true, + "SMTP": true, + "SQL": true, + "SSH": true, + "TCP": true, + "TLS": true, + "TTL": true, + "UDP": true, + "UI": true, + "UID": true, + "UUID": true, + "URI": true, + "URL": true, + "UTF8": true, + "VM": true, + "XML": true, + "XMPP": true, + "XSRF": true, + "XSS": true, +} diff --git a/cmd/mdatagen/validate.go b/cmd/mdatagen/validate.go new file mode 100644 index 00000000000..bc56375baf9 --- /dev/null +++ b/cmd/mdatagen/validate.go @@ -0,0 +1,205 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "errors" + "fmt" + "regexp" + + "go.uber.org/multierr" + + "go.opentelemetry.io/collector/pdata/pcommon" +) + +func (md *metadata) Validate() error { + var errs error + if err := md.validateType(); err != nil { + errs = multierr.Append(errs, err) + } + if err := md.validateStatus(); err != nil { + errs = multierr.Append(errs, err) + } + if err := md.validateResourceAttributes(); err != nil { + errs = multierr.Append(errs, err) + } + if err := md.validateMetrics(); err != nil { + errs = multierr.Append(errs, err) + } + return errs +} + +// typeRegexp is used to validate the type of a component. +// A type must start with an ASCII alphabetic character and +// can only contain ASCII alphanumeric characters and '_'. +// This must be kept in sync with the regex in component/config.go. +var typeRegexp = regexp.MustCompile(`^[a-zA-Z][0-9a-zA-Z_]*$`) + +func (md *metadata) validateType() error { + if md.Type == "" { + return errors.New("missing type") + } + + if !typeRegexp.MatchString(md.Type) { + return fmt.Errorf("invalid character(s) in type %q", md.Type) + } + return nil +} + +func (md *metadata) validateStatus() error { + if md.Parent != "" && md.Status == nil { + // status is not required for subcomponents. + return nil + } + + var errs error + if md.Status == nil { + return errors.New("missing status") + } + if err := md.Status.validateClass(); err != nil { + errs = multierr.Append(errs, err) + } + if md.Parent == "" { + if err := md.Status.validateStability(); err != nil { + errs = multierr.Append(errs, err) + } + } + return errs +} + +func (s *Status) validateClass() error { + if s.Class == "" { + return errors.New("missing class") + } + if s.Class != "receiver" && s.Class != "processor" && s.Class != "exporter" && s.Class != "connector" && s.Class != "extension" && s.Class != "cmd" && s.Class != "pkg" { + return fmt.Errorf("invalid class: %v", s.Class) + } + return nil +} + +func (s *Status) validateStability() error { + var errs error + if len(s.Stability) == 0 { + return errors.New("missing stability") + } + for stability, component := range s.Stability { + if stability != "development" && stability != "alpha" && stability != "beta" && stability != "stable" && stability != "deprecated" && stability != "unmaintained" { + errs = multierr.Append(errs, fmt.Errorf("invalid stability: %v", stability)) + } + if component == nil { + errs = multierr.Append(errs, fmt.Errorf("missing component for stability: %v", stability)) + } + for _, c := range component { + if c != "metrics" && + c != "traces" && + c != "logs" && + c != "traces_to_traces" && + c != "traces_to_metrics" && + c != "traces_to_logs" && + c != "metrics_to_traces" && + c != "metrics_to_metrics" && + c != "metrics_to_logs" && + c != "logs_to_traces" && + c != "logs_to_metrics" && + c != "logs_to_logs" && + c != "extension" { + errs = multierr.Append(errs, fmt.Errorf("invalid component: %v", c)) + } + } + } + return errs +} + +func (md *metadata) validateResourceAttributes() error { + var errs error + for name, attr := range md.ResourceAttributes { + if attr.Description == "" { + errs = multierr.Append(errs, fmt.Errorf("empty description for resource attribute: %v", name)) + } + empty := ValueType{ValueType: pcommon.ValueTypeEmpty} + if attr.Type == empty { + errs = multierr.Append(errs, fmt.Errorf("empty type for resource attribute: %v", name)) + } + } + return errs +} + +func (md *metadata) validateMetrics() error { + var errs error + usedAttrs := map[attributeName]bool{} + for mn, m := range md.Metrics { + if m.Sum == nil && m.Gauge == nil { + errs = multierr.Append(errs, fmt.Errorf("metric %v doesn't have a metric type key, "+ + "one of the following has to be specified: sum, gauge", mn)) + continue + } + if m.Sum != nil && m.Gauge != nil { + errs = multierr.Append(errs, fmt.Errorf("metric %v has more than one metric type keys, "+ + "only one of the following has to be specified: sum, gauge", mn)) + continue + } + if err := m.validate(); err != nil { + errs = multierr.Append(errs, fmt.Errorf(`metric "%v": %w`, mn, err)) + continue + } + unknownAttrs := make([]attributeName, 0, len(m.Attributes)) + for _, attr := range m.Attributes { + if _, ok := md.Attributes[attr]; ok { + usedAttrs[attr] = true + } else { + unknownAttrs = append(unknownAttrs, attr) + } + } + if len(unknownAttrs) > 0 { + errs = multierr.Append(errs, fmt.Errorf(`metric "%v" refers to undefined attributes: %v`, mn, unknownAttrs)) + } + } + errs = multierr.Append(errs, md.validateAttributes(usedAttrs)) + return errs +} + +func (m *metric) validate() error { + var errs error + if m.Description == "" { + errs = multierr.Append(errs, errors.New(`missing metric description`)) + } + if m.Unit == nil { + errs = multierr.Append(errs, errors.New(`missing metric unit`)) + } + if m.Sum != nil { + errs = multierr.Append(errs, m.Sum.Validate()) + } + if m.Gauge != nil { + errs = multierr.Append(errs, m.Gauge.Validate()) + } + return errs +} + +func (mit MetricInputType) Validate() error { + if mit.InputType != "" && mit.InputType != "string" { + return fmt.Errorf("invalid `input_type` value \"%v\", must be \"\" or \"string\"", mit.InputType) + } + return nil +} + +func (md *metadata) validateAttributes(usedAttrs map[attributeName]bool) error { + var errs error + unusedAttrs := make([]attributeName, 0, len(md.Attributes)) + for attrName, attr := range md.Attributes { + if attr.Description == "" { + errs = multierr.Append(errs, fmt.Errorf(`missing attribute description for: %v`, attrName)) + } + empty := ValueType{ValueType: pcommon.ValueTypeEmpty} + if attr.Type == empty { + errs = multierr.Append(errs, fmt.Errorf("empty type for attribute: %v", attrName)) + } + if !usedAttrs[attrName] { + unusedAttrs = append(unusedAttrs, attrName) + } + } + if len(unusedAttrs) > 0 { + errs = multierr.Append(errs, fmt.Errorf("unused attributes: %v", unusedAttrs)) + } + return errs +} diff --git a/cmd/mdatagen/validate_test.go b/cmd/mdatagen/validate_test.go new file mode 100644 index 00000000000..4c2ddea5741 --- /dev/null +++ b/cmd/mdatagen/validate_test.go @@ -0,0 +1,153 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "fmt" + "io/fs" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestValidate(t *testing.T) { + tests := []struct { + name string + wantErr string + }{ + { + name: "testdata/no_type.yaml", + wantErr: "missing type", + }, + { + name: "testdata/no_status.yaml", + wantErr: "missing status", + }, + { + name: "testdata/no_class.yaml", + wantErr: "missing class", + }, + { + name: "testdata/invalid_class.yaml", + wantErr: "invalid class: incorrectclass", + }, + { + name: "testdata/no_stability.yaml", + wantErr: "missing stability", + }, + { + name: "testdata/invalid_stability.yaml", + wantErr: "invalid stability: incorrectstability", + }, + { + name: "testdata/no_stability_component.yaml", + wantErr: "missing component for stability: beta", + }, + { + name: "testdata/invalid_stability_component.yaml", + wantErr: "invalid component: incorrectcomponent", + }, + { + name: "testdata/no_description_rattr.yaml", + wantErr: "empty description for resource attribute: string.resource.attr", + }, + { + name: "testdata/no_type_rattr.yaml", + wantErr: "empty type for resource attribute: string.resource.attr", + }, + { + name: "testdata/no_metric_description.yaml", + wantErr: "metric \"default.metric\": missing metric description", + }, + { + name: "testdata/no_metric_unit.yaml", + wantErr: "metric \"default.metric\": missing metric unit", + }, + { + name: "testdata/no_metric_type.yaml", + wantErr: "metric system.cpu.time doesn't have a metric type key, " + + "one of the following has to be specified: sum, gauge", + }, + { + name: "testdata/two_metric_types.yaml", + wantErr: "metric system.cpu.time has more than one metric type keys, " + + "only one of the following has to be specified: sum, gauge", + }, + { + name: "testdata/invalid_input_type.yaml", + wantErr: "metric \"system.cpu.time\": invalid `input_type` value \"double\", must be \"\" or \"string\"", + }, + { + name: "testdata/unknown_metric_attribute.yaml", + wantErr: "metric \"system.cpu.time\" refers to undefined attributes: [missing]", + }, + { + name: "testdata/unused_attribute.yaml", + wantErr: "unused attributes: [unused_attr]", + }, + { + name: "testdata/no_description_attr.yaml", + wantErr: "missing attribute description for: string_attr", + }, + { + name: "testdata/no_type_attr.yaml", + wantErr: "empty type for attribute: used_attr", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := loadMetadata(tt.name) + require.Error(t, err) + require.EqualError(t, err, tt.wantErr) + }) + } +} + +func TestValidateMetricDuplicates(t *testing.T) { + allowedMetrics := map[string][]string{ + "container.cpu.utilization": {"docker_stats", "kubeletstats"}, + "container.memory.rss": {"docker_stats", "kubeletstats"}, + "container.uptime": {"docker_stats", "kubeletstats"}, + } + allMetrics := map[string][]string{} + err := filepath.Walk("../../receiver", func(path string, info fs.FileInfo, _ error) error { + if info.Name() == "metadata.yaml" { + md, err := loadMetadata(path) + require.NoError(t, err) + if len(md.Metrics) > 0 { + for metricName := range md.Metrics { + allMetrics[md.Type] = append(allMetrics[md.Type], string(metricName)) + } + } + } + return nil + }) + require.NoError(t, err) + + seen := make(map[string]string) + for receiver, metrics := range allMetrics { + for _, metricName := range metrics { + if val, exists := seen[metricName]; exists { + receivers, allowed := allowedMetrics[metricName] + assert.True( + t, + allowed && contains(receiver, receivers) && contains(val, receivers), + fmt.Sprintf("Duplicate metric %v in receivers %v and %v. Please validate that this is intentional by adding the metric name and receiver types in the allowedMetrics map in this test\n", metricName, receiver, val), + ) + } + seen[metricName] = receiver + } + } +} + +func contains(r string, rs []string) bool { + for _, s := range rs { + if s == r { + return true + } + } + return false +} diff --git a/cmd/otelcorecol/builder-config.yaml b/cmd/otelcorecol/builder-config.yaml index ea0005bf285..d528d09964d 100644 --- a/cmd/otelcorecol/builder-config.yaml +++ b/cmd/otelcorecol/builder-config.yaml @@ -2,24 +2,25 @@ dist: module: go.opentelemetry.io/collector/cmd/otelcorecol name: otelcorecol description: Local OpenTelemetry Collector binary, testing only. - version: 0.85.0-dev - otelcol_version: 0.85.0 + version: 0.96.0-dev + otelcol_version: 0.96.0 receivers: - - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.85.0 + - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.96.0 exporters: - - gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.85.0 - - gomod: go.opentelemetry.io/collector/exporter/loggingexporter v0.85.0 - - gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.85.0 - - gomod: go.opentelemetry.io/collector/exporter/otlphttpexporter v0.85.0 + - gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.96.0 + - gomod: go.opentelemetry.io/collector/exporter/loggingexporter v0.96.0 + - gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.96.0 + - gomod: go.opentelemetry.io/collector/exporter/otlphttpexporter v0.96.0 extensions: - - gomod: go.opentelemetry.io/collector/extension/ballastextension v0.85.0 - - gomod: go.opentelemetry.io/collector/extension/zpagesextension v0.85.0 + - gomod: go.opentelemetry.io/collector/extension/ballastextension v0.96.0 + - gomod: go.opentelemetry.io/collector/extension/memorylimiterextension v0.96.0 + - gomod: go.opentelemetry.io/collector/extension/zpagesextension v0.96.0 processors: - - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.85.0 - - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.85.0 + - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.96.0 + - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.96.0 connectors: - - gomod: go.opentelemetry.io/collector/connector/forwardconnector v0.85.0 + - gomod: go.opentelemetry.io/collector/connector/forwardconnector v0.96.0 replaces: - go.opentelemetry.io/collector => ../../ @@ -31,10 +32,17 @@ replaces: - go.opentelemetry.io/collector/config/confighttp => ../../config/confighttp - go.opentelemetry.io/collector/config/confignet => ../../config/confignet - go.opentelemetry.io/collector/config/configopaque => ../../config/configopaque + - go.opentelemetry.io/collector/config/configretry => ../../config/configretry - go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry - go.opentelemetry.io/collector/config/configtls => ../../config/configtls - go.opentelemetry.io/collector/config/internal => ../../config/internal - go.opentelemetry.io/collector/confmap => ../../confmap + - go.opentelemetry.io/collector/confmap/converter/expandconverter => ../../confmap/converter/expandconverter + - go.opentelemetry.io/collector/confmap/provider/envprovider => ../../confmap/provider/envprovider + - go.opentelemetry.io/collector/confmap/provider/fileprovider => ../../confmap/provider/fileprovider + - go.opentelemetry.io/collector/confmap/provider/httpprovider => ../../confmap/provider/httpprovider + - go.opentelemetry.io/collector/confmap/provider/httpsprovider => ../../confmap/provider/httpsprovider + - go.opentelemetry.io/collector/confmap/provider/yamlprovider => ../../confmap/provider/yamlprovider - go.opentelemetry.io/collector/consumer => ../../consumer - go.opentelemetry.io/collector/connector => ../../connector - go.opentelemetry.io/collector/connector/forwardconnector => ../../connector/forwardconnector @@ -46,6 +54,7 @@ replaces: - go.opentelemetry.io/collector/extension => ../../extension - go.opentelemetry.io/collector/extension/auth => ../../extension/auth - go.opentelemetry.io/collector/extension/ballastextension => ../../extension/ballastextension + - go.opentelemetry.io/collector/extension/memorylimiterextension => ../../extension/memorylimiterextension - go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension - go.opentelemetry.io/collector/featuregate => ../../featuregate - go.opentelemetry.io/collector/pdata => ../../pdata diff --git a/cmd/otelcorecol/components.go b/cmd/otelcorecol/components.go index 170c7b55b5b..786743099b9 100644 --- a/cmd/otelcorecol/components.go +++ b/cmd/otelcorecol/components.go @@ -12,6 +12,7 @@ import ( otlphttpexporter "go.opentelemetry.io/collector/exporter/otlphttpexporter" "go.opentelemetry.io/collector/extension" ballastextension "go.opentelemetry.io/collector/extension/ballastextension" + memorylimiterextension "go.opentelemetry.io/collector/extension/memorylimiterextension" zpagesextension "go.opentelemetry.io/collector/extension/zpagesextension" "go.opentelemetry.io/collector/otelcol" "go.opentelemetry.io/collector/processor" @@ -27,6 +28,7 @@ func components() (otelcol.Factories, error) { factories.Extensions, err = extension.MakeFactoryMap( ballastextension.NewFactory(), + memorylimiterextension.NewFactory(), zpagesextension.NewFactory(), ) if err != nil { diff --git a/cmd/otelcorecol/go.mod b/cmd/otelcorecol/go.mod index 591510f158f..a9a702bd1b5 100644 --- a/cmd/otelcorecol/go.mod +++ b/cmd/otelcorecol/go.mod @@ -2,126 +2,132 @@ module go.opentelemetry.io/collector/cmd/otelcorecol -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/connector v0.85.0 - go.opentelemetry.io/collector/connector/forwardconnector v0.85.0 - go.opentelemetry.io/collector/exporter v0.85.0 - go.opentelemetry.io/collector/exporter/debugexporter v0.85.0 - go.opentelemetry.io/collector/exporter/loggingexporter v0.85.0 - go.opentelemetry.io/collector/exporter/otlpexporter v0.85.0 - go.opentelemetry.io/collector/exporter/otlphttpexporter v0.85.0 - go.opentelemetry.io/collector/extension v0.85.0 - go.opentelemetry.io/collector/extension/ballastextension v0.85.0 - go.opentelemetry.io/collector/extension/zpagesextension v0.85.0 - go.opentelemetry.io/collector/otelcol v0.0.0-00010101000000-000000000000 - go.opentelemetry.io/collector/processor v0.85.0 - go.opentelemetry.io/collector/processor/batchprocessor v0.85.0 - go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.85.0 - go.opentelemetry.io/collector/receiver v0.85.0 - go.opentelemetry.io/collector/receiver/otlpreceiver v0.85.0 - golang.org/x/sys v0.12.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/connector v0.96.0 + go.opentelemetry.io/collector/connector/forwardconnector v0.96.0 + go.opentelemetry.io/collector/exporter v0.96.0 + go.opentelemetry.io/collector/exporter/debugexporter v0.96.0 + go.opentelemetry.io/collector/exporter/loggingexporter v0.96.0 + go.opentelemetry.io/collector/exporter/otlpexporter v0.96.0 + go.opentelemetry.io/collector/exporter/otlphttpexporter v0.96.0 + go.opentelemetry.io/collector/extension v0.96.0 + go.opentelemetry.io/collector/extension/ballastextension v0.96.0 + go.opentelemetry.io/collector/extension/memorylimiterextension v0.96.0 + go.opentelemetry.io/collector/extension/zpagesextension v0.96.0 + go.opentelemetry.io/collector/otelcol v0.96.0 + go.opentelemetry.io/collector/processor v0.96.0 + go.opentelemetry.io/collector/processor/batchprocessor v0.96.0 + go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.96.0 + go.opentelemetry.io/collector/receiver v0.96.0 + go.opentelemetry.io/collector/receiver/otlpreceiver v0.96.0 + go.uber.org/goleak v1.3.0 + golang.org/x/sys v0.17.0 ) require ( - contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect + cloud.google.com/go/compute v1.24.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/felixge/httpsnoop v1.0.3 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/google/uuid v1.3.1 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.0 // indirect + github.com/klauspost/compress v1.17.7 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/mostynb/go-grpc-compression v1.2.1 // indirect + github.com/mostynb/go-grpc-compression v1.2.2 // 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.16.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect - github.com/prometheus/statsd_exporter v0.22.7 // indirect - github.com/rs/cors v1.10.0 // indirect - github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/rs/cors v1.10.1 // indirect + github.com/shirou/gopsutil/v3 v3.24.1 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect - github.com/spf13/cobra v1.7.0 // indirect + github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector v0.85.0 // indirect - go.opentelemetry.io/collector/config/configauth v0.85.0 // indirect - go.opentelemetry.io/collector/config/configcompression v0.85.0 // indirect - go.opentelemetry.io/collector/config/configgrpc v0.85.0 // indirect - go.opentelemetry.io/collector/config/confighttp v0.85.0 // indirect - go.opentelemetry.io/collector/config/confignet v0.85.0 // indirect - go.opentelemetry.io/collector/config/configopaque v0.85.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 // indirect - go.opentelemetry.io/collector/config/configtls v0.85.0 // indirect - go.opentelemetry.io/collector/config/internal v0.85.0 // indirect - go.opentelemetry.io/collector/confmap v0.85.0 // indirect - go.opentelemetry.io/collector/consumer v0.85.0 // indirect - go.opentelemetry.io/collector/extension/auth v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/semconv v0.85.0 // indirect - go.opentelemetry.io/collector/service v0.0.0-20230915215502-07938f20fcc7 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 // indirect - go.opentelemetry.io/contrib/propagators/b3 v1.19.0 // indirect - go.opentelemetry.io/contrib/zpages v0.44.0 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/bridge/opencensus v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/sdk v1.18.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.0 // indirect + go.opentelemetry.io/collector v0.96.0 // indirect + go.opentelemetry.io/collector/config/configauth v0.96.0 // indirect + go.opentelemetry.io/collector/config/configcompression v0.96.0 // indirect + go.opentelemetry.io/collector/config/configgrpc v0.96.0 // indirect + go.opentelemetry.io/collector/config/confighttp v0.96.0 // indirect + go.opentelemetry.io/collector/config/confignet v0.96.0 // indirect + go.opentelemetry.io/collector/config/configopaque v1.3.0 // indirect + go.opentelemetry.io/collector/config/configretry v0.96.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/config/configtls v0.96.0 // indirect + go.opentelemetry.io/collector/config/internal v0.96.0 // indirect + go.opentelemetry.io/collector/confmap v0.96.0 // indirect + go.opentelemetry.io/collector/confmap/converter/expandconverter v0.96.0 // indirect + go.opentelemetry.io/collector/confmap/provider/envprovider v0.96.0 // indirect + go.opentelemetry.io/collector/confmap/provider/fileprovider v0.96.0 // indirect + go.opentelemetry.io/collector/confmap/provider/httpprovider v0.96.0 // indirect + go.opentelemetry.io/collector/confmap/provider/httpsprovider v0.96.0 // indirect + go.opentelemetry.io/collector/confmap/provider/yamlprovider v0.96.0 // indirect + go.opentelemetry.io/collector/consumer v0.96.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.96.0 // indirect + go.opentelemetry.io/collector/featuregate v1.3.0 // indirect + go.opentelemetry.io/collector/pdata v1.3.0 // indirect + go.opentelemetry.io/collector/semconv v0.96.0 // indirect + go.opentelemetry.io/collector/service v0.96.0 // indirect + go.opentelemetry.io/contrib/config v0.4.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.24.0 // indirect + go.opentelemetry.io/contrib/zpages v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/bridge/opencensus v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/text v0.13.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/oauth2 v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect gonum.org/v1/gonum v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240221002015-b0ce06bbee7c // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -143,6 +149,8 @@ replace go.opentelemetry.io/collector/config/confignet => ../../config/confignet replace go.opentelemetry.io/collector/config/configopaque => ../../config/configopaque +replace go.opentelemetry.io/collector/config/configretry => ../../config/configretry + replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry replace go.opentelemetry.io/collector/config/configtls => ../../config/configtls @@ -151,6 +159,18 @@ replace go.opentelemetry.io/collector/config/internal => ../../config/internal replace go.opentelemetry.io/collector/confmap => ../../confmap +replace go.opentelemetry.io/collector/confmap/converter/expandconverter => ../../confmap/converter/expandconverter + +replace go.opentelemetry.io/collector/confmap/provider/envprovider => ../../confmap/provider/envprovider + +replace go.opentelemetry.io/collector/confmap/provider/fileprovider => ../../confmap/provider/fileprovider + +replace go.opentelemetry.io/collector/confmap/provider/httpprovider => ../../confmap/provider/httpprovider + +replace go.opentelemetry.io/collector/confmap/provider/httpsprovider => ../../confmap/provider/httpsprovider + +replace go.opentelemetry.io/collector/confmap/provider/yamlprovider => ../../confmap/provider/yamlprovider + replace go.opentelemetry.io/collector/consumer => ../../consumer replace go.opentelemetry.io/collector/connector => ../../connector @@ -173,6 +193,8 @@ replace go.opentelemetry.io/collector/extension/auth => ../../extension/auth replace go.opentelemetry.io/collector/extension/ballastextension => ../../extension/ballastextension +replace go.opentelemetry.io/collector/extension/memorylimiterextension => ../../extension/memorylimiterextension + replace go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension replace go.opentelemetry.io/collector/featuregate => ../../featuregate @@ -192,6 +214,3 @@ replace go.opentelemetry.io/collector/processor/memorylimiterprocessor => ../../ replace go.opentelemetry.io/collector/semconv => ../../semconv replace go.opentelemetry.io/collector/service => ../../service - -// ambiguous import: found package cloud.google.com/go/compute/metadata in multiple modules -replace cloud.google.com/go => cloud.google.com/go v0.110.2 diff --git a/cmd/otelcorecol/go.sum b/cmd/otelcorecol/go.sum index c62b1d5b3bb..b8a1209e827 100644 --- a/cmd/otelcorecol/go.sum +++ b/cmd/otelcorecol/go.sum @@ -1,1407 +1,287 @@ -cloud.google.com/go v0.110.2 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA= -cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= -cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= -cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= -cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= -cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= -cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= -cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= -cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= -cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= -cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= -cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= -cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= -cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= -cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= -cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= -cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= -cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= -cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= -cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= -cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= -cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= -cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= -cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= -cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= -cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= -cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= -cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= -cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= -cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= -cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= -cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= -cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= -cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= -cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= -cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= -cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= -cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= -cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= -cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= -cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= -cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= -cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= -cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= -cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= -cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= -cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= -cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= -cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= -cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= -cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= -cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= -cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= -cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= -cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= -cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= -cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= -cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= -cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= -cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= -cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= -cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= -cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= -cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= -cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= -cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= -cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= -cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= -cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= -cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= -cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= -cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= -cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= -cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= -cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= -cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= -cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= -cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= -cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= -cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= -cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= -cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= -cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= -cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= -cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= -cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= -cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= -cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= -cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= -cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= -cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= -cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= -cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= -cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= -cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= -cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= -cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= -cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= -cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= -cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= -cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= -cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= -cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= -cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= -cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= -cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= -cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= -cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= -cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= -cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= -cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= -cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= -cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= -cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= -cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= -cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= -cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= -cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= -cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= -cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= -cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= +cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68 h1:aRVqY1p2IJaBGStWMsQMpkAa83cPkCDLl80eOj0Rbz4= -cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= -cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= -cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= -cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= -cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= -cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= -cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= -cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= -cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= -cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= -cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= -cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= -cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= -cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= -cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= -cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= -cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= -cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= -cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= -cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= -cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= -cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= -cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= -cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= -cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= -cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= -cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= -cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= -cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= -cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= -cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= -cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= -cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= -cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= -cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= -cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= -cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= -cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= -cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= -cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= -cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= -cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= -cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= -cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= -cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= -cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= -cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= -cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= -cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= -cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= -cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= -cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= -cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= -cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= -cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= -cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= -cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= -cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= -cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= -cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= -cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= -cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= -cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= -cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= -cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= -cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= -cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= -cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= -cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= -cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= -cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= -cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= -cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= -cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= -cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= -cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= -cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= -cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= -cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= -cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= -cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= -cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= -cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= -cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= -cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= -cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= -cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= -cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= -cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= -cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= -cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= -cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= -cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= -cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= -cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= -cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= -cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= -cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= -cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= -cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= -cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= -cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= -cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= -cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= -cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= -cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= -cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= -cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= -cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= -cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= -cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= -cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= -cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= -cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= -cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= -cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= -cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= -cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= -cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= -cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= -cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= -cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= -cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= -cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= -cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= -cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= -cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= -cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= -cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= -cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= -cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= -cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= -cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= -cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= -cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= -cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= -cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= -cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= -cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= -cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= -cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= -cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= -cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= -cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= -cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= -cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= -cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= -cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= -cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= -cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= -cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= -cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= -cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= -cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= -cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= -cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= -cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= -cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= -cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= -cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= -cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= -cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= -cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= -cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= -cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= -cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= -cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= -cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= -cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= -cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= -cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= -cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= -cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= -cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= -cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= -cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= -cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= -cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= -cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= -cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= -cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= -cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= -cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= -cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= -cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= -cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= -cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= -cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= -cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= -cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= -cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= -cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= -cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= -cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= -cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= -cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= -cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= -cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= -cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= -cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= -cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= -cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= -cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= -cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= -cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= -cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= -cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= -cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= -cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= -cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= -cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= -cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= -cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= -cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= -cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= -cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= -cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= -cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= -cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= -cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= -cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= -cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= -cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= -cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= -cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= -cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= -cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= -cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= -cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= -cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= -cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= -cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= -cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= -cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= -cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= -cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= -cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= -cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= -cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= -cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= -cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= -cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= -cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= -cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= -cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= -cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= -cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= -cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= -cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= -cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= -cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= -cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= -cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= -cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= -cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= -cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= -cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= -cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= -cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= -cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= -cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= -cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= -cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= -cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= -cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= -cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= -cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= -cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= -cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= -cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= -cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= -cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= -cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= -cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= -cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= -cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= -cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= -cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= -cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= -cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= -cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= -cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= -cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= -cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= -cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= -cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= -cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= -cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= -cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= -cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= -cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= -cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= -cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= -cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= -cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= -cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= -cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= -cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= -cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= -cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= -cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= -cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= -cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= -cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= -cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= -cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= -cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= -cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= -cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= -cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= -cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= -cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= -cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= -cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= -cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= -cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= -cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= -cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= -cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= -cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= -cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= -cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= -cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= -cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= -cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= -cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= -cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= -cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= -cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= -cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= -cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= -cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= -cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= -cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= -cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= -cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= -cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= -cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= -cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= -cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= -cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= -cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= -cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= -cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= -cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= -cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= -cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= -cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= -cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= -cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= -cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= -cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= -cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= -cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= -cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= -cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= -cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= -cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= -cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= -cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= -cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= -cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= -cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= -cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= -cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= -cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= -cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= -cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= -cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= -cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= -cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= -cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= -cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= -cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= -cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= -cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= -cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= -cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= -cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= -cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= -cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= -cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= -git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= +cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68/go.mod h1:1a3eRNYX12fs5UABBIXS8HXVvQbX9hRB/RkEBPORpe8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= -github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= -github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= -github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= -github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= -github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= -github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= -github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= -github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= -github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= -github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= -github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= -github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mostynb/go-grpc-compression v1.2.1 h1:16tdYxBZSD8p9AUmvw4F7Nyc2T4/eE7XsIXrgxSEcJI= -github.com/mostynb/go-grpc-compression v1.2.1/go.mod h1:oidYvYyefMmhcuvU8fLJ8FfZyTyVzJ6SkmD5fIKgRe8= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= -github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/mostynb/go-grpc-compression v1.2.2 h1:XaDbnRvt2+1vgr0b/l0qh4mJAfIxE0bKXtz2Znl3GGI= +github.com/mostynb/go-grpc-compression v1.2.2/go.mod h1:GOCr2KBxXcblCuczg3YdLQlcin1/NfyDA348ckuCH6w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rs/cors v1.10.0 h1:62NOS1h+r8p1mW6FM0FSB0exioXLhd/sh15KpjWBZ+8= -github.com/rs/cors v1.10.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= -github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= -github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= -github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= +github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48= -go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= -go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ= -go.opentelemetry.io/contrib/zpages v0.44.0 h1:9J/cxTTWhM6kzgdaBt6NiXS2HUreXn/eW2M+vzHgDAQ= -go.opentelemetry.io/contrib/zpages v0.44.0/go.mod h1:G3eNCGhodjn2wIdM+i6GneZb1Cqg6dNRBlm1cpNEElg= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/bridge/opencensus v0.41.0 h1:VBpeaTbrvLFHvRtsyCJXjsTaicBNrAFdmctiN1k6WNI= -go.opentelemetry.io/otel/bridge/opencensus v0.41.0/go.mod h1:yCQB5IKRhgjlbTLc91+ixcZc2/8BncGGJ+CS3dZJwtY= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 h1:k0k7hFNDd8K4iOMJXj7s8sHaC4mhTlAeppRmZXLgZ6k= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 h1:HgbDTD8pioFdY3NRc/YCvsWjqQPtweGyXxa32LgnTOw= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0/go.mod h1:tmvt/yK5Es5d6lHYWerLSOna8lCEfrBVX/a9M0ggqss= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.41.0 h1:iV3BOgW4fry1Riw9dwypigqlIYWXvSRVT2RJmblzo40= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.41.0/go.mod h1:7PGzqlKrxIRmbj5tlNW0nTkYZ5fHXDgk6Fy8/KjR0CI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.18.0 h1:6pu8ttx76BxHf+xz/H77AUZkPF3cwWzXqAUsXhVKI18= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.18.0/go.mod h1:IOmXxPrxoxFMXdNy7lfDmE8MzE61YPcurbUm0SMjerI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 h1:XzjGkawtAXs20Y+s6k1GNDMBsMDOV28TOT8cxmE42qM= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0/go.mod h1:HAomEgjcKZk3VJ+HHdHLnhZXeGqdzPxxNTdKYRopUXY= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/contrib/config v0.4.0 h1:Xb+ncYOqseLroMuBesGNRgVQolXcXOhMj7EhGwJCdHs= +go.opentelemetry.io/contrib/config v0.4.0/go.mod h1:drNk2xRqLWW4/amk6Uh1S+sDAJTc7bcEEN1GfJzj418= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 h1:P+/g8GpuJGYbOp2tAdKrIPUX9JO02q8Q0YNlHolpibA= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/contrib/propagators/b3 v1.24.0 h1:n4xwCdTx3pZqZs2CjS/CUZAs03y3dZcGhC/FepKtEUY= +go.opentelemetry.io/contrib/propagators/b3 v1.24.0/go.mod h1:k5wRxKRU2uXx2F8uNJ4TaonuEO/V7/5xoz7kdsDACT8= +go.opentelemetry.io/contrib/zpages v0.49.0 h1:Wk217PkNBxcKWnIQpwtbZZE286K4ZY9uajnM5woSeLU= +go.opentelemetry.io/contrib/zpages v0.49.0/go.mod h1:6alLi5mmkZWbAtZMRPd1ffIgkTcsU9OTHQF2NbSOhrQ= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/bridge/opencensus v1.24.0 h1:Vlhy5ee5k5R0zASpH+9AgHiJH7xnKACI3XopO1tUZfY= +go.opentelemetry.io/otel/bridge/opencensus v1.24.0/go.mod h1:jRjVXV/X38jyrnHtvMGN8+9cejZB21JvXAAvooF2s+Q= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0 h1:f2jriWfOdldanBwS9jNBdeOKAQN7b4ugAMaNu1/1k9g= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0/go.mod h1:B+bcQI1yTY+N0vqMpoZbEN7+XU4tNM0DmUiOwebFJWI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0 h1:mM8nKi6/iFQ0iqst80wDHU2ge198Ye/TfN0WBS5U24Y= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0/go.mod h1:0PrIIzDteLSmNyxqcGYRL4mDIo8OTuBAOI/Bn1URxac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.24.0 h1:JYE2HM7pZbOt5Jhk8ndWZTUWYOVift2cHjXVMkPdmdc= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.24.0/go.mod h1:yMb/8c6hVsnma0RpsBMNo0fEiQKeclawtgaIaOp2MLY= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= -golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= +golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= -gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= -gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= -google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= -google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= -google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= -google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= -google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= -google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= -google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -google.golang.org/api v0.118.0/go.mod h1:76TtD3vkgmZ66zZzp72bUUklpmQmKlhh6sYtIjYK+5E= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= -google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= -google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= -google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= -google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= -google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= -google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= -google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= +google.golang.org/genproto/googleapis/api v0.0.0-20240221002015-b0ce06bbee7c h1:9g7erC9qu44ks7UK4gDNlnk4kOxZG707xKm4jVniy6o= +google.golang.org/genproto/googleapis/api v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c h1:NUsgEN92SQQqzfA+YtqYNqYmB3DMMYLlIwUZAQFVFbo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= -google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1410,71 +290,16 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= -modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= -modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= -modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= -modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= -modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= -modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= -modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= -modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= -modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= -modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= -modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= -modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= -modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= -modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= -modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/cmd/otelcorecol/main.go b/cmd/otelcorecol/main.go index e087028fa45..2ab2d3c7249 100644 --- a/cmd/otelcorecol/main.go +++ b/cmd/otelcorecol/main.go @@ -11,18 +11,13 @@ import ( ) func main() { - factories, err := components() - if err != nil { - log.Fatalf("failed to build components: %v", err) - } - info := component.BuildInfo{ Command: "otelcorecol", Description: "Local OpenTelemetry Collector binary, testing only.", - Version: "0.85.0-dev", + Version: "0.96.0-dev", } - if err := run(otelcol.CollectorSettings{BuildInfo: info, Factories: factories}); err != nil { + if err := run(otelcol.CollectorSettings{BuildInfo: info, Factories: components}); err != nil { log.Fatal(err) } } diff --git a/cmd/otelcorecol/main_others.go b/cmd/otelcorecol/main_others.go index e80a51cd4e0..3735aecb586 100644 --- a/cmd/otelcorecol/main_others.go +++ b/cmd/otelcorecol/main_others.go @@ -1,7 +1,6 @@ // Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT. //go:build !windows -// +build !windows package main diff --git a/cmd/otelcorecol/main_windows.go b/cmd/otelcorecol/main_windows.go index ad96fd1e801..fbae5bdc97b 100644 --- a/cmd/otelcorecol/main_windows.go +++ b/cmd/otelcorecol/main_windows.go @@ -1,48 +1,29 @@ // Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT. //go:build windows -// +build windows package main import ( + "errors" "fmt" - "os" + "golang.org/x/sys/windows" "golang.org/x/sys/windows/svc" "go.opentelemetry.io/collector/otelcol" ) func run(params otelcol.CollectorSettings) error { - if useInteractiveMode, err := checkUseInteractiveMode(); err != nil { - return err - } else if useInteractiveMode { - return runInteractive(params) - } else { - return runService(params) - } -} - -func checkUseInteractiveMode() (bool, error) { - // If environment variable NO_WINDOWS_SERVICE is set with any value other - // than 0, use interactive mode instead of running as a service. This should - // be set in case running as a service is not possible or desired even - // though the current session is not detected to be interactive - if value, present := os.LookupEnv("NO_WINDOWS_SERVICE"); present && value != "0" { - return true, nil - } - - isInteractiveSession, err := svc.IsAnInteractiveSession() - if err != nil { - return false, fmt.Errorf("failed to determine if we are running in an interactive session: %w", err) - } - return isInteractiveSession, nil -} - -func runService(params otelcol.CollectorSettings) error { - // do not need to supply service name when startup is invoked through Service Control Manager directly + // No need to supply service name when startup is invoked through + // the Service Control Manager directly. if err := svc.Run("", otelcol.NewSvcHandler(params)); err != nil { + if errors.Is(err, windows.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { + // Per https://learn.microsoft.com/en-us/windows/win32/api/winsvc/nf-winsvc-startservicectrldispatchera#return-value + // this means that the process is not running as a service, so run interactively. + return runInteractive(params) + } + return fmt.Errorf("failed to start collector server: %w", err) } diff --git a/cmd/otelcorecol/package_test.go b/cmd/otelcorecol/package_test.go new file mode 100644 index 00000000000..c5c48c671cc --- /dev/null +++ b/cmd/otelcorecol/package_test.go @@ -0,0 +1,17 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "testing" + + "go.uber.org/goleak" +) + +// The IgnoreTopFunction call prevents catching the leak generated by opencensus +// defaultWorker.Start which at this time is part of the package's init call. +// See https://github.com/open-telemetry/opentelemetry-collector/issues/9165#issuecomment-1874836336 for more context. +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m, goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start")) +} diff --git a/component/component.go b/component/component.go index 9a6a95d798a..32d69f7eda0 100644 --- a/component/component.go +++ b/component/component.go @@ -11,6 +11,8 @@ import ( var ( // ErrNilNextConsumer can be returned by receiver, or processor Start factory funcs that create the Component if the // expected next Consumer is nil. + // Deprecated: [v0.96.0] The next consumer is now checked as part of the creation of the pipelines. + // This error will be removed in a future release. ErrNilNextConsumer = errors.New("nil next Consumer") // ErrDataTypeIsNotSupported can be returned by receiver, exporter or processor factory funcs that create the @@ -96,6 +98,22 @@ const ( KindConnector ) +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 "" +} + // StabilityLevel represents the stability level of the component created by the factory. // The stability level is used to determine if the component should be used in production // or not. For more details see: @@ -175,3 +193,10 @@ type CreateDefaultConfigFunc func() Config func (f CreateDefaultConfigFunc) CreateDefaultConfig() Config { return f() } + +// InstanceID uniquely identifies a component instance +type InstanceID struct { + ID ID + Kind Kind + PipelineIDs map[ID]struct{} +} diff --git a/component/component_test.go b/component/component_test.go index 4f8df15a6e6..8b694fb4303 100644 --- a/component/component_test.go +++ b/component/component_test.go @@ -9,6 +9,16 @@ import ( "github.com/stretchr/testify/assert" ) +func TestKindString(t *testing.T) { + assert.EqualValues(t, "", Kind(0).String()) + assert.EqualValues(t, "Receiver", KindReceiver.String()) + assert.EqualValues(t, "Processor", KindProcessor.String()) + assert.EqualValues(t, "Exporter", KindExporter.String()) + assert.EqualValues(t, "Extension", KindExtension.String()) + assert.EqualValues(t, "Connector", KindConnector.String()) + assert.EqualValues(t, "", Kind(100).String()) +} + func TestStabilityLevelString(t *testing.T) { assert.EqualValues(t, "Undefined", StabilityLevelUndefined.String()) assert.EqualValues(t, "Unmaintained", StabilityLevelUnmaintained.String()) diff --git a/component/componenttest/nop_host.go b/component/componenttest/nop_host.go index 4accfab0d8c..ea85ccc8bbe 100644 --- a/component/componenttest/nop_host.go +++ b/component/componenttest/nop_host.go @@ -15,9 +15,7 @@ func NewNopHost() component.Host { return &nopHost{} } -func (nh *nopHost) ReportFatalError(_ error) {} - -func (nh *nopHost) GetFactory(_ component.Kind, _ component.Type) component.Factory { +func (nh *nopHost) GetFactory(component.Kind, component.Type) component.Factory { return nil } diff --git a/component/componenttest/nop_host_test.go b/component/componenttest/nop_host_test.go index 1bcb92d1744..4aada24b1be 100644 --- a/component/componenttest/nop_host_test.go +++ b/component/componenttest/nop_host_test.go @@ -4,7 +4,6 @@ package componenttest import ( - "errors" "testing" "github.com/stretchr/testify/assert" @@ -18,8 +17,7 @@ func TestNewNopHost(t *testing.T) { require.NotNil(t, nh) require.IsType(t, &nopHost{}, nh) - nh.ReportFatalError(errors.New("TestError")) assert.Nil(t, nh.GetExporters()) // nolint: staticcheck assert.Nil(t, nh.GetExtensions()) - assert.Nil(t, nh.GetFactory(component.KindReceiver, "test")) + assert.Nil(t, nh.GetFactory(component.KindReceiver, component.MustNewType("test"))) } diff --git a/component/componenttest/nop_telemetry.go b/component/componenttest/nop_telemetry.go index 438f9ec761a..171e9daa47e 100644 --- a/component/componenttest/nop_telemetry.go +++ b/component/componenttest/nop_telemetry.go @@ -4,8 +4,8 @@ package componenttest // import "go.opentelemetry.io/collector/component/componenttest" import ( - "go.opentelemetry.io/otel/metric/noop" - "go.opentelemetry.io/otel/trace" + noopmetric "go.opentelemetry.io/otel/metric/noop" + nooptrace "go.opentelemetry.io/otel/trace/noop" "go.uber.org/zap" "go.opentelemetry.io/collector/component" @@ -17,9 +17,11 @@ import ( func NewNopTelemetrySettings() component.TelemetrySettings { return component.TelemetrySettings{ Logger: zap.NewNop(), - TracerProvider: trace.NewNoopTracerProvider(), - MeterProvider: noop.NewMeterProvider(), + TracerProvider: nooptrace.NewTracerProvider(), + MeterProvider: noopmetric.NewMeterProvider(), MetricsLevel: configtelemetry.LevelNone, Resource: pcommon.NewResource(), + ReportStatus: func(*component.StatusEvent) { + }, } } diff --git a/obsreport/obsreporttest/obsreporttest.go b/component/componenttest/obsreporttest.go similarity index 57% rename from obsreport/obsreporttest/obsreporttest.go rename to component/componenttest/obsreporttest.go index 0ea42ab7734..f342879a533 100644 --- a/obsreport/obsreporttest/obsreporttest.go +++ b/component/componenttest/obsreporttest.go @@ -1,14 +1,13 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package obsreporttest // import "go.opentelemetry.io/collector/obsreport/obsreporttest" +package componenttest // import "go.opentelemetry.io/collector/component/componenttest" import ( "context" - ocprom "contrib.go.opencensus.io/exporter/prometheus" "github.com/prometheus/client_golang/prometheus" - "go.opencensus.io/stats/view" + "github.com/prometheus/client_golang/prometheus/promhttp" otelprom "go.opentelemetry.io/otel/exporters/prometheus" sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" @@ -17,15 +16,7 @@ import ( "go.uber.org/multierr" "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/config/configtelemetry" - "go.opentelemetry.io/collector/exporter" - "go.opentelemetry.io/collector/exporter/exportertest" - "go.opentelemetry.io/collector/internal/obsreportconfig" - "go.opentelemetry.io/collector/processor" - "go.opentelemetry.io/collector/processor/processortest" - "go.opentelemetry.io/collector/receiver" - "go.opentelemetry.io/collector/receiver/receivertest" ) const ( @@ -43,95 +34,92 @@ const ( ) type TestTelemetry struct { - component.TelemetrySettings + ts component.TelemetrySettings id component.ID SpanRecorder *tracetest.SpanRecorder - views []*view.View - otelPrometheusChecker *prometheusChecker - meterProvider *sdkmetric.MeterProvider - ocExporter *ocprom.Exporter -} - -// ToExporterCreateSettings returns an exporter.CreateSettings with configured TelemetrySettings. -// -// Deprecated: [0.85.0] Use exportertest.NewCreateSettings instead -func (tts *TestTelemetry) ToExporterCreateSettings() exporter.CreateSettings { - return exportertest.NewCreateSettings(tts.id, tts.TelemetrySettings) -} - -// ToProcessorCreateSettings returns a processor.CreateSettings with configured TelemetrySettings. -// -// Deprecated: [0.85.0] Use processortest.NewCreateSettings instead -func (tts *TestTelemetry) ToProcessorCreateSettings() processor.CreateSettings { - return processortest.NewCreateSettings(tts.id, tts.TelemetrySettings) -} - -// ToReceiverCreateSettings returns a receiver.CreateSettings with configured TelemetrySettings. -// -// Deprecated: [0.85.0] Use receivertest.NewCreateSettings instead -func (tts *TestTelemetry) ToReceiverCreateSettings() receiver.CreateSettings { - return receivertest.NewCreateSettings(tts.id, tts.TelemetrySettings) + prometheusChecker *prometheusChecker + meterProvider *sdkmetric.MeterProvider } // CheckExporterTraces checks that for the current exported values for trace exporter metrics match given values. // When this function is called it is required to also call SetupTelemetry as first thing. func (tts *TestTelemetry) CheckExporterTraces(sentSpans, sendFailedSpans int64) error { - return tts.otelPrometheusChecker.checkExporterTraces(tts.id, sentSpans, sendFailedSpans) + return tts.prometheusChecker.checkExporterTraces(tts.id, sentSpans, sendFailedSpans) } // CheckExporterMetrics checks that for the current exported values for metrics exporter metrics match given values. // When this function is called it is required to also call SetupTelemetry as first thing. func (tts *TestTelemetry) CheckExporterMetrics(sentMetricsPoints, sendFailedMetricsPoints int64) error { - return tts.otelPrometheusChecker.checkExporterMetrics(tts.id, sentMetricsPoints, sendFailedMetricsPoints) + return tts.prometheusChecker.checkExporterMetrics(tts.id, sentMetricsPoints, sendFailedMetricsPoints) +} + +func (tts *TestTelemetry) CheckExporterEnqueueFailedMetrics(enqueueFailed int64) error { + return tts.prometheusChecker.checkExporterEnqueueFailed(tts.id, "metric_points", enqueueFailed) +} + +func (tts *TestTelemetry) CheckExporterEnqueueFailedTraces(enqueueFailed int64) error { + return tts.prometheusChecker.checkExporterEnqueueFailed(tts.id, "spans", enqueueFailed) +} + +func (tts *TestTelemetry) CheckExporterEnqueueFailedLogs(enqueueFailed int64) error { + return tts.prometheusChecker.checkExporterEnqueueFailed(tts.id, "log_records", enqueueFailed) } // CheckExporterLogs checks that for the current exported values for logs exporter metrics match given values. // When this function is called it is required to also call SetupTelemetry as first thing. func (tts *TestTelemetry) CheckExporterLogs(sentLogRecords, sendFailedLogRecords int64) error { - return tts.otelPrometheusChecker.checkExporterLogs(tts.id, sentLogRecords, sendFailedLogRecords) + return tts.prometheusChecker.checkExporterLogs(tts.id, sentLogRecords, sendFailedLogRecords) +} + +func (tts *TestTelemetry) CheckExporterMetricGauge(metric string, val int64) error { + return tts.prometheusChecker.checkExporterMetricGauge(tts.id, metric, val) } // CheckProcessorTraces checks that for the current exported values for trace exporter metrics match given values. // When this function is called it is required to also call SetupTelemetry as first thing. func (tts *TestTelemetry) CheckProcessorTraces(acceptedSpans, refusedSpans, droppedSpans int64) error { - return tts.otelPrometheusChecker.checkProcessorTraces(tts.id, acceptedSpans, refusedSpans, droppedSpans) + return tts.prometheusChecker.checkProcessorTraces(tts.id, acceptedSpans, refusedSpans, droppedSpans) } // CheckProcessorMetrics checks that for the current exported values for metrics exporter metrics match given values. // When this function is called it is required to also call SetupTelemetry as first thing. func (tts *TestTelemetry) CheckProcessorMetrics(acceptedMetricPoints, refusedMetricPoints, droppedMetricPoints int64) error { - return tts.otelPrometheusChecker.checkProcessorMetrics(tts.id, acceptedMetricPoints, refusedMetricPoints, droppedMetricPoints) + return tts.prometheusChecker.checkProcessorMetrics(tts.id, acceptedMetricPoints, refusedMetricPoints, droppedMetricPoints) } // CheckProcessorLogs checks that for the current exported values for logs exporter metrics match given values. // When this function is called it is required to also call SetupTelemetry as first thing. func (tts *TestTelemetry) CheckProcessorLogs(acceptedLogRecords, refusedLogRecords, droppedLogRecords int64) error { - return tts.otelPrometheusChecker.checkProcessorLogs(tts.id, acceptedLogRecords, refusedLogRecords, droppedLogRecords) + return tts.prometheusChecker.checkProcessorLogs(tts.id, acceptedLogRecords, refusedLogRecords, droppedLogRecords) } // CheckReceiverTraces checks that for the current exported values for trace receiver metrics match given values. // When this function is called it is required to also call SetupTelemetry as first thing. func (tts *TestTelemetry) CheckReceiverTraces(protocol string, acceptedSpans, droppedSpans int64) error { - return tts.otelPrometheusChecker.checkReceiverTraces(tts.id, protocol, acceptedSpans, droppedSpans) + return tts.prometheusChecker.checkReceiverTraces(tts.id, protocol, acceptedSpans, droppedSpans) } // CheckReceiverLogs checks that for the current exported values for logs receiver metrics match given values. // When this function is called it is required to also call SetupTelemetry as first thing. func (tts *TestTelemetry) CheckReceiverLogs(protocol string, acceptedLogRecords, droppedLogRecords int64) error { - return tts.otelPrometheusChecker.checkReceiverLogs(tts.id, protocol, acceptedLogRecords, droppedLogRecords) + return tts.prometheusChecker.checkReceiverLogs(tts.id, protocol, acceptedLogRecords, droppedLogRecords) } // CheckReceiverMetrics checks that for the current exported values for metrics receiver metrics match given values. // When this function is called it is required to also call SetupTelemetry as first thing. func (tts *TestTelemetry) CheckReceiverMetrics(protocol string, acceptedMetricPoints, droppedMetricPoints int64) error { - return tts.otelPrometheusChecker.checkReceiverMetrics(tts.id, protocol, acceptedMetricPoints, droppedMetricPoints) + return tts.prometheusChecker.checkReceiverMetrics(tts.id, protocol, acceptedMetricPoints, droppedMetricPoints) +} + +// CheckScraperMetrics checks that for the current exported values for metrics scraper metrics match given values. +// When this function is called it is required to also call SetupTelemetry as first thing. +func (tts *TestTelemetry) CheckScraperMetrics(receiver component.ID, scraper component.ID, scrapedMetricPoints, erroredMetricPoints int64) error { + return tts.prometheusChecker.checkScraperMetrics(receiver, scraper, scrapedMetricPoints, erroredMetricPoints) } // Shutdown unregisters any views and shuts down the SpanRecorder func (tts *TestTelemetry) Shutdown(ctx context.Context) error { - view.Unregister(tts.views...) - view.UnregisterExporter(tts.ocExporter) var errs error errs = multierr.Append(errs, tts.SpanRecorder.Shutdown(ctx)) if tts.meterProvider != nil { @@ -140,6 +128,11 @@ func (tts *TestTelemetry) Shutdown(ctx context.Context) error { return errs } +// TelemetrySettings returns the TestTelemetry's TelemetrySettings +func (tts *TestTelemetry) TelemetrySettings() component.TelemetrySettings { + return tts.ts +} + // SetupTelemetry does setup the testing environment to check the metrics recorded by receivers, producers or exporters. // The caller must pass the ID of the component that intends to test, so the CreateSettings and Check methods will use. // The caller should defer a call to Shutdown the returned TestTelemetry. @@ -148,27 +141,16 @@ func SetupTelemetry(id component.ID) (TestTelemetry, error) { tp := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) settings := TestTelemetry{ - TelemetrySettings: componenttest.NewNopTelemetrySettings(), - id: id, - SpanRecorder: sr, + ts: NewNopTelemetrySettings(), + id: id, + SpanRecorder: sr, } - settings.TelemetrySettings.TracerProvider = tp - settings.TelemetrySettings.MetricsLevel = configtelemetry.LevelNormal - settings.views = obsreportconfig.AllViews(configtelemetry.LevelNormal) - err := view.Register(settings.views...) - if err != nil { - return settings, err - } - - promReg := prometheus.NewRegistry() + settings.ts.TracerProvider = tp + settings.ts.MetricsLevel = configtelemetry.LevelNormal - settings.ocExporter, err = ocprom.NewExporter(ocprom.Options{Registry: promReg}) - if err != nil { - return settings, err - } - view.RegisterExporter(settings.ocExporter) + promRegOtel := prometheus.NewRegistry() - exp, err := otelprom.New(otelprom.WithRegisterer(promReg), otelprom.WithoutUnits(), otelprom.WithoutScopeInfo()) + exp, err := otelprom.New(otelprom.WithRegisterer(promRegOtel), otelprom.WithoutUnits(), otelprom.WithoutScopeInfo(), otelprom.WithoutCounterSuffixes()) if err != nil { return settings, err } @@ -177,15 +159,11 @@ func SetupTelemetry(id component.ID) (TestTelemetry, error) { sdkmetric.WithResource(resource.Empty()), sdkmetric.WithReader(exp), ) - settings.TelemetrySettings.MeterProvider = settings.meterProvider + settings.ts.MeterProvider = settings.meterProvider - settings.otelPrometheusChecker = &prometheusChecker{promHandler: settings.ocExporter} + settings.prometheusChecker = &prometheusChecker{ + otelHandler: promhttp.HandlerFor(promRegOtel, promhttp.HandlerOpts{}), + } return settings, nil } - -// CheckScraperMetrics checks that for the current exported values for metrics scraper metrics match given values. -// When this function is called it is required to also call SetupTelemetry as first thing. -func CheckScraperMetrics(tts TestTelemetry, receiver component.ID, scraper component.ID, scrapedMetricPoints, erroredMetricPoints int64) error { - return tts.otelPrometheusChecker.checkScraperMetrics(receiver, scraper, scrapedMetricPoints, erroredMetricPoints) -} diff --git a/obsreport/obsreporttest/otelprometheuschecker.go b/component/componenttest/otelprometheuschecker.go similarity index 55% rename from obsreport/obsreporttest/otelprometheuschecker.go rename to component/componenttest/otelprometheuschecker.go index b5bcafb8ba8..878bfd0a37a 100644 --- a/obsreport/obsreporttest/otelprometheuschecker.go +++ b/component/componenttest/otelprometheuschecker.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package obsreporttest // import "go.opentelemetry.io/collector/obsreport/obsreporttest" +package componenttest // import "go.opentelemetry.io/collector/component/componenttest" import ( "fmt" @@ -11,7 +11,6 @@ import ( io_prometheus_client "github.com/prometheus/client_model/go" "github.com/prometheus/common/expfmt" - "go.opencensus.io/stats/view" "go.opentelemetry.io/otel/attribute" "go.uber.org/multierr" @@ -20,7 +19,7 @@ import ( // prometheusChecker is used to assert exported metrics from a prometheus handler. type prometheusChecker struct { - promHandler http.Handler + otelHandler http.Handler } func (pc *prometheusChecker) checkScraperMetrics(receiver component.ID, scraper component.ID, scrapedMetricPoints, erroredMetricPoints int64) error { @@ -30,87 +29,92 @@ func (pc *prometheusChecker) checkScraperMetrics(receiver component.ID, scraper pc.checkCounter("scraper_errored_metric_points", erroredMetricPoints, scraperAttrs)) } -func (pc *prometheusChecker) checkReceiverTraces(receiver component.ID, protocol string, acceptedSpans, droppedSpans int64) error { - receiverAttrs := attributesForReceiverMetrics(receiver, protocol) - return multierr.Combine( - pc.checkCounter("receiver_accepted_spans", acceptedSpans, receiverAttrs), - pc.checkCounter("receiver_refused_spans", droppedSpans, receiverAttrs)) +func (pc *prometheusChecker) checkReceiverTraces(receiver component.ID, protocol string, accepted, dropped int64) error { + return pc.checkReceiver(receiver, "spans", protocol, accepted, dropped) } -func (pc *prometheusChecker) checkReceiverLogs(receiver component.ID, protocol string, acceptedLogRecords, droppedLogRecords int64) error { - receiverAttrs := attributesForReceiverMetrics(receiver, protocol) - return multierr.Combine( - pc.checkCounter("receiver_accepted_log_records", acceptedLogRecords, receiverAttrs), - pc.checkCounter("receiver_refused_log_records", droppedLogRecords, receiverAttrs)) +func (pc *prometheusChecker) checkReceiverLogs(receiver component.ID, protocol string, accepted, dropped int64) error { + return pc.checkReceiver(receiver, "log_records", protocol, accepted, dropped) } -func (pc *prometheusChecker) checkReceiverMetrics(receiver component.ID, protocol string, acceptedMetricPoints, droppedMetricPoints int64) error { +func (pc *prometheusChecker) checkReceiverMetrics(receiver component.ID, protocol string, accepted, dropped int64) error { + return pc.checkReceiver(receiver, "metric_points", protocol, accepted, dropped) +} + +func (pc *prometheusChecker) checkReceiver(receiver component.ID, datatype, protocol string, acceptedMetricPoints, droppedMetricPoints int64) error { receiverAttrs := attributesForReceiverMetrics(receiver, protocol) return multierr.Combine( - pc.checkCounter("receiver_accepted_metric_points", acceptedMetricPoints, receiverAttrs), - pc.checkCounter("receiver_refused_metric_points", droppedMetricPoints, receiverAttrs)) + pc.checkCounter(fmt.Sprintf("receiver_accepted_%s", datatype), acceptedMetricPoints, receiverAttrs), + pc.checkCounter(fmt.Sprintf("receiver_refused_%s", datatype), droppedMetricPoints, receiverAttrs)) } -func (pc *prometheusChecker) checkProcessorTraces(processor component.ID, acceptedSpans, refusedSpans, droppedSpans int64) error { - processorAttrs := attributesForProcessorMetrics(processor) - return multierr.Combine( - pc.checkCounter("processor_accepted_spans", acceptedSpans, processorAttrs), - pc.checkCounter("processor_refused_spans", refusedSpans, processorAttrs), - pc.checkCounter("processor_dropped_spans", droppedSpans, processorAttrs)) +func (pc *prometheusChecker) checkProcessorTraces(processor component.ID, accepted, refused, dropped int64) error { + return pc.checkProcessor(processor, "spans", accepted, refused, dropped) } -func (pc *prometheusChecker) checkProcessorMetrics(processor component.ID, acceptedMetricPoints, refusedMetricPoints, droppedMetricPoints int64) error { - processorAttrs := attributesForProcessorMetrics(processor) - return multierr.Combine( - pc.checkCounter("processor_accepted_metric_points", acceptedMetricPoints, processorAttrs), - pc.checkCounter("processor_refused_metric_points", refusedMetricPoints, processorAttrs), - pc.checkCounter("processor_dropped_metric_points", droppedMetricPoints, processorAttrs)) +func (pc *prometheusChecker) checkProcessorMetrics(processor component.ID, accepted, refused, dropped int64) error { + return pc.checkProcessor(processor, "metric_points", accepted, refused, dropped) +} + +func (pc *prometheusChecker) checkProcessorLogs(processor component.ID, accepted, refused, dropped int64) error { + return pc.checkProcessor(processor, "log_records", accepted, refused, dropped) } -func (pc *prometheusChecker) checkProcessorLogs(processor component.ID, acceptedLogRecords, refusedLogRecords, droppedLogRecords int64) error { +func (pc *prometheusChecker) checkProcessor(processor component.ID, datatype string, accepted, refused, dropped int64) error { processorAttrs := attributesForProcessorMetrics(processor) return multierr.Combine( - pc.checkCounter("processor_accepted_log_records", acceptedLogRecords, processorAttrs), - pc.checkCounter("processor_refused_log_records", refusedLogRecords, processorAttrs), - pc.checkCounter("processor_dropped_log_records", droppedLogRecords, processorAttrs)) + pc.checkCounter(fmt.Sprintf("processor_accepted_%s", datatype), accepted, processorAttrs), + pc.checkCounter(fmt.Sprintf("processor_refused_%s", datatype), refused, processorAttrs), + pc.checkCounter(fmt.Sprintf("processor_dropped_%s", datatype), dropped, processorAttrs)) +} + +func (pc *prometheusChecker) checkExporterTraces(exporter component.ID, sent, sendFailed int64) error { + return pc.checkExporter(exporter, "spans", sent, sendFailed) +} + +func (pc *prometheusChecker) checkExporterLogs(exporter component.ID, sent, sendFailed int64) error { + return pc.checkExporter(exporter, "log_records", sent, sendFailed) } -func (pc *prometheusChecker) checkExporterTraces(exporter component.ID, sentSpans, sendFailedSpans int64) error { +func (pc *prometheusChecker) checkExporterMetrics(exporter component.ID, sent, sendFailed int64) error { + return pc.checkExporter(exporter, "metric_points", sent, sendFailed) +} + +func (pc *prometheusChecker) checkExporter(exporter component.ID, datatype string, sent, sendFailed int64) error { exporterAttrs := attributesForExporterMetrics(exporter) - if sendFailedSpans > 0 { - return multierr.Combine( - pc.checkCounter("exporter_sent_spans", sentSpans, exporterAttrs), - pc.checkCounter("exporter_send_failed_spans", sendFailedSpans, exporterAttrs)) + errs := pc.checkCounter(fmt.Sprintf("exporter_sent_%s", datatype), sent, exporterAttrs) + if sendFailed > 0 { + errs = multierr.Append(errs, + pc.checkCounter(fmt.Sprintf("exporter_send_failed_%s", datatype), sendFailed, exporterAttrs)) } - return multierr.Combine( - pc.checkCounter("exporter_sent_spans", sentSpans, exporterAttrs)) + return errs } -func (pc *prometheusChecker) checkExporterLogs(exporter component.ID, sentLogRecords, sendFailedLogRecords int64) error { - exporterAttrs := attributesForExporterMetrics(exporter) - if sendFailedLogRecords > 0 { - return multierr.Combine( - pc.checkCounter("exporter_sent_log_records", sentLogRecords, exporterAttrs), - pc.checkCounter("exporter_send_failed_log_records", sendFailedLogRecords, exporterAttrs)) +func (pc *prometheusChecker) checkExporterEnqueueFailed(exporter component.ID, datatype string, enqueueFailed int64) error { + if enqueueFailed == 0 { + return nil } - return multierr.Combine( - pc.checkCounter("exporter_sent_log_records", sentLogRecords, exporterAttrs)) + exporterAttrs := attributesForExporterMetrics(exporter) + return pc.checkCounter(fmt.Sprintf("exporter_enqueue_failed_%s", datatype), enqueueFailed, exporterAttrs) } -func (pc *prometheusChecker) checkExporterMetrics(exporter component.ID, sentMetricPoints, sendFailedMetricPoints int64) error { +func (pc *prometheusChecker) checkExporterMetricGauge(exporter component.ID, metric string, val int64) error { exporterAttrs := attributesForExporterMetrics(exporter) - if sendFailedMetricPoints > 0 { - return multierr.Combine( - pc.checkCounter("exporter_sent_metric_points", sentMetricPoints, exporterAttrs), - pc.checkCounter("exporter_send_failed_metric_points", sendFailedMetricPoints, exporterAttrs)) + + ts, err := pc.getMetric(metric, io_prometheus_client.MetricType_GAUGE, exporterAttrs) + if err != nil { + return err } - return multierr.Combine( - pc.checkCounter("exporter_sent_metric_points", sentMetricPoints, exporterAttrs)) + + expected := float64(val) + if math.Abs(ts.GetGauge().GetValue()-expected) > 0.0001 { + return fmt.Errorf("values for metric '%s' did not match, expected '%f' got '%f'", metric, expected, ts.GetGauge().GetValue()) + } + + return nil } func (pc *prometheusChecker) checkCounter(expectedMetric string, value int64, attrs []attribute.KeyValue) error { - // Forces a flush for the opencensus view data. - _, _ = view.RetrieveData(expectedMetric) ts, err := pc.getMetric(expectedMetric, io_prometheus_client.MetricType_COUNTER, attrs) if err != nil { @@ -119,7 +123,7 @@ func (pc *prometheusChecker) checkCounter(expectedMetric string, value int64, at expected := float64(value) if math.Abs(expected-ts.GetCounter().GetValue()) > 0.0001 { - return fmt.Errorf("values for metric '%s' did no match, expected '%f' got '%f'", expectedMetric, expected, ts.GetCounter().GetValue()) + return fmt.Errorf("values for metric '%s' did not match, expected '%f' got '%f'", expectedMetric, expected, ts.GetCounter().GetValue()) } return nil @@ -128,18 +132,14 @@ func (pc *prometheusChecker) checkCounter(expectedMetric string, value int64, at // getMetric returns the metric time series that matches the given name, type and set of attributes // it fetches data from the prometheus endpoint and parse them, ideally OTel Go should provide a MeterRecorder of some kind. func (pc *prometheusChecker) getMetric(expectedName string, expectedType io_prometheus_client.MetricType, expectedAttrs []attribute.KeyValue) (*io_prometheus_client.Metric, error) { - parsed, err := fetchPrometheusMetrics(pc.promHandler) + parsed, err := fetchPrometheusMetrics(pc.otelHandler) if err != nil { return nil, err } metricFamily, ok := parsed[expectedName] if !ok { - // OTel Go adds `_total` suffix for all monotonic sum. - metricFamily, ok = parsed[expectedName+"_total"] - if !ok { - return nil, fmt.Errorf("metric '%s' not found", expectedName) - } + return nil, fmt.Errorf("metric '%s' not found", expectedName) } if metricFamily.Type.String() != expectedType.String() { diff --git a/obsreport/obsreporttest/otelprometheuschecker_test.go b/component/componenttest/otelprometheuschecker_test.go similarity index 89% rename from obsreport/obsreporttest/otelprometheuschecker_test.go rename to component/componenttest/otelprometheuschecker_test.go index d059e4848d9..d7176134f54 100644 --- a/obsreport/obsreporttest/otelprometheuschecker_test.go +++ b/component/componenttest/otelprometheuschecker_test.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package obsreporttest // import "go.opentelemetry.io/collector/obsreport/obsreporttest" +package componenttest // import "go.opentelemetry.io/collector/component/componenttest" import ( "net/http" @@ -26,7 +26,7 @@ func newStubPromChecker() (prometheusChecker, error) { promResponse := strings.ReplaceAll(string(promBytes), "\r\n", "\n") return prometheusChecker{ - promHandler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + otelHandler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { _, _ = w.Write([]byte(promResponse)) }), }, nil @@ -36,10 +36,10 @@ func TestPromChecker(t *testing.T) { pc, err := newStubPromChecker() require.NoError(t, err) - scraper := component.NewID("fakeScraper") - receiver := component.NewID("fakeReceiver") - processor := component.NewID("fakeProcessor") - exporter := component.NewID("fakeExporter") + scraper := component.MustNewID("fakeScraper") + receiver := component.MustNewID("fakeReceiver") + processor := component.MustNewID("fakeProcessor") + exporter := component.MustNewID("fakeExporter") transport := "fakeTransport" assert.NoError(t, diff --git a/component/componenttest/package_test.go b/component/componenttest/package_test.go new file mode 100644 index 00000000000..13cb89ad444 --- /dev/null +++ b/component/componenttest/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package componenttest + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/obsreport/obsreporttest/testdata/prometheus_response b/component/componenttest/testdata/prometheus_response similarity index 100% rename from obsreport/obsreporttest/testdata/prometheus_response rename to component/componenttest/testdata/prometheus_response diff --git a/component/config.go b/component/config.go index e46ead72f06..f54b3a176c2 100644 --- a/component/config.go +++ b/component/config.go @@ -4,7 +4,9 @@ package component // import "go.opentelemetry.io/collector/component" import ( + "fmt" "reflect" + "regexp" "go.uber.org/multierr" @@ -32,7 +34,7 @@ func UnmarshalConfig(conf *confmap.Conf, intoCfg Config) error { return cu.Unmarshal(conf) } - return conf.Unmarshal(intoCfg, confmap.WithErrorUnused()) + return conf.Unmarshal(intoCfg) } // ConfigValidator defines an optional interface for configurations to implement to do validation. @@ -110,6 +112,45 @@ func callValidateIfPossible(v reflect.Value) error { // Type is the component type as it is used in the config. type Type string +// String returns the string representation of the type. +func (t Type) String() string { + return string(t) +} + +// typeRegexp is used to validate the type of a component. +// A type must start with an ASCII alphabetic character and +// can only contain ASCII alphanumeric characters and '_'. +// This must be kept in sync with the regex in cmd/mdatagen/validate.go. +var typeRegexp = regexp.MustCompile(`^[a-zA-Z][0-9a-zA-Z_]*$`) + +// NewType creates a type. It returns an error if the type is invalid. +// A type must +// - have at least one character, +// - start with an ASCII alphabetic character and +// - can only contain ASCII alphanumeric characters and '_'. +func NewType(ty string) (Type, error) { + if len(ty) == 0 { + return Type(""), fmt.Errorf("id must not be empty") + } + if !typeRegexp.MatchString(ty) { + return Type(""), fmt.Errorf("invalid character(s) in type %q", ty) + } + return Type(ty), nil +} + +// MustNewType creates a type. It panics if the type is invalid. +// A type must +// - have at least one character, +// - start with an ASCII alphabetic character and +// - can only contain ASCII alphanumeric characters and '_'. +func MustNewType(strType string) Type { + ty, err := NewType(strType) + if err != nil { + panic(err) + } + return ty +} + // DataType is a special Type that represents the data types supported by the collector. We currently support // collecting metrics, traces and logs, this can expand in the future. type DataType = Type diff --git a/component/config_test.go b/component/config_test.go index b42328678ea..fcddc343d20 100644 --- a/component/config_test.go +++ b/component/config_test.go @@ -5,12 +5,16 @@ package component import ( "errors" + "fmt" "reflect" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) +var _ fmt.Stringer = (Type)("") + type configChildStruct struct { Child errConfig ChildPtr *errConfig @@ -194,3 +198,222 @@ func TestValidateConfig(t *testing.T) { }) } } + +func TestNewType(t *testing.T) { + tests := []struct { + name string + shouldErr bool + }{ + {name: "active_directory_ds"}, + {name: "aerospike"}, + {name: "alertmanager"}, + {name: "alibabacloud_logservice"}, + {name: "apache"}, + {name: "apachespark"}, + {name: "asapclient"}, + {name: "attributes"}, + {name: "awscloudwatch"}, + {name: "awscloudwatchlogs"}, + {name: "awscloudwatchmetrics"}, + {name: "awscontainerinsightreceiver"}, + {name: "awsecscontainermetrics"}, + {name: "awsemf"}, + {name: "awsfirehose"}, + {name: "awskinesis"}, + {name: "awsproxy"}, + {name: "awss3"}, + {name: "awsxray"}, + {name: "azureblob"}, + {name: "azuredataexplorer"}, + {name: "azureeventhub"}, + {name: "azuremonitor"}, + {name: "basicauth"}, + {name: "batch"}, + {name: "bearertokenauth"}, + {name: "bigip"}, + {name: "carbon"}, + {name: "cassandra"}, + {name: "chrony"}, + {name: "clickhouse"}, + {name: "cloudflare"}, + {name: "cloudfoundry"}, + {name: "collectd"}, + {name: "configschema"}, + {name: "coralogix"}, + {name: "couchdb"}, + {name: "count"}, + {name: "cumulativetodelta"}, + {name: "datadog"}, + {name: "dataset"}, + {name: "db_storage"}, + {name: "debug"}, + {name: "deltatorate"}, + {name: "demo"}, + {name: "docker_observer"}, + {name: "docker_stats"}, + {name: "dynatrace"}, + {name: "ecs_observer"}, + {name: "ecs_task_observer"}, + {name: "elasticsearch"}, + {name: "exceptions"}, + {name: "experimental_metricsgeneration"}, + {name: "expvar"}, + {name: "f5cloud"}, + {name: "failover"}, + {name: "file"}, + {name: "filelog"}, + {name: "filestats"}, + {name: "file_storage"}, + {name: "filter"}, + {name: "flinkmetrics"}, + {name: "fluentforward"}, + {name: "forward"}, + {name: "githubgen"}, + {name: "gitprovider"}, + {name: "golden"}, + {name: "googlecloud"}, + {name: "googlecloudpubsub"}, + {name: "googlecloudspanner"}, + {name: "googlemanagedprometheus"}, + {name: "groupbyattrs"}, + {name: "groupbytrace"}, + {name: "haproxy"}, + {name: "headers_setter"}, + {name: "health_check"}, + {name: "honeycombmarker"}, + {name: "hostmetrics"}, + {name: "host_observer"}, + {name: "httpcheck"}, + {name: "http_forwarder"}, + {name: "iis"}, + {name: "influxdb"}, + {name: "instana"}, + {name: "interval"}, + {name: "jaeger"}, + {name: "jaeger_encoding"}, + {name: "jaegerremotesampling"}, + {name: "jmx"}, + {name: "journald"}, + {name: "json_log_encoding"}, + {name: "k8sattributes"}, + {name: "k8s_cluster"}, + {name: "k8s_events"}, + {name: "k8sobjects"}, + {name: "k8s_observer"}, + {name: "kafka"}, + {name: "kafkametrics"}, + {name: "kinetica"}, + {name: "kubeletstats"}, + {name: "loadbalancing"}, + {name: "logging"}, + {name: "logicmonitor"}, + {name: "logstransform"}, + {name: "logzio"}, + {name: "loki"}, + {name: "mdatagen"}, + {name: "memcached"}, + {name: "memory_ballast"}, + {name: "memory_limiter"}, + {name: "metricstransform"}, + {name: "mezmo"}, + {name: "mongodb"}, + {name: "mongodbatlas"}, + {name: "mysql"}, + {name: "namedpipe"}, + {name: "nginx"}, + {name: "nsxt"}, + {name: "oauth2client"}, + {name: "oidc"}, + {name: "opamp"}, + {name: "opampsupervisor"}, + {name: "opencensus"}, + {name: "opensearch"}, + {name: "oracledb"}, + {name: "osquery"}, + {name: "otelarrow"}, + {name: "otelcontribcol"}, + {name: "oteltestbedcol"}, + {name: "otlp"}, + {name: "otlp_encoding"}, + {name: "otlphttp"}, + {name: "otlpjsonfile"}, + {name: "ottl"}, + {name: "podman_stats"}, + {name: "postgresql"}, + {name: "pprof"}, + {name: "probabilistic_sampler"}, + {name: "prometheus"}, + {name: "prometheusremotewrite"}, + {name: "prometheus_simple"}, + {name: "pulsar"}, + {name: "purefa"}, + {name: "purefb"}, + {name: "rabbitmq"}, + {name: "receiver_creator"}, + {name: "redaction"}, + {name: "redis"}, + {name: "remotetap"}, + {name: "resource"}, + {name: "resourcedetection"}, + {name: "riak"}, + {name: "routing"}, + {name: "saphana"}, + {name: "sapm"}, + {name: "schema"}, + {name: "sentry"}, + {name: "servicegraph"}, + {name: "signalfx"}, + {name: "sigv4auth"}, + {name: "skywalking"}, + {name: "snmp"}, + {name: "snowflake"}, + {name: "solace"}, + {name: "solarwindsapmsettings"}, + {name: "span"}, + {name: "spanmetrics"}, + {name: "splunkenterprise"}, + {name: "splunk_hec"}, + {name: "sqlquery"}, + {name: "sqlserver"}, + {name: "sshcheck"}, + {name: "statsd"}, + {name: "sumologic"}, + {name: "syslog"}, + {name: "tail_sampling"}, + {name: "tcplog"}, + {name: "telemetrygen"}, + {name: "tencentcloud_logservice"}, + {name: "text_encoding"}, + {name: "transform"}, + {name: "udplog"}, + {name: "vcenter"}, + {name: "wavefront"}, + {name: "webhookevent"}, + {name: "windowseventlog"}, + {name: "windowsperfcounters"}, + {name: "zipkin"}, + {name: "zipkin_encoding"}, + {name: "zookeeper"}, + {name: "zpages"}, + + {name: "", shouldErr: true}, + {name: "contains spaces", shouldErr: true}, + {name: "contains-dashes", shouldErr: true}, + {name: "0startswithnumber", shouldErr: true}, + {name: "contains/slash", shouldErr: true}, + {name: "contains:colon", shouldErr: true}, + {name: "contains#hash", shouldErr: true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ty, err := NewType(tt.name) + if tt.shouldErr { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, tt.name, ty.String()) + } + }) + } +} diff --git a/component/go.mod b/component/go.mod index 4276411cde8..05298e470ba 100644 --- a/component/go.mod +++ b/component/go.mod @@ -1,37 +1,48 @@ module go.opentelemetry.io/collector/component -go 1.20 +go 1.21 require ( + github.com/prometheus/client_golang v1.19.0 + github.com/prometheus/client_model v0.6.0 + github.com/prometheus/common v0.48.0 github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 - go.opentelemetry.io/collector/confmap v0.85.0 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/otel/metric v1.18.0 - go.opentelemetry.io/otel/trace v1.18.0 + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 + go.opentelemetry.io/collector/confmap v0.96.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 + go.opentelemetry.io/otel/sdk/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 - go.uber.org/zap v1.26.0 + go.uber.org/zap v1.27.0 ) require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -39,8 +50,6 @@ replace go.opentelemetry.io/collector/config/configtelemetry => ../config/config replace go.opentelemetry.io/collector/confmap => ../confmap -replace go.opentelemetry.io/collector/featuregate => ../featuregate - replace go.opentelemetry.io/collector/pdata => ../pdata retract ( diff --git a/component/go.sum b/component/go.sum index e5817058840..2f664245ecd 100644 --- a/component/go.sum +++ b/component/go.sum @@ -1,48 +1,74 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -52,20 +78,20 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -74,15 +100,16 @@ 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-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= 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/component/host.go b/component/host.go index ea3825d743f..4b6933baaef 100644 --- a/component/host.go +++ b/component/host.go @@ -6,14 +6,6 @@ package component // import "go.opentelemetry.io/collector/component" // Host represents the entity that is hosting a Component. It is used to allow communication // between the Component and its host (normally the service.Collector is the host). type Host interface { - // ReportFatalError is used to report to the host that the component - // encountered a fatal error (i.e.: an error that the instance can't recover - // from) after its start function had already returned. - // - // ReportFatalError should be called by the component anytime after Component.Start() ends and - // before Component.Shutdown() begins. - ReportFatalError(err error) - // GetFactory of the specified kind. Returns the factory for a component type. // This allows components to create other components. For example: // func (r MyReceiver) Start(host component.Host) error { diff --git a/component/identifiable.go b/component/identifiable.go index 331c348fe59..d2d65a5e24f 100644 --- a/component/identifiable.go +++ b/component/identifiable.go @@ -26,11 +26,23 @@ func NewID(typeVal Type) ID { return ID{typeVal: typeVal} } +// MustNewID builds a Type and returns a new ID with the given Type and empty name. +// See MustNewType to check the valid values of typeVal. +func MustNewID(typeVal string) ID { + return ID{typeVal: MustNewType(typeVal)} +} + // NewIDWithName returns a new ID with the given Type and name. func NewIDWithName(typeVal Type, nameVal string) ID { return ID{typeVal: typeVal, nameVal: nameVal} } +// MustNewIDWithName builds a Type and returns a new ID with the given Type and name. +// See MustNewType to check the valid values of typeVal. +func MustNewIDWithName(typeVal string, nameVal string) ID { + return ID{typeVal: MustNewType(typeVal), nameVal: nameVal} +} + // Type returns the type of the component. func (id ID) Type() Type { return id.typeVal @@ -51,34 +63,41 @@ func (id ID) MarshalText() (text []byte, err error) { func (id *ID) UnmarshalText(text []byte) error { idStr := string(text) items := strings.SplitN(idStr, typeAndNameSeparator, 2) + var typeStr, nameStr string if len(items) >= 1 { - id.typeVal = Type(strings.TrimSpace(items[0])) + typeStr = strings.TrimSpace(items[0]) } - if len(items) == 1 && id.typeVal == "" { + if len(items) == 1 && typeStr == "" { return errors.New("id must not be empty") } - if id.typeVal == "" { + if typeStr == "" { return fmt.Errorf("in %q id: the part before %s should not be empty", idStr, typeAndNameSeparator) } if len(items) > 1 { // "name" part is present. - id.nameVal = strings.TrimSpace(items[1]) - if id.nameVal == "" { + nameStr = strings.TrimSpace(items[1]) + if nameStr == "" { return fmt.Errorf("in %q id: the part after %s should not be empty", idStr, typeAndNameSeparator) } } + var err error + if id.typeVal, err = NewType(typeStr); err != nil { + return fmt.Errorf("in %q id: %w", idStr, err) + } + id.nameVal = nameStr + return nil } // String returns the ID string representation as "type[/name]" format. func (id ID) String() string { if id.nameVal == "" { - return string(id.typeVal) + return id.typeVal.String() } - return string(id.typeVal) + typeAndNameSeparator + id.nameVal + return id.typeVal.String() + typeAndNameSeparator + id.nameVal } diff --git a/component/identifiable_test.go b/component/identifiable_test.go index 6b55375adc3..25c449ef11c 100644 --- a/component/identifiable_test.go +++ b/component/identifiable_test.go @@ -10,13 +10,14 @@ import ( ) func TestMarshalText(t *testing.T) { - id := NewIDWithName("test", "name") + id := NewIDWithName(MustNewType("test"), "name") got, err := id.MarshalText() assert.NoError(t, err) assert.Equal(t, id.String(), string(got)) } func TestUnmarshalText(t *testing.T) { + validType := MustNewType("valid_type") var testCases = []struct { idStr string expectedErr bool @@ -24,15 +25,15 @@ func TestUnmarshalText(t *testing.T) { }{ { idStr: "valid_type", - expectedID: ID{typeVal: "valid_type", nameVal: ""}, + expectedID: ID{typeVal: validType, nameVal: ""}, }, { idStr: "valid_type/valid_name", - expectedID: ID{typeVal: "valid_type", nameVal: "valid_name"}, + expectedID: ID{typeVal: validType, nameVal: "valid_name"}, }, { idStr: " valid_type / valid_name ", - expectedID: ID{typeVal: "valid_type", nameVal: "valid_name"}, + expectedID: ID{typeVal: validType, nameVal: "valid_name"}, }, { idStr: "/valid_name", diff --git a/component/package_test.go b/component/package_test.go new file mode 100644 index 00000000000..8bf70a2eb7b --- /dev/null +++ b/component/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package component + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/component/status.go b/component/status.go new file mode 100644 index 00000000000..8cd4d802644 --- /dev/null +++ b/component/status.go @@ -0,0 +1,190 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package component // import "go.opentelemetry.io/collector/component" + +import ( + "time" +) + +type Status int32 + +// Enumeration of possible component statuses +const ( + StatusNone Status = iota + StatusStarting + StatusOK + StatusRecoverableError + StatusPermanentError + StatusFatalError + StatusStopping + StatusStopped +) + +// String returns a string representation of a Status +func (s Status) String() string { + switch s { + case StatusStarting: + return "StatusStarting" + case StatusOK: + return "StatusOK" + case StatusRecoverableError: + return "StatusRecoverableError" + case StatusPermanentError: + return "StatusPermanentError" + case StatusFatalError: + return "StatusFatalError" + case StatusStopping: + return "StatusStopping" + case StatusStopped: + return "StatusStopped" + } + return "StatusNone" +} + +// StatusEvent contains a status and timestamp, and can contain an error +type StatusEvent struct { + status Status + err error + timestamp time.Time +} + +// Status returns the Status (enum) associated with the StatusEvent +func (ev *StatusEvent) Status() Status { + return ev.status +} + +// Err returns the error associated with the StatusEvent. +func (ev *StatusEvent) Err() error { + return ev.err +} + +// Timestamp returns the timestamp associated with the StatusEvent +func (ev *StatusEvent) Timestamp() time.Time { + return ev.timestamp +} + +// NewStatusEvent creates and returns a StatusEvent with the specified status and sets the timestamp +// time.Now(). To set an error on the event for an error status use one of the dedicated +// constructors (e.g. NewRecoverableErrorEvent, NewPermanentErrorEvent, NewFatalErrorEvent) +func NewStatusEvent(status Status) *StatusEvent { + return &StatusEvent{ + status: status, + timestamp: time.Now(), + } +} + +// NewRecoverableErrorEvent creates and returns a StatusEvent with StatusRecoverableError, the +// specified error, and a timestamp set to time.Now(). +func NewRecoverableErrorEvent(err error) *StatusEvent { + ev := NewStatusEvent(StatusRecoverableError) + ev.err = err + return ev +} + +// NewPermanentErrorEvent creates and returns a StatusEvent with StatusPermanentError, the +// specified error, and a timestamp set to time.Now(). +func NewPermanentErrorEvent(err error) *StatusEvent { + ev := NewStatusEvent(StatusPermanentError) + ev.err = err + return ev +} + +// NewFatalErrorEvent creates and returns a StatusEvent with StatusFatalError, the +// specified error, and a timestamp set to time.Now(). +func NewFatalErrorEvent(err error) *StatusEvent { + ev := NewStatusEvent(StatusFatalError) + ev.err = err + return ev +} + +// AggregateStatus will derive a status for the given input using the following rules in order: +// 1. If all instances have the same status, there is nothing to aggregate, return it. +// 2. If any instance encounters a fatal error, the component is in a Fatal Error state. +// 3. If any instance is in a Permanent Error state, the component status is Permanent Error. +// 4. If any instance is Stopping, the component is in a Stopping state. +// 5. An instance is Stopped, but not all instances are Stopped, we must be in the process of Stopping the component. +// 6. If any instance is in a Recoverable Error state, the component status is Recoverable Error. +// 7. By process of elimination, the only remaining state is starting. +func AggregateStatus[K comparable](eventMap map[K]*StatusEvent) Status { + seen := make(map[Status]struct{}) + for _, ev := range eventMap { + seen[ev.Status()] = struct{}{} + } + + // All statuses are the same. Note, this will handle StatusOK and StatusStopped as these two + // cases require all components be in the same state. + if len(seen) == 1 { + for st := range seen { + return st + } + } + + // Handle mixed status cases + if _, isFatal := seen[StatusFatalError]; isFatal { + return StatusFatalError + } + + if _, isPermanent := seen[StatusPermanentError]; isPermanent { + return StatusPermanentError + } + + if _, isStopping := seen[StatusStopping]; isStopping { + return StatusStopping + } + + if _, isStopped := seen[StatusStopped]; isStopped { + return StatusStopping + } + + if _, isRecoverable := seen[StatusRecoverableError]; isRecoverable { + return StatusRecoverableError + } + + // By process of elimination, this is the last possible status; no check necessary. + return StatusStarting +} + +// StatusIsError returns true for error statuses (e.g. StatusRecoverableError, +// StatusPermanentError, or StatusFatalError) +func StatusIsError(status Status) bool { + return status == StatusRecoverableError || + status == StatusPermanentError || + status == StatusFatalError +} + +// AggregateStatusEvent returns a status event where: +// - The status is set to the aggregate status of the events in the eventMap +// - The timestamp is set to the latest timestamp of the events in the eventMap +// - For an error status, the event will have same error as the most current event of the same +// error type from the eventMap +func AggregateStatusEvent[K comparable](eventMap map[K]*StatusEvent) *StatusEvent { + var lastEvent, lastMatchingEvent *StatusEvent + aggregateStatus := AggregateStatus[K](eventMap) + + for _, ev := range eventMap { + if lastEvent == nil || lastEvent.timestamp.Before(ev.timestamp) { + lastEvent = ev + } + if aggregateStatus == ev.Status() && + (lastMatchingEvent == nil || lastMatchingEvent.timestamp.Before(ev.timestamp)) { + lastMatchingEvent = ev + } + } + + // the effective status matches an existing event + if lastEvent.Status() == aggregateStatus { + return lastEvent + } + + // the effective status requires a synthetic event + aggregateEvent := &StatusEvent{ + status: aggregateStatus, + timestamp: lastEvent.timestamp, + } + if StatusIsError(aggregateStatus) { + aggregateEvent.err = lastMatchingEvent.err + } + + return aggregateEvent +} diff --git a/component/status_test.go b/component/status_test.go new file mode 100644 index 00000000000..13755d078a5 --- /dev/null +++ b/component/status_test.go @@ -0,0 +1,330 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 +package component + +import ( + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewStatusEvent(t *testing.T) { + statuses := []Status{ + StatusStarting, + StatusOK, + StatusRecoverableError, + StatusPermanentError, + StatusFatalError, + StatusStopping, + StatusStopped, + } + + for _, status := range statuses { + t.Run(fmt.Sprintf("%s without error", status), func(t *testing.T) { + ev := NewStatusEvent(status) + require.Equal(t, status, ev.Status()) + require.Nil(t, ev.Err()) + require.False(t, ev.Timestamp().IsZero()) + }) + } +} + +func TestStatusEventsWithError(t *testing.T) { + statusConstructorMap := map[Status]func(error) *StatusEvent{ + StatusRecoverableError: NewRecoverableErrorEvent, + StatusPermanentError: NewPermanentErrorEvent, + StatusFatalError: NewFatalErrorEvent, + } + + for status, newEvent := range statusConstructorMap { + t.Run(fmt.Sprintf("error status constructor for: %s", status), func(t *testing.T) { + ev := newEvent(assert.AnError) + require.Equal(t, status, ev.Status()) + require.Equal(t, assert.AnError, ev.Err()) + require.False(t, ev.Timestamp().IsZero()) + }) + } +} + +func TestAggregateStatus(t *testing.T) { + for _, tc := range []struct { + name string + statusMap map[*InstanceID]*StatusEvent + expectedStatus Status + }{ + { + name: "aggregate status with fatal is FatalError", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStarting), + {}: NewStatusEvent(StatusOK), + {}: NewStatusEvent(StatusFatalError), + {}: NewStatusEvent(StatusRecoverableError), + }, + expectedStatus: StatusFatalError, + }, + { + name: "aggregate status with permanent is PermanentError", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStarting), + {}: NewStatusEvent(StatusOK), + {}: NewStatusEvent(StatusPermanentError), + {}: NewStatusEvent(StatusRecoverableError), + }, + expectedStatus: StatusPermanentError, + }, + { + name: "aggregate status with stopping is Stopping", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStarting), + {}: NewStatusEvent(StatusOK), + {}: NewStatusEvent(StatusRecoverableError), + {}: NewStatusEvent(StatusStopping), + }, + expectedStatus: StatusStopping, + }, + { + name: "aggregate status with stopped and non-stopped is Stopping", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStarting), + {}: NewStatusEvent(StatusOK), + {}: NewStatusEvent(StatusRecoverableError), + {}: NewStatusEvent(StatusStopped), + }, + expectedStatus: StatusStopping, + }, + { + name: "aggregate status with all stopped is Stopped", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStopped), + {}: NewStatusEvent(StatusStopped), + {}: NewStatusEvent(StatusStopped), + }, + expectedStatus: StatusStopped, + }, + { + name: "aggregate status with recoverable is RecoverableError", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStarting), + {}: NewStatusEvent(StatusOK), + {}: NewStatusEvent(StatusRecoverableError), + }, + expectedStatus: StatusRecoverableError, + }, + { + name: "aggregate status with starting is Starting", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStarting), + {}: NewStatusEvent(StatusOK), + }, + expectedStatus: StatusStarting, + }, + { + name: "aggregate status with all ok is OK", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusOK), + {}: NewStatusEvent(StatusOK), + {}: NewStatusEvent(StatusOK), + }, + expectedStatus: StatusOK, + }, + } { + t.Run(tc.name, func(t *testing.T) { + assert.Equal(t, tc.expectedStatus, AggregateStatus(tc.statusMap)) + }) + } +} + +func TestStatusIsError(t *testing.T) { + for _, tc := range []struct { + status Status + isError bool + }{ + { + status: StatusStarting, + isError: false, + }, + { + status: StatusOK, + isError: false, + }, + { + status: StatusRecoverableError, + isError: true, + }, + { + status: StatusPermanentError, + isError: true, + }, + { + status: StatusFatalError, + isError: true, + }, + { + status: StatusStopping, + isError: false, + }, + { + status: StatusStopped, + isError: false, + }, + } { + name := fmt.Sprintf("StatusIsError(%s) is %t", tc.status, tc.isError) + t.Run(name, func(t *testing.T) { + assert.Equal(t, tc.isError, StatusIsError(tc.status)) + }) + } +} + +func TestAggregateStatusEvent(t *testing.T) { + // maxTime is used to make sure we select the event with the latest timestamp + maxTime := time.Unix(1<<63-62135596801, 999999999) + // latest sets the timestamp for an event to maxTime + latest := func(ev *StatusEvent) *StatusEvent { + ev.timestamp = maxTime + return ev + } + + for _, tc := range []struct { + name string + statusMap map[*InstanceID]*StatusEvent + expectedStatus *StatusEvent + }{ + { + name: "FatalError - existing event", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStarting), + {}: NewStatusEvent(StatusOK), + {}: latest(NewFatalErrorEvent(assert.AnError)), + {}: NewStatusEvent(StatusRecoverableError), + }, + expectedStatus: &StatusEvent{ + status: StatusFatalError, + timestamp: maxTime, + err: assert.AnError, + }, + }, + { + name: "FatalError - synthetic event", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStarting), + {}: NewStatusEvent(StatusOK), + {}: NewFatalErrorEvent(assert.AnError), + {}: latest(NewStatusEvent(StatusRecoverableError)), + }, + expectedStatus: &StatusEvent{ + status: StatusFatalError, + timestamp: maxTime, + err: assert.AnError, + }, + }, + { + name: "PermanentError - existing event", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStarting), + {}: NewStatusEvent(StatusOK), + {}: latest(NewPermanentErrorEvent(assert.AnError)), + {}: NewStatusEvent(StatusRecoverableError), + }, + expectedStatus: &StatusEvent{ + status: StatusPermanentError, + timestamp: maxTime, + err: assert.AnError, + }, + }, + { + name: "PermanentError - synthetic event", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStarting), + {}: NewStatusEvent(StatusOK), + {}: NewPermanentErrorEvent(assert.AnError), + {}: latest(NewStatusEvent(StatusRecoverableError)), + }, + expectedStatus: &StatusEvent{ + status: StatusPermanentError, + timestamp: maxTime, + err: assert.AnError, + }, + }, + { + name: "Stopping - existing event", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStarting), + {}: NewStatusEvent(StatusOK), + {}: NewStatusEvent(StatusRecoverableError), + {}: latest(NewStatusEvent(StatusStopping)), + }, + expectedStatus: &StatusEvent{ + status: StatusStopping, + timestamp: maxTime, + }, + }, + { + name: "Stopping - synthetic event", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStarting), + {}: NewStatusEvent(StatusOK), + {}: NewStatusEvent(StatusRecoverableError), + {}: latest(NewStatusEvent(StatusStopped)), + }, + expectedStatus: &StatusEvent{ + status: StatusStopping, + timestamp: maxTime, + }, + }, + { + name: "Stopped - existing event", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStopped), + {}: latest(NewStatusEvent(StatusStopped)), + {}: NewStatusEvent(StatusStopped), + }, + expectedStatus: &StatusEvent{ + status: StatusStopped, + timestamp: maxTime, + }, + }, + { + name: "RecoverableError - existing event", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStarting), + {}: NewStatusEvent(StatusOK), + {}: latest(NewRecoverableErrorEvent(assert.AnError)), + }, + expectedStatus: &StatusEvent{ + status: StatusRecoverableError, + timestamp: maxTime, + err: assert.AnError, + }, + }, + { + name: "Starting - synthetic event", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusStarting), + {}: latest(NewStatusEvent(StatusOK)), + }, + expectedStatus: &StatusEvent{ + status: StatusStarting, + timestamp: maxTime, + }, + }, + { + name: "OK - existing event", + statusMap: map[*InstanceID]*StatusEvent{ + {}: NewStatusEvent(StatusOK), + {}: latest(NewStatusEvent(StatusOK)), + {}: NewStatusEvent(StatusOK), + }, + expectedStatus: &StatusEvent{ + status: StatusOK, + timestamp: maxTime, + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + assert.Equal(t, tc.expectedStatus, AggregateStatusEvent(tc.statusMap)) + }) + } +} diff --git a/component/telemetry.go b/component/telemetry.go index 9617e456319..572b4bdd916 100644 --- a/component/telemetry.go +++ b/component/telemetry.go @@ -12,6 +12,11 @@ import ( "go.opentelemetry.io/collector/pdata/pcommon" ) +// TelemetrySettings provides components with APIs to report telemetry. +// +// Note: there is a service version of this struct, servicetelemetry.TelemetrySettings, that mirrors +// this struct with the exception of ReportComponentStatus. When adding or removing anything from +// this struct consider whether or not the same should be done for the service version. type TelemetrySettings struct { // Logger that the factory can use during creation and can pass to the created // component to be used later as well. @@ -29,4 +34,9 @@ type TelemetrySettings struct { // Resource contains the resource attributes for the collector's telemetry. Resource pcommon.Resource + + // ReportStatus allows a component to report runtime changes in status. The service + // will automatically report status for a component during startup and shutdown. Components can + // use this method to report status after start and before shutdown. + ReportStatus func(*StatusEvent) } diff --git a/config/configauth/configauth_test.go b/config/configauth/configauth_test.go index 19497c2e7c5..43c84ceb497 100644 --- a/config/configauth/configauth_test.go +++ b/config/configauth/configauth_test.go @@ -13,6 +13,8 @@ import ( "go.opentelemetry.io/collector/extension/auth" ) +var mockID = component.MustNewID("mock") + func TestGetServer(t *testing.T) { testCases := []struct { desc string @@ -34,10 +36,10 @@ func TestGetServer(t *testing.T) { t.Run(tC.desc, func(t *testing.T) { // prepare cfg := &Authentication{ - AuthenticatorID: component.NewID("mock"), + AuthenticatorID: mockID, } ext := map[component.ID]component.Component{ - component.NewID("mock"): tC.authenticator, + mockID: tC.authenticator, } authenticator, err := cfg.GetServerAuthenticator(ext) @@ -56,7 +58,7 @@ func TestGetServer(t *testing.T) { func TestGetServerFails(t *testing.T) { cfg := &Authentication{ - AuthenticatorID: component.NewID("does-not-exist"), + AuthenticatorID: component.MustNewID("does_not_exist"), } authenticator, err := cfg.GetServerAuthenticator(map[component.ID]component.Component{}) @@ -85,10 +87,10 @@ func TestGetClient(t *testing.T) { t.Run(tC.desc, func(t *testing.T) { // prepare cfg := &Authentication{ - AuthenticatorID: component.NewID("mock"), + AuthenticatorID: mockID, } ext := map[component.ID]component.Component{ - component.NewID("mock"): tC.authenticator, + mockID: tC.authenticator, } authenticator, err := cfg.GetClientAuthenticator(ext) @@ -107,7 +109,7 @@ func TestGetClient(t *testing.T) { func TestGetClientFails(t *testing.T) { cfg := &Authentication{ - AuthenticatorID: component.NewID("does-not-exist"), + AuthenticatorID: component.MustNewID("does_not_exist"), } authenticator, err := cfg.GetClientAuthenticator(map[component.ID]component.Component{}) assert.ErrorIs(t, err, errAuthenticatorNotFound) diff --git a/config/configauth/go.mod b/config/configauth/go.mod index 196fdca44ea..a58c97c3449 100644 --- a/config/configauth/go.mod +++ b/config/configauth/go.mod @@ -1,47 +1,45 @@ module go.opentelemetry.io/collector/config/configauth -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/extension v0.85.0 - go.opentelemetry.io/collector/extension/auth v0.85.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/extension v0.96.0 + go.opentelemetry.io/collector/extension/auth v0.96.0 + go.uber.org/goleak v1.3.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 // indirect - go.opentelemetry.io/collector/confmap v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/confmap v0.96.0 // indirect + go.opentelemetry.io/collector/pdata v1.3.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) replace go.opentelemetry.io/collector/pdata => ../../pdata -replace go.opentelemetry.io/collector/featuregate => ../../featuregate - replace go.opentelemetry.io/collector/confmap => ../../confmap replace go.opentelemetry.io/collector/component => ../../component diff --git a/config/configauth/go.sum b/config/configauth/go.sum index e5817058840..f0d91ce3b4d 100644 --- a/config/configauth/go.sum +++ b/config/configauth/go.sum @@ -1,48 +1,73 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -52,20 +77,20 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -74,15 +99,16 @@ 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-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= 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/config/configauth/package_test.go b/config/configauth/package_test.go new file mode 100644 index 00000000000..1364f8b58f6 --- /dev/null +++ b/config/configauth/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package configauth + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/config/configcompression/compressionType.go b/config/configcompression/compressionType.go deleted file mode 100644 index ed0a979420a..00000000000 --- a/config/configcompression/compressionType.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package configcompression // import "go.opentelemetry.io/collector/config/configcompression" - -import "fmt" - -type CompressionType string - -const ( - Gzip CompressionType = "gzip" - Zlib CompressionType = "zlib" - Deflate CompressionType = "deflate" - Snappy CompressionType = "snappy" - Zstd CompressionType = "zstd" - none CompressionType = "none" - empty CompressionType = "" -) - -func IsCompressed(compressionType CompressionType) bool { - return compressionType != empty && compressionType != none -} - -func (ct *CompressionType) UnmarshalText(in []byte) error { - switch typ := CompressionType(in); typ { - case Gzip, - Zlib, - Deflate, - Snappy, - Zstd, - none, - empty: - *ct = typ - return nil - default: - return fmt.Errorf("unsupported compression type %q", typ) - } -} diff --git a/config/configcompression/compressiontype.go b/config/configcompression/compressiontype.go new file mode 100644 index 00000000000..f2bf3850964 --- /dev/null +++ b/config/configcompression/compressiontype.go @@ -0,0 +1,41 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package configcompression // import "go.opentelemetry.io/collector/config/configcompression" + +import "fmt" + +// Type represents a compression method +type Type string + +const ( + TypeGzip Type = "gzip" + TypeZlib Type = "zlib" + TypeDeflate Type = "deflate" + TypeSnappy Type = "snappy" + TypeZstd Type = "zstd" + typeNone Type = "none" + typeEmpty Type = "" +) + +// IsCompressed returns false if CompressionType is nil, none, or empty. +// Otherwise, returns true. +func (ct *Type) IsCompressed() bool { + return *ct != typeEmpty && *ct != typeNone +} + +func (ct *Type) UnmarshalText(in []byte) error { + switch typ := Type(in); typ { + case TypeGzip, + TypeZlib, + TypeDeflate, + TypeSnappy, + TypeZstd, + typeNone, + typeEmpty: + *ct = typ + return nil + default: + return fmt.Errorf("unsupported compression type %q", typ) + } +} diff --git a/config/configcompression/compressionType_test.go b/config/configcompression/compressiontype_test.go similarity index 82% rename from config/configcompression/compressionType_test.go rename to config/configcompression/compressiontype_test.go index dcf3350861e..cf8166d5a24 100644 --- a/config/configcompression/compressionType_test.go +++ b/config/configcompression/compressiontype_test.go @@ -15,31 +15,37 @@ func TestUnmarshalText(t *testing.T) { name string compressionName []byte shouldError bool + isCompressed bool }{ { name: "ValidGzip", compressionName: []byte("gzip"), shouldError: false, + isCompressed: true, }, { name: "ValidZlib", compressionName: []byte("zlib"), shouldError: false, + isCompressed: true, }, { name: "ValidDeflate", compressionName: []byte("deflate"), shouldError: false, + isCompressed: true, }, { name: "ValidSnappy", compressionName: []byte("snappy"), shouldError: false, + isCompressed: true, }, { name: "ValidZstd", compressionName: []byte("zstd"), shouldError: false, + isCompressed: true, }, { name: "ValidEmpty", @@ -59,14 +65,16 @@ func TestUnmarshalText(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - temp := none + temp := typeNone err := temp.UnmarshalText(tt.compressionName) if tt.shouldError { assert.Error(t, err) return } require.NoError(t, err) - assert.Equal(t, temp, CompressionType(tt.compressionName)) + ct := Type(tt.compressionName) + assert.Equal(t, temp, ct) + assert.Equal(t, tt.isCompressed, ct.IsCompressed()) }) } } diff --git a/config/configcompression/go.mod b/config/configcompression/go.mod index 176a02b55b3..1ac40196d85 100644 --- a/config/configcompression/go.mod +++ b/config/configcompression/go.mod @@ -1,8 +1,11 @@ module go.opentelemetry.io/collector/config/configcompression -go 1.20 +go 1.21 -require github.com/stretchr/testify v1.8.4 +require ( + github.com/stretchr/testify v1.8.4 + go.uber.org/goleak v1.3.0 +) require ( github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/config/configcompression/go.sum b/config/configcompression/go.sum index 3ee4af40e76..b4eccab6a53 100644 --- a/config/configcompression/go.sum +++ b/config/configcompression/go.sum @@ -16,6 +16,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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/configcompression/package_test.go b/config/configcompression/package_test.go new file mode 100644 index 00000000000..a8be1b407c0 --- /dev/null +++ b/config/configcompression/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package configcompression + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/config/configgrpc/configgrpc.go b/config/configgrpc/configgrpc.go index f6da798f165..18526262317 100644 --- a/config/configgrpc/configgrpc.go +++ b/config/configgrpc/configgrpc.go @@ -8,7 +8,6 @@ import ( "crypto/tls" "errors" "fmt" - "net" "strings" "time" @@ -47,18 +46,18 @@ type KeepaliveClientConfig struct { PermitWithoutStream bool `mapstructure:"permit_without_stream"` } -// GRPCClientSettings defines common settings for a gRPC client configuration. -type GRPCClientSettings struct { +// ClientConfig defines common settings for a gRPC client configuration. +type ClientConfig struct { // The target to which the exporter is going to send traces or metrics, // using the gRPC protocol. The valid syntax is described at // https://github.com/grpc/grpc/blob/master/doc/naming.md. Endpoint string `mapstructure:"endpoint"` // The compression key for supported compression types within collector. - Compression configcompression.CompressionType `mapstructure:"compression"` + Compression configcompression.Type `mapstructure:"compression"` // TLSSetting struct exposes TLS client configuration. - TLSSetting configtls.TLSClientSetting `mapstructure:"tls"` + TLSSetting configtls.ClientConfig `mapstructure:"tls"` // The keepalive parameters for gRPC client. See grpc.WithKeepaliveParams. // (https://godoc.org/google.golang.org/grpc#WithKeepaliveParams). @@ -116,14 +115,14 @@ type KeepaliveEnforcementPolicy struct { PermitWithoutStream bool `mapstructure:"permit_without_stream"` } -// GRPCServerSettings defines common settings for a gRPC server configuration. -type GRPCServerSettings struct { +// ServerConfig defines common settings for a gRPC server configuration. +type ServerConfig struct { // Server net.Addr config. For transport only "tcp" and "unix" are valid options. - NetAddr confignet.NetAddr `mapstructure:",squash"` + NetAddr confignet.AddrConfig `mapstructure:",squash"` // Configures the protocol to use TLS. // The default value is nil, which will cause the protocol to not use TLS. - TLSSetting *configtls.TLSServerSetting `mapstructure:"tls"` + TLSSetting *configtls.ServerConfig `mapstructure:"tls"` // MaxRecvMsgSizeMiB sets the maximum size (in MiB) of messages accepted by the server. MaxRecvMsgSizeMiB uint64 `mapstructure:"max_recv_msg_size_mib"` @@ -151,8 +150,8 @@ type GRPCServerSettings struct { IncludeMetadata bool `mapstructure:"include_metadata"` } -// SanitizedEndpoint strips the prefix of either http:// or https:// from configgrpc.GRPCClientSettings.Endpoint. -func (gcs *GRPCClientSettings) SanitizedEndpoint() string { +// SanitizedEndpoint strips the prefix of either http:// or https:// from configgrpc.ClientConfig.Endpoint. +func (gcs *ClientConfig) SanitizedEndpoint() string { switch { case gcs.isSchemeHTTP(): return strings.TrimPrefix(gcs.Endpoint, "http://") @@ -163,11 +162,11 @@ func (gcs *GRPCClientSettings) SanitizedEndpoint() string { } } -func (gcs *GRPCClientSettings) isSchemeHTTP() bool { +func (gcs *ClientConfig) isSchemeHTTP() bool { return strings.HasPrefix(gcs.Endpoint, "http://") } -func (gcs *GRPCClientSettings) isSchemeHTTPS() bool { +func (gcs *ClientConfig) isSchemeHTTPS() bool { return strings.HasPrefix(gcs.Endpoint, "https://") } @@ -175,7 +174,7 @@ func (gcs *GRPCClientSettings) isSchemeHTTPS() bool { // a non-blocking dial (the function won't wait for connections to be // established, and connecting happens in the background). To make it a blocking // dial, use grpc.WithBlock() dial option. -func (gcs *GRPCClientSettings) ToClientConn(ctx context.Context, host component.Host, settings component.TelemetrySettings, extraOpts ...grpc.DialOption) (*grpc.ClientConn, error) { +func (gcs *ClientConfig) ToClientConn(ctx context.Context, host component.Host, settings component.TelemetrySettings, extraOpts ...grpc.DialOption) (*grpc.ClientConn, error) { opts, err := gcs.toDialOptions(host, settings) if err != nil { return nil, err @@ -184,9 +183,9 @@ func (gcs *GRPCClientSettings) ToClientConn(ctx context.Context, host component. return grpc.DialContext(ctx, gcs.SanitizedEndpoint(), opts...) } -func (gcs *GRPCClientSettings) toDialOptions(host component.Host, settings component.TelemetrySettings) ([]grpc.DialOption, error) { +func (gcs *ClientConfig) toDialOptions(host component.Host, settings component.TelemetrySettings) ([]grpc.DialOption, error) { var opts []grpc.DialOption - if configcompression.IsCompressed(gcs.Compression) { + if gcs.Compression.IsCompressed() { cp, err := getGRPCCompressionName(gcs.Compression) if err != nil { return nil, err @@ -259,8 +258,7 @@ func (gcs *GRPCClientSettings) toDialOptions(host component.Host, settings compo } // Enable OpenTelemetry observability plugin. - opts = append(opts, grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor(otelOpts...))) - opts = append(opts, grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor(otelOpts...))) + opts = append(opts, grpc.WithStatsHandler(otelgrpc.NewClientHandler(otelOpts...))) return opts, nil } @@ -269,12 +267,14 @@ func validateBalancerName(balancerName string) bool { return balancer.Get(balancerName) != nil } -// ToListener returns the net.Listener constructed from the settings. -func (gss *GRPCServerSettings) ToListener() (net.Listener, error) { - return gss.NetAddr.Listen() +// ToServer returns a grpc.Server for the configuration +// Deprecated: [0.96.0] Use ToServerContext instead. +func (gss *ServerConfig) ToServer(host component.Host, settings component.TelemetrySettings, extraOpts ...grpc.ServerOption) (*grpc.Server, error) { + return gss.ToServerContext(context.Background(), host, settings, extraOpts...) } -func (gss *GRPCServerSettings) ToServer(host component.Host, settings component.TelemetrySettings, extraOpts ...grpc.ServerOption) (*grpc.Server, error) { +// ToServerContext returns a grpc.Server for the configuration +func (gss *ServerConfig) ToServerContext(_ context.Context, host component.Host, settings component.TelemetrySettings, extraOpts ...grpc.ServerOption) (*grpc.Server, error) { opts, err := gss.toServerOption(host, settings) if err != nil { return nil, err @@ -283,7 +283,7 @@ func (gss *GRPCServerSettings) ToServer(host component.Host, settings component. return grpc.NewServer(opts...), nil } -func (gss *GRPCServerSettings) toServerOption(host component.Host, settings component.TelemetrySettings) ([]grpc.ServerOption, error) { +func (gss *ServerConfig) toServerOption(host component.Host, settings component.TelemetrySettings) ([]grpc.ServerOption, error) { switch gss.NetAddr.Transport { case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6": internal.WarnOnUnspecifiedHost(settings.Logger, gss.NetAddr.Endpoint) @@ -367,26 +367,23 @@ func (gss *GRPCServerSettings) toServerOption(host component.Host, settings comp } // Enable OpenTelemetry observability plugin. - // TODO: Pass construct settings to have access to Tracer. - uInterceptors = append(uInterceptors, otelgrpc.UnaryServerInterceptor(otelOpts...)) - sInterceptors = append(sInterceptors, otelgrpc.StreamServerInterceptor(otelOpts...)) uInterceptors = append(uInterceptors, enhanceWithClientInformation(gss.IncludeMetadata)) sInterceptors = append(sInterceptors, enhanceStreamWithClientInformation(gss.IncludeMetadata)) - opts = append(opts, grpc.ChainUnaryInterceptor(uInterceptors...), grpc.ChainStreamInterceptor(sInterceptors...)) + opts = append(opts, grpc.StatsHandler(otelgrpc.NewServerHandler(otelOpts...)), grpc.ChainUnaryInterceptor(uInterceptors...), grpc.ChainStreamInterceptor(sInterceptors...)) return opts, nil } // getGRPCCompressionName returns compression name registered in grpc. -func getGRPCCompressionName(compressionType configcompression.CompressionType) (string, error) { +func getGRPCCompressionName(compressionType configcompression.Type) (string, error) { switch compressionType { - case configcompression.Gzip: + case configcompression.TypeGzip: return gzip.Name, nil - case configcompression.Snappy: + case configcompression.TypeSnappy: return snappy.Name, nil - case configcompression.Zstd: + case configcompression.TypeZstd: return zstd.Name, nil default: return "", fmt.Errorf("unsupported compression type %q", compressionType) diff --git a/config/configgrpc/configgrpc_test.go b/config/configgrpc/configgrpc_test.go index 175848a5ebf..7d646af2b3e 100644 --- a/config/configgrpc/configgrpc_test.go +++ b/config/configgrpc/configgrpc_test.go @@ -32,14 +32,13 @@ import ( "go.opentelemetry.io/collector/config/configtls" "go.opentelemetry.io/collector/extension/auth" "go.opentelemetry.io/collector/extension/auth/authtest" - "go.opentelemetry.io/collector/obsreport/obsreporttest" "go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp" ) // testBalancerBuilder facilitates testing validateBalancerName(). type testBalancerBuilder struct{} -func (testBalancerBuilder) Build(_ balancer.ClientConn, _ balancer.BuildOptions) balancer.Balancer { +func (testBalancerBuilder) Build(balancer.ClientConn, balancer.BuildOptions) balancer.Balancer { return nil } @@ -51,40 +50,47 @@ func init() { balancer.Register(testBalancerBuilder{}) } +var ( + componentID = component.MustNewID("component") + testAuthID = component.MustNewID("testauth") + mockID = component.MustNewID("mock") + doesntExistID = component.MustNewID("doesntexist") +) + func TestDefaultGrpcClientSettings(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(component.NewID("component")) + tt, err := componenttest.SetupTelemetry(componentID) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - gcs := &GRPCClientSettings{ - TLSSetting: configtls.TLSClientSetting{ + gcs := &ClientConfig{ + TLSSetting: configtls.ClientConfig{ Insecure: true, }, } - opts, err := gcs.toDialOptions(componenttest.NewNopHost(), tt.TelemetrySettings) + opts, err := gcs.toDialOptions(componenttest.NewNopHost(), tt.TelemetrySettings()) assert.NoError(t, err) - assert.Len(t, opts, 3) + assert.Len(t, opts, 2) } func TestAllGrpcClientSettings(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(component.NewID("component")) + tt, err := componenttest.SetupTelemetry(componentID) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) tests := []struct { - settings GRPCClientSettings + settings ClientConfig name string host component.Host }{ { name: "test all with gzip compression", - settings: GRPCClientSettings{ + settings: ClientConfig{ Headers: map[string]configopaque.String{ "test": "test", }, Endpoint: "localhost:1234", - Compression: configcompression.Gzip, - TLSSetting: configtls.TLSClientSetting{ + Compression: configcompression.TypeGzip, + TLSSetting: configtls.ClientConfig{ Insecure: false, }, Keepalive: &KeepaliveClientConfig{ @@ -97,23 +103,23 @@ func TestAllGrpcClientSettings(t *testing.T) { WaitForReady: true, BalancerName: "round_robin", Authority: "pseudo-authority", - Auth: &configauth.Authentication{AuthenticatorID: component.NewID("testauth")}, + Auth: &configauth.Authentication{AuthenticatorID: testAuthID}, }, host: &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("testauth"): &authtest.MockClient{}, + testAuthID: &authtest.MockClient{}, }, }, }, { name: "test all with snappy compression", - settings: GRPCClientSettings{ + settings: ClientConfig{ Headers: map[string]configopaque.String{ "test": "test", }, Endpoint: "localhost:1234", - Compression: configcompression.Snappy, - TLSSetting: configtls.TLSClientSetting{ + Compression: configcompression.TypeSnappy, + TLSSetting: configtls.ClientConfig{ Insecure: false, }, Keepalive: &KeepaliveClientConfig{ @@ -126,23 +132,23 @@ func TestAllGrpcClientSettings(t *testing.T) { WaitForReady: true, BalancerName: "round_robin", Authority: "pseudo-authority", - Auth: &configauth.Authentication{AuthenticatorID: component.NewID("testauth")}, + Auth: &configauth.Authentication{AuthenticatorID: testAuthID}, }, host: &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("testauth"): &authtest.MockClient{}, + testAuthID: &authtest.MockClient{}, }, }, }, { name: "test all with zstd compression", - settings: GRPCClientSettings{ + settings: ClientConfig{ Headers: map[string]configopaque.String{ "test": "test", }, Endpoint: "localhost:1234", - Compression: configcompression.Zstd, - TLSSetting: configtls.TLSClientSetting{ + Compression: configcompression.TypeZstd, + TLSSetting: configtls.ClientConfig{ Insecure: false, }, Keepalive: &KeepaliveClientConfig{ @@ -155,43 +161,43 @@ func TestAllGrpcClientSettings(t *testing.T) { WaitForReady: true, BalancerName: "configgrpc_balancer_test", Authority: "pseudo-authority", - Auth: &configauth.Authentication{AuthenticatorID: component.NewID("testauth")}, + Auth: &configauth.Authentication{AuthenticatorID: testAuthID}, }, host: &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("testauth"): &authtest.MockClient{}, + testAuthID: &authtest.MockClient{}, }, }, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - opts, err := test.settings.toDialOptions(test.host, tt.TelemetrySettings) + opts, err := test.settings.toDialOptions(test.host, tt.TelemetrySettings()) assert.NoError(t, err) - assert.Len(t, opts, 10) + assert.Len(t, opts, 9) }) } } func TestDefaultGrpcServerSettings(t *testing.T) { - gss := &GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + gss := &ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "0.0.0.0:1234", }, } opts, err := gss.toServerOption(componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) assert.NoError(t, err) - assert.Len(t, opts, 2) + assert.Len(t, opts, 3) } func TestAllGrpcServerSettingsExceptAuth(t *testing.T) { - gss := &GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + gss := &ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "localhost:1234", Transport: "tcp", }, - TLSSetting: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{}, + TLSSetting: &configtls.ServerConfig{ + TLSSetting: configtls.Config{}, ClientCAFile: "", }, MaxRecvMsgSizeMiB: 1, @@ -214,21 +220,40 @@ func TestAllGrpcServerSettingsExceptAuth(t *testing.T) { } opts, err := gss.toServerOption(componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) assert.NoError(t, err) - assert.Len(t, opts, 9) + assert.Len(t, opts, 10) } func TestGrpcServerAuthSettings(t *testing.T) { - gss := &GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + gss := &ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "0.0.0.0:1234", }, } gss.Auth = &configauth.Authentication{ - AuthenticatorID: component.NewID("mock"), + AuthenticatorID: mockID, } host := &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("mock"): auth.NewServer(), + mockID: auth.NewServer(), + }, + } + srv, err := gss.ToServerContext(context.Background(), host, componenttest.NewNopTelemetrySettings()) + assert.NoError(t, err) + assert.NotNil(t, srv) +} + +func TestGrpcServerAuthSettings_Deprecated(t *testing.T) { + gss := &ServerConfig{ + NetAddr: confignet.AddrConfig{ + Endpoint: "0.0.0.0:1234", + }, + } + gss.Auth = &configauth.Authentication{ + AuthenticatorID: mockID, + } + host := &mockHost{ + ext: map[component.ID]component.Component{ + mockID: auth.NewServer(), }, } srv, err := gss.ToServer(host, componenttest.NewNopTelemetrySettings()) @@ -237,23 +262,23 @@ func TestGrpcServerAuthSettings(t *testing.T) { } func TestGRPCClientSettingsError(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(component.NewID("component")) + tt, err := componenttest.SetupTelemetry(componentID) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) tests := []struct { - settings GRPCClientSettings + settings ClientConfig err string host component.Host }{ { err: "^failed to load TLS config: failed to load CA CertPool File: failed to load cert /doesnt/exist:", - settings: GRPCClientSettings{ + settings: ClientConfig{ Headers: nil, Endpoint: "", Compression: "", - TLSSetting: configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: "/doesnt/exist", }, Insecure: false, @@ -264,12 +289,12 @@ func TestGRPCClientSettingsError(t *testing.T) { }, { err: "^failed to load TLS config: failed to load TLS cert and key: for auth via TLS, provide both certificate and key, or neither", - settings: GRPCClientSettings{ + settings: ClientConfig{ Headers: nil, Endpoint: "", Compression: "", - TLSSetting: configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: configtls.ClientConfig{ + TLSSetting: configtls.Config{ CertFile: "/doesnt/exist", }, Insecure: false, @@ -280,13 +305,13 @@ func TestGRPCClientSettingsError(t *testing.T) { }, { err: "invalid balancer_name: test", - settings: GRPCClientSettings{ + settings: ClientConfig{ Headers: map[string]configopaque.String{ "test": "test", }, Endpoint: "localhost:1234", Compression: "gzip", - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: false, }, Keepalive: &KeepaliveClientConfig{ @@ -302,25 +327,25 @@ func TestGRPCClientSettingsError(t *testing.T) { }, { err: "failed to resolve authenticator \"doesntexist\": authenticator not found", - settings: GRPCClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", - Auth: &configauth.Authentication{AuthenticatorID: component.NewID("doesntexist")}, + Auth: &configauth.Authentication{AuthenticatorID: doesntExistID}, }, host: &mockHost{ext: map[component.ID]component.Component{}}, }, { err: "no extensions configuration available", - settings: GRPCClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", - Auth: &configauth.Authentication{AuthenticatorID: component.NewID("doesntexist")}, + Auth: &configauth.Authentication{AuthenticatorID: doesntExistID}, }, host: &mockHost{}, }, { err: "unsupported compression type \"zlib\"", - settings: GRPCClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: true, }, Compression: "zlib", @@ -329,9 +354,9 @@ func TestGRPCClientSettingsError(t *testing.T) { }, { err: "unsupported compression type \"deflate\"", - settings: GRPCClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: true, }, Compression: "deflate", @@ -340,9 +365,9 @@ func TestGRPCClientSettingsError(t *testing.T) { }, { err: "unsupported compression type \"bad\"", - settings: GRPCClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: true, }, Compression: "bad", @@ -352,7 +377,7 @@ func TestGRPCClientSettingsError(t *testing.T) { } for _, test := range tests { t.Run(test.err, func(t *testing.T) { - _, err := test.settings.ToClientConn(context.Background(), test.host, tt.TelemetrySettings) + _, err := test.settings.ToClientConn(context.Background(), test.host, tt.TelemetrySettings()) assert.Error(t, err) assert.Regexp(t, test.err, err) }) @@ -360,31 +385,31 @@ func TestGRPCClientSettingsError(t *testing.T) { } func TestUseSecure(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(component.NewID("component")) + tt, err := componenttest.SetupTelemetry(componentID) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - gcs := &GRPCClientSettings{ + gcs := &ClientConfig{ Headers: nil, Endpoint: "", Compression: "", - TLSSetting: configtls.TLSClientSetting{}, + TLSSetting: configtls.ClientConfig{}, Keepalive: nil, } - dialOpts, err := gcs.toDialOptions(componenttest.NewNopHost(), tt.TelemetrySettings) + dialOpts, err := gcs.toDialOptions(componenttest.NewNopHost(), tt.TelemetrySettings()) assert.NoError(t, err) - assert.Len(t, dialOpts, 3) + assert.Len(t, dialOpts, 2) } func TestGRPCServerWarning(t *testing.T) { tests := []struct { name string - settings GRPCServerSettings + settings ServerConfig len int }{ { - settings: GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + settings: ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "0.0.0.0:1234", Transport: "tcp", }, @@ -392,8 +417,8 @@ func TestGRPCServerWarning(t *testing.T) { len: 1, }, { - settings: GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + settings: ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "127.0.0.1:1234", Transport: "tcp", }, @@ -401,8 +426,8 @@ func TestGRPCServerWarning(t *testing.T) { len: 0, }, { - settings: GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + settings: ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "0.0.0.0:1234", Transport: "unix", }, @@ -429,18 +454,18 @@ func TestGRPCServerWarning(t *testing.T) { func TestGRPCServerSettingsError(t *testing.T) { tests := []struct { - settings GRPCServerSettings + settings ServerConfig err string }{ { err: "^failed to load TLS config: failed to load CA CertPool File: failed to load cert /doesnt/exist:", - settings: GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + settings: ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "127.0.0.1:1234", Transport: "tcp", }, - TLSSetting: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CAFile: "/doesnt/exist", }, }, @@ -448,13 +473,13 @@ func TestGRPCServerSettingsError(t *testing.T) { }, { err: "^failed to load TLS config: failed to load TLS cert and key: for auth via TLS, provide both certificate and key, or neither", - settings: GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + settings: ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "127.0.0.1:1234", Transport: "tcp", }, - TLSSetting: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CertFile: "/doesnt/exist", }, }, @@ -462,12 +487,12 @@ func TestGRPCServerSettingsError(t *testing.T) { }, { err: "^failed to load client CA CertPool: failed to load CA /doesnt/exist:", - settings: GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + settings: ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "127.0.0.1:1234", Transport: "tcp", }, - TLSSetting: &configtls.TLSServerSetting{ + TLSSetting: &configtls.ServerConfig{ ClientCAFile: "/doesnt/exist", }, }, @@ -475,58 +500,52 @@ func TestGRPCServerSettingsError(t *testing.T) { } for _, test := range tests { t.Run(test.err, func(t *testing.T) { - _, err := test.settings.ToServer(componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) + _, err := test.settings.ToServerContext(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) assert.Regexp(t, test.err, err) }) } } func TestGRPCServerSettings_ToListener_Error(t *testing.T) { - settings := GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + settings := ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "127.0.0.1:1234567", Transport: "tcp", }, - TLSSetting: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ - CertFile: "/doesnt/exist", - }, - }, - Keepalive: nil, } - _, err := settings.ToListener() + _, err := settings.NetAddr.Listen(context.Background()) assert.Error(t, err) } func TestHttpReception(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(component.NewID("component")) + tt, err := componenttest.SetupTelemetry(componentID) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) tests := []struct { name string - tlsServerCreds *configtls.TLSServerSetting - tlsClientCreds *configtls.TLSClientSetting + tlsServerCreds *configtls.ServerConfig + tlsClientCreds *configtls.ClientConfig hasError bool }{ { name: "noTLS", tlsServerCreds: nil, - tlsClientCreds: &configtls.TLSClientSetting{ + tlsClientCreds: &configtls.ClientConfig{ Insecure: true, }, }, { name: "TLS", - tlsServerCreds: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + tlsServerCreds: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), }, }, - tlsClientCreds: &configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + tlsClientCreds: &configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -534,13 +553,13 @@ func TestHttpReception(t *testing.T) { }, { name: "NoServerCertificates", - tlsServerCreds: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + tlsServerCreds: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, }, - tlsClientCreds: &configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + tlsClientCreds: &configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -549,16 +568,16 @@ func TestHttpReception(t *testing.T) { }, { name: "mTLS", - tlsServerCreds: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + tlsServerCreds: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), }, ClientCAFile: filepath.Join("testdata", "ca.crt"), }, - tlsClientCreds: &configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + tlsClientCreds: &configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "client.crt"), KeyFile: filepath.Join("testdata", "client.key"), @@ -568,16 +587,16 @@ func TestHttpReception(t *testing.T) { }, { name: "NoClientCertificate", - tlsServerCreds: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + tlsServerCreds: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), }, ClientCAFile: filepath.Join("testdata", "ca.crt"), }, - tlsClientCreds: &configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + tlsClientCreds: &configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -586,16 +605,16 @@ func TestHttpReception(t *testing.T) { }, { name: "WrongClientCA", - tlsServerCreds: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + tlsServerCreds: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), }, ClientCAFile: filepath.Join("testdata", "server.crt"), }, - tlsClientCreds: &configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + tlsClientCreds: &configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "client.crt"), KeyFile: filepath.Join("testdata", "client.key"), @@ -609,16 +628,16 @@ func TestHttpReception(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - gss := &GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + gss := &ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "localhost:0", Transport: "tcp", }, TLSSetting: test.tlsServerCreds, } - ln, err := gss.ToListener() + ln, err := gss.NetAddr.Listen(context.Background()) assert.NoError(t, err) - s, err := gss.ToServer(componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) + s, err := gss.ToServerContext(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) assert.NoError(t, err) ptraceotlp.RegisterGRPCServer(s, &grpcTraceServer{}) @@ -626,12 +645,13 @@ func TestHttpReception(t *testing.T) { _ = s.Serve(ln) }() - gcs := &GRPCClientSettings{ + gcs := &ClientConfig{ Endpoint: ln.Addr().String(), TLSSetting: *test.tlsClientCreds, } - grpcClientConn, errClient := gcs.ToClientConn(context.Background(), componenttest.NewNopHost(), tt.TelemetrySettings) + grpcClientConn, errClient := gcs.ToClientConn(context.Background(), componenttest.NewNopHost(), tt.TelemetrySettings()) assert.NoError(t, errClient) + defer func() { assert.NoError(t, grpcClientConn.Close()) }() c := ptraceotlp.NewGRPCClient(grpcClientConn) ctx, cancelFunc := context.WithTimeout(context.Background(), 2*time.Second) resp, errResp := c.Export(ctx, ptraceotlp.NewExportRequest(), grpc.WaitForReady(true)) @@ -651,20 +671,20 @@ func TestReceiveOnUnixDomainSocket(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("skipping test on windows") } - tt, err := obsreporttest.SetupTelemetry(component.NewID("component")) + tt, err := componenttest.SetupTelemetry(componentID) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) socketName := tempSocketName(t) - gss := &GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + gss := &ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: socketName, Transport: "unix", }, } - ln, err := gss.ToListener() + ln, err := gss.NetAddr.Listen(context.Background()) assert.NoError(t, err) - srv, err := gss.ToServer(componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) + srv, err := gss.ToServerContext(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) assert.NoError(t, err) ptraceotlp.RegisterGRPCServer(srv, &grpcTraceServer{}) @@ -672,14 +692,15 @@ func TestReceiveOnUnixDomainSocket(t *testing.T) { _ = srv.Serve(ln) }() - gcs := &GRPCClientSettings{ + gcs := &ClientConfig{ Endpoint: "unix://" + ln.Addr().String(), - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: true, }, } - grpcClientConn, errClient := gcs.ToClientConn(context.Background(), componenttest.NewNopHost(), tt.TelemetrySettings) + grpcClientConn, errClient := gcs.ToClientConn(context.Background(), componenttest.NewNopHost(), tt.TelemetrySettings()) assert.NoError(t, errClient) + defer func() { assert.NoError(t, grpcClientConn.Close()) }() c := ptraceotlp.NewGRPCClient(grpcClientConn) ctx, cancelFunc := context.WithTimeout(context.Background(), 2*time.Second) resp, errResp := c.Export(ctx, ptraceotlp.NewExportRequest(), grpc.WaitForReady(true)) @@ -804,7 +825,7 @@ func TestStreamInterceptorEnhancesClient(t *testing.T) { ctx: inCtx, } - handler := func(srv any, stream grpc.ServerStream) error { + handler := func(_ any, stream grpc.ServerStream) error { outContext = stream.Context() return nil } @@ -851,19 +872,19 @@ func TestClientInfoInterceptors(t *testing.T) { // prepare the server { - gss := &GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + gss := &ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "localhost:0", Transport: "tcp", }, } - srv, err := gss.ToServer(componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) + srv, err := gss.ToServerContext(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) require.NoError(t, err) ptraceotlp.RegisterGRPCServer(srv, mock) defer srv.Stop() - l, err = gss.ToListener() + l, err = gss.NetAddr.Listen(context.Background()) require.NoError(t, err) go func() { @@ -873,21 +894,22 @@ func TestClientInfoInterceptors(t *testing.T) { // prepare the client and execute a RPC { - gcs := &GRPCClientSettings{ + gcs := &ClientConfig{ Endpoint: l.Addr().String(), - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: true, }, } - tt, err := obsreporttest.SetupTelemetry(component.NewID("component")) + tt, err := componenttest.SetupTelemetry(componentID) require.NoError(t, err) defer func() { require.NoError(t, tt.Shutdown(context.Background())) }() - grpcClientConn, errClient := gcs.ToClientConn(context.Background(), componenttest.NewNopHost(), tt.TelemetrySettings) + grpcClientConn, errClient := gcs.ToClientConn(context.Background(), componenttest.NewNopHost(), tt.TelemetrySettings()) require.NoError(t, errClient) + defer func() { assert.NoError(t, grpcClientConn.Close()) }() cl := ptraceotlp.NewGRPCClient(grpcClientConn) ctx, cancelFunc := context.WithTimeout(context.Background(), 2*time.Second) @@ -918,7 +940,7 @@ func TestDefaultUnaryInterceptorAuthSucceeded(t *testing.T) { return ctx, nil } - handler := func(ctx context.Context, req any) (any, error) { + handler := func(ctx context.Context, _ any) (any, error) { handlerCalled = true cl := client.FromContext(ctx) assert.Equal(t, "1.2.3.4", cl.Addr.String()) @@ -944,7 +966,7 @@ func TestDefaultUnaryInterceptorAuthFailure(t *testing.T) { authCalled = true return context.Background(), expectedErr } - handler := func(ctx context.Context, req any) (any, error) { + handler := func(context.Context, any) (any, error) { assert.FailNow(t, "the handler should not have been called on auth failure!") return nil, nil } @@ -965,7 +987,7 @@ func TestDefaultUnaryInterceptorMissingMetadata(t *testing.T) { assert.FailNow(t, "the auth func should not have been called!") return context.Background(), nil } - handler := func(ctx context.Context, req any) (any, error) { + handler := func(context.Context, any) (any, error) { assert.FailNow(t, "the handler should not have been called!") return nil, nil } @@ -989,7 +1011,7 @@ func TestDefaultStreamInterceptorAuthSucceeded(t *testing.T) { }) return ctx, nil } - handler := func(srv any, stream grpc.ServerStream) error { + handler := func(_ any, stream grpc.ServerStream) error { // ensure that the client information is propagated down to the underlying stream cl := client.FromContext(stream.Context()) assert.Equal(t, "1.2.3.4", cl.Addr.String()) @@ -1018,7 +1040,7 @@ func TestDefaultStreamInterceptorAuthFailure(t *testing.T) { authCalled = true return context.Background(), expectedErr } - handler := func(srv any, stream grpc.ServerStream) error { + handler := func(any, grpc.ServerStream) error { assert.FailNow(t, "the handler should not have been called on auth failure!") return nil } @@ -1041,7 +1063,7 @@ func TestDefaultStreamInterceptorMissingMetadata(t *testing.T) { assert.FailNow(t, "the auth func should not have been called!") return context.Background(), nil } - handler := func(srv any, stream grpc.ServerStream) error { + handler := func(any, grpc.ServerStream) error { assert.FailNow(t, "the handler should not have been called!") return nil } diff --git a/config/configgrpc/go.mod b/config/configgrpc/go.mod index d0b3bfec179..224c724c8e6 100644 --- a/config/configgrpc/go.mod +++ b/config/configgrpc/go.mod @@ -1,79 +1,69 @@ module go.opentelemetry.io/collector/config/configgrpc -go 1.20 +go 1.21 require ( - github.com/mostynb/go-grpc-compression v1.2.1 + github.com/mostynb/go-grpc-compression v1.2.2 github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/configauth v0.85.0 - go.opentelemetry.io/collector/config/configcompression v0.85.0 - go.opentelemetry.io/collector/config/confignet v0.85.0 - go.opentelemetry.io/collector/config/configopaque v0.85.0 - go.opentelemetry.io/collector/config/configtls v0.85.0 - go.opentelemetry.io/collector/config/internal v0.85.0 - go.opentelemetry.io/collector/extension/auth v0.85.0 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 - go.opentelemetry.io/otel v1.18.0 - go.uber.org/zap v1.26.0 - google.golang.org/grpc v1.58.1 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/configauth v0.96.0 + go.opentelemetry.io/collector/config/configcompression v0.96.0 + go.opentelemetry.io/collector/config/confignet v0.96.0 + go.opentelemetry.io/collector/config/configopaque v1.3.0 + go.opentelemetry.io/collector/config/configtls v0.96.0 + go.opentelemetry.io/collector/config/internal v0.96.0 + go.opentelemetry.io/collector/extension/auth v0.96.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 + go.opentelemetry.io/otel v1.24.0 + go.uber.org/goleak v1.3.0 + go.uber.org/zap v1.27.0 + google.golang.org/grpc v1.62.0 ) require ( cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68 // indirect - contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.0 // indirect + github.com/klauspost/compress v1.17.2 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect - github.com/prometheus/statsd_exporter v0.22.7 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 // indirect - go.opentelemetry.io/collector/confmap v0.85.0 // indirect - go.opentelemetry.io/collector/consumer v0.85.0 // indirect - go.opentelemetry.io/collector/exporter v0.85.0 // indirect - go.opentelemetry.io/collector/extension v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/processor v0.85.0 // indirect - go.opentelemetry.io/collector/receiver v0.85.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/sdk v1.18.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/confmap v0.96.0 // indirect + go.opentelemetry.io/collector/extension v0.96.0 // indirect + go.opentelemetry.io/collector/featuregate v1.3.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -99,24 +89,10 @@ replace go.opentelemetry.io/collector/extension/auth => ../../extension/auth replace go.opentelemetry.io/collector/confmap => ../../confmap -replace go.opentelemetry.io/collector/processor => ../../processor - -replace go.opentelemetry.io/collector/exporter => ../../exporter - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension - -replace go.opentelemetry.io/collector/receiver => ../../receiver - -replace go.opentelemetry.io/collector/connector => ../../connector - replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata replace go.opentelemetry.io/collector/component => ../../component -replace go.opentelemetry.io/collector/semconv => ../../semconv - replace go.opentelemetry.io/collector/consumer => ../../consumer - -replace go.opentelemetry.io/collector/service => ../../service diff --git a/config/configgrpc/go.sum b/config/configgrpc/go.sum index 29dbc55cf07..6774b9cc3c9 100644 --- a/config/configgrpc/go.sum +++ b/config/configgrpc/go.sum @@ -1,601 +1,150 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68 h1:aRVqY1p2IJaBGStWMsQMpkAa83cPkCDLl80eOj0Rbz4= cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68/go.mod h1:1a3eRNYX12fs5UABBIXS8HXVvQbX9hRB/RkEBPORpe8= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mostynb/go-grpc-compression v1.2.1 h1:16tdYxBZSD8p9AUmvw4F7Nyc2T4/eE7XsIXrgxSEcJI= -github.com/mostynb/go-grpc-compression v1.2.1/go.mod h1:oidYvYyefMmhcuvU8fLJ8FfZyTyVzJ6SkmD5fIKgRe8= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/mostynb/go-grpc-compression v1.2.2 h1:XaDbnRvt2+1vgr0b/l0qh4mJAfIxE0bKXtz2Znl3GGI= +github.com/mostynb/go-grpc-compression v1.2.2/go.mod h1:GOCr2KBxXcblCuczg3YdLQlcin1/NfyDA348ckuCH6w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/config/configgrpc/package_test.go b/config/configgrpc/package_test.go new file mode 100644 index 00000000000..519657748da --- /dev/null +++ b/config/configgrpc/package_test.go @@ -0,0 +1,17 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package configgrpc + +import ( + "testing" + + "go.uber.org/goleak" +) + +// The IgnoreTopFunction call prevents catching the leak generated by opencensus +// defaultWorker.Start which at this time is part of the package's init call. +// See https://github.com/open-telemetry/opentelemetry-collector/issues/9165#issuecomment-1874836336 for more context. +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m, goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start")) +} diff --git a/config/confighttp/README.md b/config/confighttp/README.md index 2249f6c72db..beb28028bdb 100644 --- a/config/confighttp/README.md +++ b/config/confighttp/README.md @@ -16,7 +16,10 @@ README](../configtls/README.md). - `endpoint`: address:port - [`tls`](../configtls/README.md) -- `headers`: name/value pairs added to the HTTP request headers +- [`headers`](https://pkg.go.dev/net/http#Request): name/value pairs added to the HTTP request headers + - certain headers such as Content-Length and Connection are automatically written when needed and values in Header may be ignored. + - `Host` header is automatically derived from `endpoint` value. However, this automatic assignment can be overridden by explicitly setting the Host field in the headers field. + - if `Host` header is provided then it overrides `Host` field in [Request](https://pkg.go.dev/net/http#Request) which results as an override of `Host` header value. - [`read_buffer_size`](https://golang.org/pkg/net/http/#Transport) - [`timeout`](https://golang.org/pkg/net/http/#Client) - [`write_buffer_size`](https://golang.org/pkg/net/http/#Transport) @@ -29,6 +32,8 @@ README](../configtls/README.md). - [`idle_conn_timeout`](https://golang.org/pkg/net/http/#Transport) - [`auth`](../configauth/README.md) - [`disable_keep_alives`](https://golang.org/pkg/net/http/#Transport) +- [`http2_read_idle_timeout`](https://pkg.go.dev/golang.org/x/net/http2#Transport) +- [`http2_ping_timeout`](https://pkg.go.dev/golang.org/x/net/http2#Transport) Example: @@ -69,6 +74,7 @@ will not be enabled. header, allowing clients to cache the response to CORS preflight requests. If not set, browsers use a default of 5 seconds. - `endpoint`: Valid value syntax available [here](https://github.com/grpc/grpc/blob/master/doc/naming.md) +- `max_request_body_size`: configures the maximum allowed body size in bytes for a single request. Default: `0` (no restriction) - [`tls`](../configtls/README.md) - [`auth`](../configauth/README.md) diff --git a/config/confighttp/clientinfohandler.go b/config/confighttp/clientinfohandler.go index 25105cf51a6..464153bc2c7 100644 --- a/config/confighttp/clientinfohandler.go +++ b/config/confighttp/clientinfohandler.go @@ -11,8 +11,6 @@ import ( "go.opentelemetry.io/collector/client" ) -var _ http.Handler = (*clientInfoHandler)(nil) - // clientInfoHandler is an http.Handler that enhances the incoming request context with client.Info. type clientInfoHandler struct { next http.Handler diff --git a/config/confighttp/clientinfohandler_test.go b/config/confighttp/clientinfohandler_test.go index d8201cad149..bbd18ec52fd 100644 --- a/config/confighttp/clientinfohandler_test.go +++ b/config/confighttp/clientinfohandler_test.go @@ -5,11 +5,14 @@ package confighttp // import "go.opentelemetry.io/collector/config/confighttp" import ( "net" + "net/http" "testing" "github.com/stretchr/testify/assert" ) +var _ http.Handler = (*clientInfoHandler)(nil) + func TestParseIP(t *testing.T) { testCases := []struct { desc string diff --git a/config/confighttp/compression.go b/config/confighttp/compression.go index faa716c4414..88ecafe78da 100644 --- a/config/confighttp/compression.go +++ b/config/confighttp/compression.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/snappy" "github.com/klauspost/compress/zstd" "go.opentelemetry.io/collector/config/configcompression" @@ -20,11 +21,11 @@ import ( type compressRoundTripper struct { rt http.RoundTripper - compressionType configcompression.CompressionType + compressionType configcompression.Type compressor *compressor } -func newCompressRoundTripper(rt http.RoundTripper, compressionType configcompression.CompressionType) (*compressRoundTripper, error) { +func newCompressRoundTripper(rt http.RoundTripper, compressionType configcompression.Type) (*compressRoundTripper, error) { encoder, err := newCompressor(compressionType) if err != nil { return nil, err @@ -85,7 +86,7 @@ func httpContentDecompressor(h http.Handler, eh func(w http.ResponseWriter, r *h errHandler: errHandler, base: h, decoders: map[string]func(body io.ReadCloser) (io.ReadCloser, error){ - "": func(body io.ReadCloser) (io.ReadCloser, error) { + "": func(io.ReadCloser) (io.ReadCloser, error) { // Not a compressed payload. Nothing to do. return nil, nil }, @@ -117,6 +118,18 @@ func httpContentDecompressor(h http.Handler, eh func(w http.ResponseWriter, r *h } return zr, nil }, + "snappy": func(body io.ReadCloser) (io.ReadCloser, error) { + sr := snappy.NewReader(body) + sb := new(bytes.Buffer) + _, err := io.Copy(sb, sr) + if err != nil { + return nil, err + } + if err = body.Close(); err != nil { + return nil, err + } + return io.NopCloser(sb), nil + }, }, } d.decoders["deflate"] = d.decoders["zlib"] diff --git a/config/confighttp/compression_test.go b/config/confighttp/compression_test.go index 091d9faff12..63d9ba02ab9 100644 --- a/config/confighttp/compression_test.go +++ b/config/confighttp/compression_test.go @@ -33,7 +33,7 @@ func TestHTTPClientCompression(t *testing.T) { tests := []struct { name string - encoding configcompression.CompressionType + encoding configcompression.Type reqBody []byte shouldError bool }{ @@ -51,31 +51,31 @@ func TestHTTPClientCompression(t *testing.T) { }, { name: "ValidGzip", - encoding: configcompression.Gzip, + encoding: configcompression.TypeGzip, reqBody: compressedGzipBody.Bytes(), shouldError: false, }, { name: "ValidZlib", - encoding: configcompression.Zlib, + encoding: configcompression.TypeZlib, reqBody: compressedZlibBody.Bytes(), shouldError: false, }, { name: "ValidDeflate", - encoding: configcompression.Deflate, + encoding: configcompression.TypeDeflate, reqBody: compressedDeflateBody.Bytes(), shouldError: false, }, { name: "ValidSnappy", - encoding: configcompression.Snappy, + encoding: configcompression.TypeSnappy, reqBody: compressedSnappyBody.Bytes(), shouldError: false, }, { name: "ValidZstd", - encoding: configcompression.Zstd, + encoding: configcompression.TypeZstd, reqBody: compressedZstdBody.Bytes(), shouldError: false, }, @@ -95,7 +95,7 @@ func TestHTTPClientCompression(t *testing.T) { req, err := http.NewRequest(http.MethodGet, srv.URL, reqBody) require.NoError(t, err, "failed to create request to test handler") - clientSettings := HTTPClientSettings{ + clientSettings := ClientConfig{ Endpoint: srv.URL, Compression: tt.encoding, } @@ -190,6 +190,12 @@ func TestHTTPContentDecompressionHandler(t *testing.T) { reqBody: compressZstd(t, testBody), respCode: http.StatusOK, }, + { + name: "ValidSnappy", + encoding: "snappy", + reqBody: compressSnappy(t, testBody), + respCode: http.StatusOK, + }, { name: "InvalidDeflate", encoding: "deflate", @@ -218,6 +224,13 @@ func TestHTTPContentDecompressionHandler(t *testing.T) { respCode: http.StatusBadRequest, respBody: "invalid input: magic number mismatch", }, + { + name: "InvalidSnappy", + encoding: "snappy", + reqBody: bytes.NewBuffer(testBody), + respCode: http.StatusBadRequest, + respBody: "snappy: corrupt input\n", + }, { name: "UnsupportedCompression", encoding: "nosuchcompression", @@ -274,7 +287,7 @@ func TestHTTPContentCompressionRequestWithNilBody(t *testing.T) { require.NoError(t, err, "failed to create request to test handler") client := http.Client{} - client.Transport, err = newCompressRoundTripper(http.DefaultTransport, configcompression.Gzip) + client.Transport, err = newCompressRoundTripper(http.DefaultTransport, configcompression.TypeGzip) require.NoError(t, err) res, err := client.Do(req) require.NoError(t, err) @@ -287,7 +300,7 @@ func TestHTTPContentCompressionRequestWithNilBody(t *testing.T) { type copyFailBody struct { } -func (*copyFailBody) Read(_ []byte) (n int, err error) { +func (*copyFailBody) Read([]byte) (n int, err error) { return 0, fmt.Errorf("read failed") } @@ -296,7 +309,7 @@ func (*copyFailBody) Close() error { } func TestHTTPContentCompressionCopyError(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) })) t.Cleanup(server.Close) @@ -305,7 +318,7 @@ func TestHTTPContentCompressionCopyError(t *testing.T) { require.NoError(t, err) client := http.Client{} - client.Transport, err = newCompressRoundTripper(http.DefaultTransport, configcompression.Gzip) + client.Transport, err = newCompressRoundTripper(http.DefaultTransport, configcompression.TypeGzip) require.NoError(t, err) _, err = client.Do(req) require.Error(t, err) @@ -320,7 +333,7 @@ func (*closeFailBody) Close() error { } func TestHTTPContentCompressionRequestBodyCloseError(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) })) t.Cleanup(server.Close) @@ -329,7 +342,7 @@ func TestHTTPContentCompressionRequestBodyCloseError(t *testing.T) { require.NoError(t, err) client := http.Client{} - client.Transport, err = newCompressRoundTripper(http.DefaultTransport, configcompression.Gzip) + client.Transport, err = newCompressRoundTripper(http.DefaultTransport, configcompression.TypeGzip) require.NoError(t, err) _, err = client.Do(req) require.Error(t, err) diff --git a/config/confighttp/compressor.go b/config/confighttp/compressor.go index 0ff951d4130..3e085bead0d 100644 --- a/config/confighttp/compressor.go +++ b/config/confighttp/compressor.go @@ -39,15 +39,15 @@ type compressor struct { // writerFactory defines writer field in CompressRoundTripper. // The validity of input is already checked when NewCompressRoundTripper was called in confighttp, -func newCompressor(compressionType configcompression.CompressionType) (*compressor, error) { +func newCompressor(compressionType configcompression.Type) (*compressor, error) { switch compressionType { - case configcompression.Gzip: + case configcompression.TypeGzip: return gZipPool, nil - case configcompression.Snappy: + case configcompression.TypeSnappy: return snappyPool, nil - case configcompression.Zstd: + case configcompression.TypeZstd: return zStdPool, nil - case configcompression.Zlib, configcompression.Deflate: + case configcompression.TypeZlib, configcompression.TypeDeflate: return zLibPool, nil } return nil, errors.New("unsupported compression type, ") diff --git a/config/confighttp/confighttp.go b/config/confighttp/confighttp.go index 9294b6ee78c..40ec4ba0b83 100644 --- a/config/confighttp/confighttp.go +++ b/config/confighttp/confighttp.go @@ -6,9 +6,11 @@ package confighttp // import "go.opentelemetry.io/collector/config/confighttp" import ( "crypto/tls" "errors" + "fmt" "io" "net" "net/http" + "net/url" "time" "github.com/rs/cors" @@ -27,13 +29,16 @@ import ( const headerContentEncoding = "Content-Encoding" -// HTTPClientSettings defines settings for creating an HTTP client. -type HTTPClientSettings struct { +// ClientConfig defines settings for creating an HTTP client. +type ClientConfig struct { // The target URL to send data to (e.g.: http://some.url:9411/v1/traces). Endpoint string `mapstructure:"endpoint"` + // ProxyURL setting for the collector + ProxyURL string `mapstructure:"proxy_url"` + // TLSSetting struct exposes TLS client configuration. - TLSSetting configtls.TLSClientSetting `mapstructure:"tls"` + TLSSetting configtls.ClientConfig `mapstructure:"tls"` // ReadBufferSize for HTTP client. See http.Transport.ReadBufferSize. ReadBufferSize int `mapstructure:"read_buffer_size"` @@ -56,7 +61,7 @@ type HTTPClientSettings struct { Auth *configauth.Authentication `mapstructure:"auth"` // The compression key for supported compression types within collector. - Compression configcompression.CompressionType `mapstructure:"compression"` + Compression configcompression.Type `mapstructure:"compression"` // MaxIdleConns is used to set a limit to the maximum idle HTTP connections the client can keep open. // There's an already set value, and we want to override it only if an explicit value provided @@ -82,25 +87,35 @@ type HTTPClientSettings struct { // connection for every request. Before enabling this option please consider whether changes // to idle connection settings can achieve your goal. DisableKeepAlives bool `mapstructure:"disable_keep_alives"` + + // This is needed in case you run into + // https://github.com/golang/go/issues/59690 + // https://github.com/golang/go/issues/36026 + // HTTP2ReadIdleTimeout if the connection has been idle for the configured value send a ping frame for health check + // 0s means no health check will be performed. + HTTP2ReadIdleTimeout time.Duration `mapstructure:"http2_read_idle_timeout"` + // HTTP2PingTimeout if there's no response to the ping within the configured value, the connection will be closed. + // If not set or set to 0, it defaults to 15s. + HTTP2PingTimeout time.Duration `mapstructure:"http2_ping_timeout"` } -// NewDefaultHTTPClientSettings returns HTTPClientSettings type object with +// NewDefaultClientConfig returns ClientConfig type object with // the default values of 'MaxIdleConns' and 'IdleConnTimeout'. // Other config options are not added as they are initialized with 'zero value' by GoLang as default. -// We encourage to use this function to create an object of HTTPClientSettings. -func NewDefaultHTTPClientSettings() HTTPClientSettings { +// We encourage to use this function to create an object of ClientConfig. +func NewDefaultClientConfig() ClientConfig { // The default values are taken from the values of 'DefaultTransport' of 'http' package. maxIdleConns := 100 idleConnTimeout := 90 * time.Second - return HTTPClientSettings{ + return ClientConfig{ MaxIdleConns: &maxIdleConns, IdleConnTimeout: &idleConnTimeout, } } // ToClient creates an HTTP client. -func (hcs *HTTPClientSettings) ToClient(host component.Host, settings component.TelemetrySettings) (*http.Client, error) { +func (hcs *ClientConfig) ToClient(host component.Host, settings component.TelemetrySettings) (*http.Client, error) { tlsCfg, err := hcs.TLSSetting.LoadTLSConfig() if err != nil { return nil, err @@ -132,8 +147,26 @@ func (hcs *HTTPClientSettings) ToClient(host component.Host, settings component. transport.IdleConnTimeout = *hcs.IdleConnTimeout } + // Setting the Proxy URL + if hcs.ProxyURL != "" { + proxyURL, parseErr := url.ParseRequestURI(hcs.ProxyURL) + if parseErr != nil { + return nil, parseErr + } + transport.Proxy = http.ProxyURL(proxyURL) + } + transport.DisableKeepAlives = hcs.DisableKeepAlives + if hcs.HTTP2ReadIdleTimeout > 0 { + transport2, transportErr := http2.ConfigureTransports(transport) + if transportErr != nil { + return nil, fmt.Errorf("failed to configure http2 transport: %w", transportErr) + } + transport2.ReadIdleTimeout = hcs.HTTP2ReadIdleTimeout + transport2.PingTimeout = hcs.HTTP2PingTimeout + } + clientTransport := (http.RoundTripper)(transport) // The Auth RoundTripper should always be the innermost to ensure that @@ -165,7 +198,7 @@ func (hcs *HTTPClientSettings) ToClient(host component.Host, settings component. // Compress the body using specified compression methods if non-empty string is provided. // Supporting gzip, zlib, deflate, snappy, and zstd; none is treated as uncompressed. - if configcompression.IsCompressed(hcs.Compression) { + if hcs.Compression.IsCompressed() { clientTransport, err = newCompressRoundTripper(clientTransport, hcs.Compression) if err != nil { return nil, err @@ -203,23 +236,30 @@ type headerRoundTripper struct { // RoundTrip is a custom RoundTripper that adds headers to the request. func (interceptor *headerRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + // Set Host header if provided + hostHeader, found := interceptor.headers["Host"] + if found && hostHeader != "" { + // `Host` field should be set to override default `Host` header value which is Endpoint + req.Host = string(hostHeader) + } for k, v := range interceptor.headers { req.Header.Set(k, string(v)) } + // Send the request to next transport. return interceptor.transport.RoundTrip(req) } -// HTTPServerSettings defines settings for creating an HTTP server. -type HTTPServerSettings struct { +// ServerConfig defines settings for creating an HTTP server. +type ServerConfig struct { // Endpoint configures the listening address for the server. Endpoint string `mapstructure:"endpoint"` // TLSSetting struct exposes TLS client configuration. - TLSSetting *configtls.TLSServerSetting `mapstructure:"tls"` + TLSSetting *configtls.ServerConfig `mapstructure:"tls"` // CORS configures the server for HTTP cross-origin resource sharing (CORS). - CORS *CORSSettings `mapstructure:"cors"` + CORS *CORSConfig `mapstructure:"cors"` // Auth for this receiver Auth *configauth.Authentication `mapstructure:"auth"` @@ -240,7 +280,7 @@ type HTTPServerSettings struct { } // ToListener creates a net.Listener. -func (hss *HTTPServerSettings) ToListener() (net.Listener, error) { +func (hss *ServerConfig) ToListener() (net.Listener, error) { listener, err := net.Listen("tcp", hss.Endpoint) if err != nil { return nil, err @@ -259,14 +299,14 @@ func (hss *HTTPServerSettings) ToListener() (net.Listener, error) { } // toServerOptions has options that change the behavior of the HTTP server -// returned by HTTPServerSettings.ToServer(). +// returned by ServerConfig.ToServer(). type toServerOptions struct { errHandler func(w http.ResponseWriter, r *http.Request, errorMsg string, statusCode int) decoders map[string]func(body io.ReadCloser) (io.ReadCloser, error) } // ToServerOption is an option to change the behavior of the HTTP server -// returned by HTTPServerSettings.ToServer(). +// returned by ServerConfig.ToServer(). type ToServerOption func(opts *toServerOptions) // WithErrorHandler overrides the HTTP error handler that gets invoked @@ -289,7 +329,7 @@ func WithDecoder(key string, dec func(body io.ReadCloser) (io.ReadCloser, error) } // ToServer creates an http.Server from settings object. -func (hss *HTTPServerSettings) ToServer(host component.Host, settings component.TelemetrySettings, handler http.Handler, opts ...ToServerOption) (*http.Server, error) { +func (hss *ServerConfig) ToServer(host component.Host, settings component.TelemetrySettings, handler http.Handler, opts ...ToServerOption) (*http.Server, error) { internal.WarnOnUnspecifiedHost(settings.Logger, hss.Endpoint) serverOpts := &toServerOptions{} @@ -323,7 +363,6 @@ func (hss *HTTPServerSettings) ToServer(host component.Host, settings component. handler = rateLimitInterceptor(handler, limiter) } - // TODO: emit a warning when non-empty CorsHeaders and empty CorsOrigins. if hss.CORS != nil && len(hss.CORS.AllowedOrigins) > 0 { co := cors.Options{ AllowedOrigins: hss.CORS.AllowedOrigins, @@ -333,6 +372,9 @@ func (hss *HTTPServerSettings) ToServer(host component.Host, settings component. } handler = cors.New(co).Handler(handler) } + if hss.CORS != nil && len(hss.CORS.AllowedOrigins) == 0 && len(hss.CORS.AllowedHeaders) > 0 { + settings.Logger.Warn("The CORS configuration specifies allowed headers but no allowed origins, and is therefore ignored.") + } if hss.ResponseHeaders != nil { handler = responseHeadersHandler(handler, hss.ResponseHeaders) @@ -346,7 +388,7 @@ func (hss *HTTPServerSettings) ToServer(host component.Host, settings component. otelhttp.WithTracerProvider(settings.TracerProvider), otelhttp.WithMeterProvider(settings.MeterProvider), otelhttp.WithPropagators(otel.GetTextMapPropagator()), - otelhttp.WithSpanNameFormatter(func(operation string, r *http.Request) string { + otelhttp.WithSpanNameFormatter(func(_ string, r *http.Request) string { return r.URL.Path }), ) @@ -374,9 +416,9 @@ func responseHeadersHandler(handler http.Handler, headers map[string]configopaqu }) } -// CORSSettings configures a receiver for HTTP cross-origin resource sharing (CORS). +// CORSConfig configures a receiver for HTTP cross-origin resource sharing (CORS). // See the underlying https://github.com/rs/cors package for details. -type CORSSettings struct { +type CORSConfig struct { // AllowedOrigins sets the allowed values of the Origin header for // HTTP/JSON requests to an OTLP receiver. An origin may contain a // wildcard (*) to replace 0 or more characters (e.g., diff --git a/config/confighttp/confighttp_test.go b/config/confighttp/confighttp_test.go index 5d62a7af930..fc90f8f7caf 100644 --- a/config/confighttp/confighttp_test.go +++ b/config/confighttp/confighttp_test.go @@ -38,14 +38,21 @@ type customRoundTripper struct { var _ http.RoundTripper = (*customRoundTripper)(nil) -func (c *customRoundTripper) RoundTrip(_ *http.Request) (*http.Response, error) { +func (c *customRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { return nil, nil } +var ( + testAuthID = component.MustNewID("testauth") + mockID = component.MustNewID("mock") + dummyID = component.MustNewID("dummy") + nonExistingID = component.MustNewID("nonexisting") +) + func TestAllHTTPClientSettings(t *testing.T) { host := &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("testauth"): &authtest.MockClient{ResultRoundTripper: &customRoundTripper{}}, + testAuthID: &authtest.MockClient{ResultRoundTripper: &customRoundTripper{}}, }, } @@ -53,78 +60,106 @@ func TestAllHTTPClientSettings(t *testing.T) { maxIdleConnsPerHost := 40 maxConnsPerHost := 45 idleConnTimeout := 30 * time.Second + http2PingTimeout := 5 * time.Second tests := []struct { name string - settings HTTPClientSettings + settings ClientConfig shouldError bool }{ { name: "all_valid_settings", - settings: HTTPClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: false, }, - ReadBufferSize: 1024, - WriteBufferSize: 512, - MaxIdleConns: &maxIdleConns, - MaxIdleConnsPerHost: &maxIdleConnsPerHost, - MaxConnsPerHost: &maxConnsPerHost, - IdleConnTimeout: &idleConnTimeout, - CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return next, nil }, - Compression: "", - DisableKeepAlives: true, + ReadBufferSize: 1024, + WriteBufferSize: 512, + MaxIdleConns: &maxIdleConns, + MaxIdleConnsPerHost: &maxIdleConnsPerHost, + MaxConnsPerHost: &maxConnsPerHost, + IdleConnTimeout: &idleConnTimeout, + CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return next, nil }, + Compression: "", + DisableKeepAlives: true, + HTTP2ReadIdleTimeout: idleConnTimeout, + HTTP2PingTimeout: http2PingTimeout, }, shouldError: false, }, { name: "all_valid_settings_with_none_compression", - settings: HTTPClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: false, }, - ReadBufferSize: 1024, - WriteBufferSize: 512, - MaxIdleConns: &maxIdleConns, - MaxIdleConnsPerHost: &maxIdleConnsPerHost, - MaxConnsPerHost: &maxConnsPerHost, - IdleConnTimeout: &idleConnTimeout, - CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return next, nil }, - Compression: "none", - DisableKeepAlives: true, + ReadBufferSize: 1024, + WriteBufferSize: 512, + MaxIdleConns: &maxIdleConns, + MaxIdleConnsPerHost: &maxIdleConnsPerHost, + MaxConnsPerHost: &maxConnsPerHost, + IdleConnTimeout: &idleConnTimeout, + CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return next, nil }, + Compression: "none", + DisableKeepAlives: true, + HTTP2ReadIdleTimeout: idleConnTimeout, + HTTP2PingTimeout: http2PingTimeout, }, shouldError: false, }, { name: "all_valid_settings_with_gzip_compression", - settings: HTTPClientSettings{ + settings: ClientConfig{ + Endpoint: "localhost:1234", + TLSSetting: configtls.ClientConfig{ + Insecure: false, + }, + ReadBufferSize: 1024, + WriteBufferSize: 512, + MaxIdleConns: &maxIdleConns, + MaxIdleConnsPerHost: &maxIdleConnsPerHost, + MaxConnsPerHost: &maxConnsPerHost, + IdleConnTimeout: &idleConnTimeout, + CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return next, nil }, + Compression: "gzip", + DisableKeepAlives: true, + HTTP2ReadIdleTimeout: idleConnTimeout, + HTTP2PingTimeout: http2PingTimeout, + }, + shouldError: false, + }, + { + name: "all_valid_settings_http2_health_check", + settings: ClientConfig{ Endpoint: "localhost:1234", - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: false, }, - ReadBufferSize: 1024, - WriteBufferSize: 512, - MaxIdleConns: &maxIdleConns, - MaxIdleConnsPerHost: &maxIdleConnsPerHost, - MaxConnsPerHost: &maxConnsPerHost, - IdleConnTimeout: &idleConnTimeout, - CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return next, nil }, - Compression: "gzip", - DisableKeepAlives: true, + ReadBufferSize: 1024, + WriteBufferSize: 512, + MaxIdleConns: &maxIdleConns, + MaxIdleConnsPerHost: &maxIdleConnsPerHost, + MaxConnsPerHost: &maxConnsPerHost, + IdleConnTimeout: &idleConnTimeout, + CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return next, nil }, + Compression: "gzip", + DisableKeepAlives: true, + HTTP2ReadIdleTimeout: idleConnTimeout, + HTTP2PingTimeout: http2PingTimeout, }, shouldError: false, }, { name: "error_round_tripper_returned", - settings: HTTPClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: false, }, ReadBufferSize: 1024, WriteBufferSize: 512, - CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return nil, errors.New("error") }, + CustomRoundTripper: func(http.RoundTripper) (http.RoundTripper, error) { return nil, errors.New("error") }, }, shouldError: true, }, @@ -159,20 +194,20 @@ func TestAllHTTPClientSettings(t *testing.T) { func TestPartialHTTPClientSettings(t *testing.T) { host := &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("testauth"): &authtest.MockClient{ResultRoundTripper: &customRoundTripper{}}, + testAuthID: &authtest.MockClient{ResultRoundTripper: &customRoundTripper{}}, }, } tests := []struct { name string - settings HTTPClientSettings + settings ClientConfig shouldError bool }{ { name: "valid_partial_settings", - settings: HTTPClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: false, }, ReadBufferSize: 1024, @@ -203,25 +238,80 @@ func TestPartialHTTPClientSettings(t *testing.T) { } func TestDefaultHTTPClientSettings(t *testing.T) { - httpClientSettings := NewDefaultHTTPClientSettings() + httpClientSettings := NewDefaultClientConfig() assert.EqualValues(t, 100, *httpClientSettings.MaxIdleConns) assert.EqualValues(t, 90*time.Second, *httpClientSettings.IdleConnTimeout) } +func TestProxyURL(t *testing.T) { + testCases := []struct { + desc string + proxyURL string + expectedURL *url.URL + err bool + }{ + { + desc: "default config", + expectedURL: nil, + }, + { + desc: "proxy is set", + proxyURL: "http://proxy.example.com:8080", + expectedURL: &url.URL{Scheme: "http", Host: "proxy.example.com:8080"}, + }, + { + desc: "proxy is invalid", + proxyURL: "://example.com", + err: true, + }, + } + for _, tC := range testCases { + t.Run(tC.desc, func(t *testing.T) { + s := NewDefaultClientConfig() + s.ProxyURL = tC.proxyURL + + tt := componenttest.NewNopTelemetrySettings() + tt.TracerProvider = nil + client, err := s.ToClient(componenttest.NewNopHost(), tt) + + if tC.err { + require.Error(t, err) + } else { + require.NoError(t, err) + } + + if err == nil { + transport := client.Transport.(*http.Transport) + require.NotNil(t, transport.Proxy) + + url, err := transport.Proxy(&http.Request{URL: &url.URL{Scheme: "http", Host: "example.com"}}) + require.NoError(t, err) + + if tC.expectedURL == nil { + assert.Nil(t, url) + } else { + require.NotNil(t, url) + assert.Equal(t, tC.expectedURL, url) + } + } + }) + } +} + func TestHTTPClientSettingsError(t *testing.T) { host := &mockHost{ ext: map[component.ID]component.Component{}, } tests := []struct { - settings HTTPClientSettings + settings ClientConfig err string }{ { err: "^failed to load TLS config: failed to load CA CertPool File: failed to load cert /doesnt/exist:", - settings: HTTPClientSettings{ + settings: ClientConfig{ Endpoint: "", - TLSSetting: configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: "/doesnt/exist", }, Insecure: false, @@ -231,10 +321,10 @@ func TestHTTPClientSettingsError(t *testing.T) { }, { err: "^failed to load TLS config: failed to load TLS cert and key: for auth via TLS, provide both certificate and key, or neither", - settings: HTTPClientSettings{ + settings: ClientConfig{ Endpoint: "", - TLSSetting: configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: configtls.ClientConfig{ + TLSSetting: configtls.Config{ CertFile: "/doesnt/exist", }, Insecure: false, @@ -244,9 +334,9 @@ func TestHTTPClientSettingsError(t *testing.T) { }, { err: "failed to resolve authenticator \"dummy\": authenticator not found", - settings: HTTPClientSettings{ + settings: ClientConfig{ Endpoint: "https://localhost:1234/v1/traces", - Auth: &configauth.Authentication{AuthenticatorID: component.NewID("dummy")}, + Auth: &configauth.Authentication{AuthenticatorID: dummyID}, }, }, } @@ -262,19 +352,19 @@ func TestHTTPClientSettingWithAuthConfig(t *testing.T) { tests := []struct { name string shouldErr bool - settings HTTPClientSettings + settings ClientConfig host component.Host }{ { name: "no_auth_extension_enabled", - settings: HTTPClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", Auth: nil, }, shouldErr: false, host: &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("mock"): &authtest.MockClient{ + mockID: &authtest.MockClient{ ResultRoundTripper: &customRoundTripper{}, }, }, @@ -282,77 +372,77 @@ func TestHTTPClientSettingWithAuthConfig(t *testing.T) { }, { name: "with_auth_configuration_and_no_extension", - settings: HTTPClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", - Auth: &configauth.Authentication{AuthenticatorID: component.NewID("dummy")}, + Auth: &configauth.Authentication{AuthenticatorID: dummyID}, }, shouldErr: true, host: &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("mock"): &authtest.MockClient{ResultRoundTripper: &customRoundTripper{}}, + mockID: &authtest.MockClient{ResultRoundTripper: &customRoundTripper{}}, }, }, }, { name: "with_auth_configuration_and_no_extension_map", - settings: HTTPClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", - Auth: &configauth.Authentication{AuthenticatorID: component.NewID("dummy")}, + Auth: &configauth.Authentication{AuthenticatorID: dummyID}, }, shouldErr: true, host: componenttest.NewNopHost(), }, { name: "with_auth_configuration_has_extension", - settings: HTTPClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", - Auth: &configauth.Authentication{AuthenticatorID: component.NewID("mock")}, + Auth: &configauth.Authentication{AuthenticatorID: mockID}, }, shouldErr: false, host: &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("mock"): &authtest.MockClient{ResultRoundTripper: &customRoundTripper{}}, + mockID: &authtest.MockClient{ResultRoundTripper: &customRoundTripper{}}, }, }, }, { name: "with_auth_configuration_has_extension_and_headers", - settings: HTTPClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", - Auth: &configauth.Authentication{AuthenticatorID: component.NewID("mock")}, + Auth: &configauth.Authentication{AuthenticatorID: mockID}, Headers: map[string]configopaque.String{"foo": "bar"}, }, shouldErr: false, host: &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("mock"): &authtest.MockClient{ResultRoundTripper: &customRoundTripper{}}, + mockID: &authtest.MockClient{ResultRoundTripper: &customRoundTripper{}}, }, }, }, { name: "with_auth_configuration_has_extension_and_compression", - settings: HTTPClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", Auth: &configauth.Authentication{AuthenticatorID: component.NewID("mock")}, - Compression: configcompression.Gzip, + Compression: configcompression.TypeGzip, }, shouldErr: false, host: &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("mock"): &authtest.MockClient{ResultRoundTripper: &customRoundTripper{}}, + mockID: &authtest.MockClient{ResultRoundTripper: &customRoundTripper{}}, }, }, }, { name: "with_auth_configuration_has_err_extension", - settings: HTTPClientSettings{ + settings: ClientConfig{ Endpoint: "localhost:1234", - Auth: &configauth.Authentication{AuthenticatorID: component.NewID("mock")}, + Auth: &configauth.Authentication{AuthenticatorID: mockID}, }, shouldErr: true, host: &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("mock"): &authtest.MockClient{ + mockID: &authtest.MockClient{ ResultRoundTripper: &customRoundTripper{}, MustError: true}, }, }, @@ -371,7 +461,7 @@ func TestHTTPClientSettingWithAuthConfig(t *testing.T) { transport := client.Transport // Compression should wrap Auth, unwrap it - if configcompression.IsCompressed(test.settings.Compression) { + if test.settings.Compression.IsCompressed() { ct, ok := transport.(*compressRoundTripper) assert.True(t, ok) assert.Equal(t, test.settings.Compression, ct.compressionType) @@ -396,15 +486,15 @@ func TestHTTPClientSettingWithAuthConfig(t *testing.T) { func TestHTTPServerSettingsError(t *testing.T) { tests := []struct { - settings HTTPServerSettings + settings ServerConfig err string }{ { err: "^failed to load TLS config: failed to load CA CertPool File: failed to load cert /doesnt/exist:", - settings: HTTPServerSettings{ + settings: ServerConfig{ Endpoint: "localhost:0", - TLSSetting: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CAFile: "/doesnt/exist", }, }, @@ -412,10 +502,10 @@ func TestHTTPServerSettingsError(t *testing.T) { }, { err: "^failed to load TLS config: failed to load TLS cert and key: for auth via TLS, provide both certificate and key, or neither", - settings: HTTPServerSettings{ + settings: ServerConfig{ Endpoint: "localhost:0", - TLSSetting: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CertFile: "/doesnt/exist", }, }, @@ -423,9 +513,9 @@ func TestHTTPServerSettingsError(t *testing.T) { }, { err: "failed to load client CA CertPool: failed to load CA /doesnt/exist:", - settings: HTTPServerSettings{ + settings: ServerConfig{ Endpoint: "localhost:0", - TLSSetting: &configtls.TLSServerSetting{ + TLSSetting: &configtls.ServerConfig{ ClientCAFile: "/doesnt/exist", }, }, @@ -442,17 +532,17 @@ func TestHTTPServerSettingsError(t *testing.T) { func TestHTTPServerWarning(t *testing.T) { tests := []struct { name string - settings HTTPServerSettings + settings ServerConfig len int }{ { - settings: HTTPServerSettings{ + settings: ServerConfig{ Endpoint: "0.0.0.0:0", }, len: 1, }, { - settings: HTTPServerSettings{ + settings: ServerConfig{ Endpoint: "127.0.0.1:0", }, len: 0, @@ -467,7 +557,7 @@ func TestHTTPServerWarning(t *testing.T) { _, err := test.settings.ToServer( componenttest.NewNopHost(), set, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { _, errWrite := fmt.Fprint(w, "test") assert.NoError(t, errWrite) })) @@ -481,29 +571,29 @@ func TestHTTPServerWarning(t *testing.T) { func TestHttpReception(t *testing.T) { tests := []struct { name string - tlsServerCreds *configtls.TLSServerSetting - tlsClientCreds *configtls.TLSClientSetting + tlsServerCreds *configtls.ServerConfig + tlsClientCreds *configtls.ClientConfig hasError bool forceHTTP1 bool }{ { name: "noTLS", tlsServerCreds: nil, - tlsClientCreds: &configtls.TLSClientSetting{ + tlsClientCreds: &configtls.ClientConfig{ Insecure: true, }, }, { name: "TLS", - tlsServerCreds: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + tlsServerCreds: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), }, }, - tlsClientCreds: &configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + tlsClientCreds: &configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -511,15 +601,15 @@ func TestHttpReception(t *testing.T) { }, { name: "TLS (HTTP/1.1)", - tlsServerCreds: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + tlsServerCreds: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), }, }, - tlsClientCreds: &configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + tlsClientCreds: &configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -528,13 +618,13 @@ func TestHttpReception(t *testing.T) { }, { name: "NoServerCertificates", - tlsServerCreds: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + tlsServerCreds: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, }, - tlsClientCreds: &configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + tlsClientCreds: &configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -543,16 +633,16 @@ func TestHttpReception(t *testing.T) { }, { name: "mTLS", - tlsServerCreds: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + tlsServerCreds: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), }, ClientCAFile: filepath.Join("testdata", "ca.crt"), }, - tlsClientCreds: &configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + tlsClientCreds: &configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "client.crt"), KeyFile: filepath.Join("testdata", "client.key"), @@ -562,16 +652,16 @@ func TestHttpReception(t *testing.T) { }, { name: "NoClientCertificate", - tlsServerCreds: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + tlsServerCreds: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), }, ClientCAFile: filepath.Join("testdata", "ca.crt"), }, - tlsClientCreds: &configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + tlsClientCreds: &configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -580,16 +670,16 @@ func TestHttpReception(t *testing.T) { }, { name: "WrongClientCA", - tlsServerCreds: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + tlsServerCreds: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), }, ClientCAFile: filepath.Join("testdata", "server.crt"), }, - tlsClientCreds: &configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + tlsClientCreds: &configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "client.crt"), KeyFile: filepath.Join("testdata", "client.key"), @@ -603,7 +693,7 @@ func TestHttpReception(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - hss := &HTTPServerSettings{ + hss := &ServerConfig{ Endpoint: "localhost:0", TLSSetting: tt.tlsServerCreds, } @@ -613,7 +703,7 @@ func TestHttpReception(t *testing.T) { s, err := hss.ToServer( componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { _, errWrite := fmt.Fprint(w, "test") assert.NoError(t, errWrite) })) @@ -623,9 +713,6 @@ func TestHttpReception(t *testing.T) { _ = s.Serve(ln) }() - // Wait for the servers to start - <-time.After(10 * time.Millisecond) - prefix := "https://" expectedProto := "HTTP/2.0" if tt.tlsClientCreds.Insecure { @@ -633,7 +720,7 @@ func TestHttpReception(t *testing.T) { expectedProto = "HTTP/1.1" } - hcs := &HTTPClientSettings{ + hcs := &ClientConfig{ Endpoint: prefix + ln.Addr().String(), TLSSetting: *tt.tlsClientCreds, } @@ -666,7 +753,7 @@ func TestHttpCors(t *testing.T) { tests := []struct { name string - *CORSSettings + *CORSConfig allowedWorks bool disallowedWorks bool @@ -680,14 +767,14 @@ func TestHttpCors(t *testing.T) { }, { name: "emptyCORS", - CORSSettings: &CORSSettings{}, + CORSConfig: &CORSConfig{}, allowedWorks: false, disallowedWorks: false, extraHeaderWorks: false, }, { name: "OriginCORS", - CORSSettings: &CORSSettings{ + CORSConfig: &CORSConfig{ AllowedOrigins: []string{"allowed-*.com"}, }, allowedWorks: true, @@ -696,7 +783,7 @@ func TestHttpCors(t *testing.T) { }, { name: "CacheableCORS", - CORSSettings: &CORSSettings{ + CORSConfig: &CORSConfig{ AllowedOrigins: []string{"allowed-*.com"}, MaxAge: 360, }, @@ -706,7 +793,7 @@ func TestHttpCors(t *testing.T) { }, { name: "HeaderCORS", - CORSSettings: &CORSSettings{ + CORSConfig: &CORSConfig{ AllowedOrigins: []string{"allowed-*.com"}, AllowedHeaders: []string{"ExtraHeader"}, }, @@ -718,9 +805,9 @@ func TestHttpCors(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - hss := &HTTPServerSettings{ + hss := &ServerConfig{ Endpoint: "localhost:0", - CORS: tt.CORSSettings, + CORS: tt.CORSConfig, } ln, err := hss.ToListener() @@ -729,7 +816,7 @@ func TestHttpCors(t *testing.T) { s, err := hss.ToServer( componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) })) require.NoError(t, err) @@ -738,25 +825,21 @@ func TestHttpCors(t *testing.T) { _ = s.Serve(ln) }() - // TODO: make starting server deterministic - // Wait for the servers to start - <-time.After(10 * time.Millisecond) - url := fmt.Sprintf("http://%s", ln.Addr().String()) expectedStatus := http.StatusNoContent - if tt.CORSSettings == nil || len(tt.AllowedOrigins) == 0 { + if tt.CORSConfig == nil || len(tt.AllowedOrigins) == 0 { expectedStatus = http.StatusOK } // Verify allowed domain gets responses that allow CORS. - verifyCorsResp(t, url, "allowed-origin.com", tt.CORSSettings, false, expectedStatus, tt.allowedWorks) + verifyCorsResp(t, url, "allowed-origin.com", tt.CORSConfig, false, expectedStatus, tt.allowedWorks) // Verify allowed domain and extra headers gets responses that allow CORS. - verifyCorsResp(t, url, "allowed-origin.com", tt.CORSSettings, true, expectedStatus, tt.extraHeaderWorks) + verifyCorsResp(t, url, "allowed-origin.com", tt.CORSConfig, true, expectedStatus, tt.extraHeaderWorks) // Verify disallowed domain gets responses that disallow CORS. - verifyCorsResp(t, url, "disallowed-origin.com", tt.CORSSettings, false, expectedStatus, tt.disallowedWorks) + verifyCorsResp(t, url, "disallowed-origin.com", tt.CORSConfig, false, expectedStatus, tt.disallowedWorks) require.NoError(t, s.Close()) }) @@ -764,36 +847,36 @@ func TestHttpCors(t *testing.T) { } func TestHttpCorsInvalidSettings(t *testing.T) { - hss := &HTTPServerSettings{ + hss := &ServerConfig{ Endpoint: "localhost:0", - CORS: &CORSSettings{AllowedHeaders: []string{"some-header"}}, + CORS: &CORSConfig{AllowedHeaders: []string{"some-header"}}, } // This effectively does not enable CORS but should also not cause an error s, err := hss.ToServer( componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) + http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})) require.NoError(t, err) require.NotNil(t, s) require.NoError(t, s.Close()) } func TestHttpCorsWithSettings(t *testing.T) { - hss := &HTTPServerSettings{ + hss := &ServerConfig{ Endpoint: "localhost:0", - CORS: &CORSSettings{ + CORS: &CORSConfig{ AllowedOrigins: []string{"*"}, }, Auth: &configauth.Authentication{ - AuthenticatorID: component.NewID("mock"), + AuthenticatorID: mockID, }, } host := &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("mock"): auth.NewServer( - auth.WithServerAuthenticate(func(ctx context.Context, headers map[string][]string) (context.Context, error) { + mockID: auth.NewServer( + auth.WithServerAuthenticate(func(ctx context.Context, _ map[string][]string) (context.Context, error) { return ctx, errors.New("Settings failed") }), ), @@ -838,7 +921,7 @@ func TestHttpServerHeaders(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - hss := &HTTPServerSettings{ + hss := &ServerConfig{ Endpoint: "localhost:0", ResponseHeaders: tt.headers, } @@ -849,7 +932,7 @@ func TestHttpServerHeaders(t *testing.T) { s, err := hss.ToServer( componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) })) require.NoError(t, err) @@ -858,10 +941,6 @@ func TestHttpServerHeaders(t *testing.T) { _ = s.Serve(ln) }() - // TODO: make starting server deterministic - // Wait for the servers to start - <-time.After(10 * time.Millisecond) - url := fmt.Sprintf("http://%s", ln.Addr().String()) // Verify allowed domain gets responses that allow CORS. @@ -872,7 +951,7 @@ func TestHttpServerHeaders(t *testing.T) { } } -func verifyCorsResp(t *testing.T, url string, origin string, set *CORSSettings, extraHeader bool, wantStatus int, wantAllowed bool) { +func verifyCorsResp(t *testing.T, url string, origin string, set *CORSConfig, extraHeader bool, wantStatus int, wantAllowed bool) { req, err := http.NewRequest(http.MethodOptions, url, nil) require.NoError(t, err, "Error creating trace OPTIONS request: %v", err) req.Header.Set("Origin", origin) @@ -929,8 +1008,8 @@ func verifyHeadersResp(t *testing.T, url string, expected map[string]configopaqu } } -func ExampleHTTPServerSettings() { - settings := HTTPServerSettings{ +func ExampleServerConfig() { + settings := ServerConfig{ Endpoint: "localhost:443", } s, err := settings.ToServer( @@ -972,9 +1051,9 @@ func TestHttpClientHeaders(t *testing.T) { })) defer server.Close() serverURL, _ := url.Parse(server.URL) - setting := HTTPClientSettings{ + setting := ClientConfig{ Endpoint: serverURL.String(), - TLSSetting: configtls.TLSClientSetting{}, + TLSSetting: configtls.ClientConfig{}, ReadBufferSize: 0, WriteBufferSize: 0, Timeout: 0, @@ -989,6 +1068,41 @@ func TestHttpClientHeaders(t *testing.T) { } } +func TestHttpClientHostHeader(t *testing.T) { + hostHeader := "th" + tt := struct { + name string + headers map[string]configopaque.String + }{ + name: "with_host_header", + headers: map[string]configopaque.String{ + "Host": configopaque.String(hostHeader), + }, + } + + t.Run(tt.name, func(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, hostHeader, r.Host) + w.WriteHeader(http.StatusOK) + })) + defer server.Close() + serverURL, _ := url.Parse(server.URL) + setting := ClientConfig{ + Endpoint: serverURL.String(), + TLSSetting: configtls.TLSClientSetting{}, + ReadBufferSize: 0, + WriteBufferSize: 0, + Timeout: 0, + Headers: tt.headers, + } + client, _ := setting.ToClient(componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) + req, err := http.NewRequest(http.MethodGet, setting.Endpoint, nil) + assert.NoError(t, err) + _, err = client.Do(req) + assert.NoError(t, err) + }) +} + func TestContextWithClient(t *testing.T) { testCases := []struct { desc string @@ -1053,17 +1167,17 @@ func TestContextWithClient(t *testing.T) { func TestServerAuth(t *testing.T) { // prepare authCalled := false - hss := HTTPServerSettings{ + hss := ServerConfig{ Endpoint: "localhost:0", Auth: &configauth.Authentication{ - AuthenticatorID: component.NewID("mock"), + AuthenticatorID: mockID, }, } host := &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("mock"): auth.NewServer( - auth.WithServerAuthenticate(func(ctx context.Context, headers map[string][]string) (context.Context, error) { + mockID: auth.NewServer( + auth.WithServerAuthenticate(func(ctx context.Context, _ map[string][]string) (context.Context, error) { authCalled = true return ctx, nil }), @@ -1072,7 +1186,7 @@ func TestServerAuth(t *testing.T) { } handlerCalled := false - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.HandlerFunc(func(http.ResponseWriter, *http.Request) { handlerCalled = true }) @@ -1088,9 +1202,9 @@ func TestServerAuth(t *testing.T) { } func TestInvalidServerAuth(t *testing.T) { - hss := HTTPServerSettings{ + hss := ServerConfig{ Auth: &configauth.Authentication{ - AuthenticatorID: component.NewID("non-existing"), + AuthenticatorID: nonExistingID, }, } @@ -1101,23 +1215,23 @@ func TestInvalidServerAuth(t *testing.T) { func TestFailedServerAuth(t *testing.T) { // prepare - hss := HTTPServerSettings{ + hss := ServerConfig{ Endpoint: "localhost:0", Auth: &configauth.Authentication{ - AuthenticatorID: component.NewID("mock"), + AuthenticatorID: mockID, }, } host := &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("mock"): auth.NewServer( - auth.WithServerAuthenticate(func(ctx context.Context, headers map[string][]string) (context.Context, error) { + mockID: auth.NewServer( + auth.WithServerAuthenticate(func(ctx context.Context, _ map[string][]string) (context.Context, error) { return ctx, errors.New("Settings failed") }), ), }, } - srv, err := hss.ToServer(host, componenttest.NewNopTelemetrySettings(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) + srv, err := hss.ToServer(host, componenttest.NewNopTelemetrySettings(), http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})) require.NoError(t, err) // test @@ -1131,20 +1245,19 @@ func TestFailedServerAuth(t *testing.T) { func TestServerWithErrorHandler(t *testing.T) { // prepare - hss := HTTPServerSettings{ + hss := ServerConfig{ Endpoint: "localhost:0", } - eh := func(w http.ResponseWriter, r *http.Request, errorMsg string, statusCode int) { + eh := func(w http.ResponseWriter, _ *http.Request, _ string, statusCode int) { assert.Equal(t, statusCode, http.StatusBadRequest) // custom error handler changes returned status code http.Error(w, "invalid request", http.StatusInternalServerError) - } srv, err := hss.ToServer( componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}), + http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}), WithErrorHandler(eh), ) require.NoError(t, err) @@ -1162,7 +1275,7 @@ func TestServerWithErrorHandler(t *testing.T) { func TestServerWithDecoder(t *testing.T) { // prepare - hss := HTTPServerSettings{ + hss := ServerConfig{ Endpoint: "localhost:0", } decoder := func(body io.ReadCloser) (io.ReadCloser, error) { @@ -1172,7 +1285,7 @@ func TestServerWithDecoder(t *testing.T) { srv, err := hss.ToServer( componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}), + http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}), WithDecoder("something-else", decoder), ) require.NoError(t, err) @@ -1226,21 +1339,21 @@ func BenchmarkHttpRequest(b *testing.B) { }, } - tlsServerCreds := &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + tlsServerCreds := &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), }, } - tlsClientCreds := &configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + tlsClientCreds := &configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", } - hss := &HTTPServerSettings{ + hss := &ServerConfig{ Endpoint: "localhost:0", TLSSetting: tlsServerCreds, } @@ -1248,7 +1361,7 @@ func BenchmarkHttpRequest(b *testing.B) { s, err := hss.ToServer( componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { _, errWrite := fmt.Fprint(w, "test") require.NoError(b, errWrite) })) @@ -1263,11 +1376,8 @@ func BenchmarkHttpRequest(b *testing.B) { _ = s.Close() }() - // Wait for the servers to start - <-time.After(10 * time.Millisecond) - for _, bb := range tests { - hcs := &HTTPClientSettings{ + hcs := &ClientConfig{ Endpoint: "https://" + ln.Addr().String(), TLSSetting: *tlsClientCreds, } diff --git a/config/confighttp/go.mod b/config/confighttp/go.mod index 11924deaae6..48dd57e2806 100644 --- a/config/confighttp/go.mod +++ b/config/confighttp/go.mod @@ -1,54 +1,65 @@ module go.opentelemetry.io/collector/config/confighttp -go 1.20 +go 1.21 require ( github.com/golang/snappy v0.0.4 - github.com/klauspost/compress v1.17.0 - github.com/rs/cors v1.10.0 + github.com/klauspost/compress v1.17.7 + github.com/rs/cors v1.10.1 github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/configauth v0.85.0 - go.opentelemetry.io/collector/config/configcompression v0.85.0 - go.opentelemetry.io/collector/config/configopaque v0.85.0 - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 - go.opentelemetry.io/collector/config/configtls v0.85.0 - go.opentelemetry.io/collector/config/internal v0.85.0 - go.opentelemetry.io/collector/extension/auth v0.85.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 - go.opentelemetry.io/otel v1.18.0 - go.uber.org/zap v1.26.0 - golang.org/x/net v0.15.0 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/configauth v0.96.0 + go.opentelemetry.io/collector/config/configcompression v0.96.0 + go.opentelemetry.io/collector/config/configopaque v1.3.0 + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 + go.opentelemetry.io/collector/config/configtls v0.96.0 + go.opentelemetry.io/collector/config/internal v0.96.0 + go.opentelemetry.io/collector/extension/auth v0.96.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 + go.opentelemetry.io/otel v1.24.0 + go.uber.org/goleak v1.3.0 + go.uber.org/zap v1.27.0 + golang.org/x/net v0.21.0 ) require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/felixge/httpsnoop v1.0.3 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/collector/confmap v0.85.0 // indirect - go.opentelemetry.io/collector/extension v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector/confmap v0.96.0 // indirect + go.opentelemetry.io/collector/extension v0.96.0 // indirect + go.opentelemetry.io/collector/featuregate v1.3.0 // indirect + go.opentelemetry.io/collector/pdata v1.3.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -58,8 +69,6 @@ replace go.opentelemetry.io/collector/config/configauth => ../configauth replace go.opentelemetry.io/collector/config/configcompression => ../configcompression -replace go.opentelemetry.io/collector/config/confignet => ../confignet - replace go.opentelemetry.io/collector/config/configopaque => ../configopaque replace go.opentelemetry.io/collector/config/configtls => ../configtls @@ -74,24 +83,10 @@ replace go.opentelemetry.io/collector/extension/auth => ../../extension/auth replace go.opentelemetry.io/collector/confmap => ../../confmap -replace go.opentelemetry.io/collector/processor => ../../processor - -replace go.opentelemetry.io/collector/exporter => ../../exporter - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension - -replace go.opentelemetry.io/collector/receiver => ../../receiver - -replace go.opentelemetry.io/collector/connector => ../../connector - replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata replace go.opentelemetry.io/collector/component => ../../component -replace go.opentelemetry.io/collector/semconv => ../../semconv - replace go.opentelemetry.io/collector/consumer => ../../consumer - -replace go.opentelemetry.io/collector/service => ../../service diff --git a/config/confighttp/go.sum b/config/confighttp/go.sum index 2d630dc6561..6d440490f4c 100644 --- a/config/confighttp/go.sum +++ b/config/confighttp/go.sum @@ -1,14 +1,20 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= @@ -17,50 +23,72 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rs/cors v1.10.0 h1:62NOS1h+r8p1mW6FM0FSB0exioXLhd/sh15KpjWBZ+8= -github.com/rs/cors v1.10.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -70,21 +98,20 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -93,15 +120,16 @@ 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-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= 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/config/confighttp/package_test.go b/config/confighttp/package_test.go new file mode 100644 index 00000000000..30797439baf --- /dev/null +++ b/config/confighttp/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package confighttp + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/config/confignet/README.md b/config/confignet/README.md index 579564cbff4..cd8150e6303 100644 --- a/config/confignet/README.md +++ b/config/confignet/README.md @@ -13,6 +13,7 @@ leverage network configuration to set connection and transport information. - `transport`: Known protocols are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only), "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4" (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and "unixpacket". +- `dialer_timeout`: DialerTimeout is the maximum amount of time a dial will wait for a connect to complete. The default is no timeout. Note that for TCP receivers only the `endpoint` configuration setting is required. diff --git a/config/confignet/confignet.go b/config/confignet/confignet.go index 6695b6035b8..09f7ec24ff6 100644 --- a/config/confignet/confignet.go +++ b/config/confignet/confignet.go @@ -4,11 +4,20 @@ package confignet // import "go.opentelemetry.io/collector/config/confignet" import ( + "context" "net" + "time" ) -// NetAddr represents a network endpoint address. -type NetAddr struct { +// DialerConfig contains options for connecting to an address. +type DialerConfig struct { + // Timeout is the maximum amount of time a dial will wait for + // a connect to complete. The default is no timeout. + Timeout time.Duration `mapstructure:"timeout"` +} + +// AddrConfig represents a network endpoint address. +type AddrConfig struct { // Endpoint configures the address for this network connection. // For TCP and UDP networks, the address has the form "host:port". The host must be a literal IP address, // or a host name that can be resolved to IP addresses. The port must be a literal port number or a service name. @@ -19,34 +28,44 @@ type NetAddr struct { // Transport to use. Known protocols are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only), "udp", "udp4" (IPv4-only), // "udp6" (IPv6-only), "ip", "ip4" (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and "unixpacket". Transport string `mapstructure:"transport"` + + // DialerConfig contains options for connecting to an address. + DialerConfig DialerConfig `mapstructure:"dialer"` } -// Dial equivalent with net.Dial for this address. -func (na *NetAddr) Dial() (net.Conn, error) { - return net.Dial(na.Transport, na.Endpoint) +// Dial equivalent with net.Dialer's DialContext for this address. +func (na *AddrConfig) Dial(ctx context.Context) (net.Conn, error) { + d := net.Dialer{Timeout: na.DialerConfig.Timeout} + return d.DialContext(ctx, na.Transport, na.Endpoint) } -// Listen equivalent with net.Listen for this address. -func (na *NetAddr) Listen() (net.Listener, error) { - return net.Listen(na.Transport, na.Endpoint) +// Listen equivalent with net.ListenConfig's Listen for this address. +func (na *AddrConfig) Listen(ctx context.Context) (net.Listener, error) { + lc := net.ListenConfig{} + return lc.Listen(ctx, na.Transport, na.Endpoint) } -// TCPAddr represents a TCP endpoint address. -type TCPAddr struct { +// TCPAddrConfig represents a TCP endpoint address. +type TCPAddrConfig struct { // Endpoint configures the address for this network connection. // The address has the form "host:port". The host must be a literal IP address, or a host name that can be // resolved to IP addresses. The port must be a literal port number or a service name. // If the host is a literal IPv6 address it must be enclosed in square brackets, as in "[2001:db8::1]:80" or // "[fe80::1%zone]:80". The zone specifies the scope of the literal IPv6 address as defined in RFC 4007. Endpoint string `mapstructure:"endpoint"` + + // DialerConfig contains options for connecting to an address. + DialerConfig DialerConfig `mapstructure:"dialer"` } -// Dial equivalent with net.Dial for this address. -func (na *TCPAddr) Dial() (net.Conn, error) { - return net.Dial("tcp", na.Endpoint) +// Dial equivalent with net.Dialer's DialContext for this address. +func (na *TCPAddrConfig) Dial(ctx context.Context) (net.Conn, error) { + d := net.Dialer{Timeout: na.DialerConfig.Timeout} + return d.DialContext(ctx, "tcp", na.Endpoint) } -// Listen equivalent with net.Listen for this address. -func (na *TCPAddr) Listen() (net.Listener, error) { - return net.Listen("tcp", na.Endpoint) +// Listen equivalent with net.ListenConfig's Listen for this address. +func (na *TCPAddrConfig) Listen(ctx context.Context) (net.Listener, error) { + lc := net.ListenConfig{} + return lc.Listen(ctx, "tcp", na.Endpoint) } diff --git a/config/confignet/confignet_test.go b/config/confignet/confignet_test.go index 7ba5e442ed5..f3481609562 100644 --- a/config/confignet/confignet_test.go +++ b/config/confignet/confignet_test.go @@ -4,18 +4,56 @@ package confignet import ( + "context" + "errors" "net" "testing" + "time" "github.com/stretchr/testify/assert" ) -func TestNetAddr(t *testing.T) { - nas := &NetAddr{ +func TestAddrConfigTimeout(t *testing.T) { + nac := &AddrConfig{ Endpoint: "localhost:0", Transport: "tcp", + DialerConfig: DialerConfig{ + Timeout: -1 * time.Second, + }, } - ln, err := nas.Listen() + _, err := nac.Dial(context.Background()) + assert.Error(t, err) + var netErr net.Error + if errors.As(err, &netErr) { + assert.True(t, netErr.Timeout()) + } else { + assert.Fail(t, "error should be a net.Error") + } +} + +func TestTCPAddrConfigTimeout(t *testing.T) { + nac := &TCPAddrConfig{ + Endpoint: "localhost:0", + DialerConfig: DialerConfig{ + Timeout: -1 * time.Second, + }, + } + _, err := nac.Dial(context.Background()) + assert.Error(t, err) + var netErr net.Error + if errors.As(err, &netErr) { + assert.True(t, netErr.Timeout()) + } else { + assert.Fail(t, "error should be a net.Error") + } +} + +func TestAddrConfig(t *testing.T) { + nas := &AddrConfig{ + Endpoint: "localhost:0", + Transport: "tcp", + } + ln, err := nas.Listen(context.Background()) assert.NoError(t, err) done := make(chan bool, 1) @@ -31,12 +69,12 @@ func TestNetAddr(t *testing.T) { done <- true }() - nac := &NetAddr{ + nac := &AddrConfig{ Endpoint: ln.Addr().String(), Transport: "tcp", } var conn net.Conn - conn, err = nac.Dial() + conn, err = nac.Dial(context.Background()) assert.NoError(t, err) _, err = conn.Write([]byte("test")) assert.NoError(t, err) @@ -45,11 +83,11 @@ func TestNetAddr(t *testing.T) { assert.NoError(t, ln.Close()) } -func TestTcpAddr(t *testing.T) { - nas := &TCPAddr{ +func TestTCPAddrConfig(t *testing.T) { + nas := &TCPAddrConfig{ Endpoint: "localhost:0", } - ln, err := nas.Listen() + ln, err := nas.Listen(context.Background()) assert.NoError(t, err) done := make(chan bool, 1) @@ -65,11 +103,11 @@ func TestTcpAddr(t *testing.T) { done <- true }() - nac := &TCPAddr{ + nac := &TCPAddrConfig{ Endpoint: ln.Addr().String(), } var conn net.Conn - conn, err = nac.Dial() + conn, err = nac.Dial(context.Background()) assert.NoError(t, err) _, err = conn.Write([]byte("test")) assert.NoError(t, err) diff --git a/config/confignet/go.mod b/config/confignet/go.mod index 1b4d3e231a1..cbd4d70267e 100644 --- a/config/confignet/go.mod +++ b/config/confignet/go.mod @@ -1,8 +1,11 @@ module go.opentelemetry.io/collector/config/confignet -go 1.20 +go 1.21 -require github.com/stretchr/testify v1.8.4 +require ( + github.com/stretchr/testify v1.8.4 + go.uber.org/goleak v1.3.0 +) require ( github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/config/confignet/go.sum b/config/confignet/go.sum index 3ee4af40e76..b4eccab6a53 100644 --- a/config/confignet/go.sum +++ b/config/confignet/go.sum @@ -16,6 +16,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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/confignet/package_test.go b/config/confignet/package_test.go new file mode 100644 index 00000000000..5107616e21c --- /dev/null +++ b/config/confignet/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package confignet + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/config/configopaque/doc.go b/config/configopaque/doc.go index 7153ca1eb79..dffb3eba84a 100644 --- a/config/configopaque/doc.go +++ b/config/configopaque/doc.go @@ -1,10 +1,21 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -// Package configopaque implements String type alias to mask sensitive information. +// Package configopaque implements a String type alias to mask sensitive information. // Use configopaque.String on the type of sensitive fields, to mask the // opaque string as `[REDACTED]`. // -// This ensure that no sensitive information is leaked when printing the +// This ensures that no sensitive information is leaked in logs or when printing the // full Collector configurations. +// +// The only way to view the value stored in a configopaque.String is to first convert +// it to a string by casting with the builtin `string` function. +// +// To achieve this, configopaque.String implements standard library interfaces +// like fmt.Stringer, encoding.TextMarshaler and others to ensure that the +// underlying value is masked when printed or serialized. +// +// If new interfaces that would leak opaque values are added to the standard library +// or become widely used in the Go ecosystem, these will eventually be implemented +// by configopaque.String as well. This is not considered a breaking change. package configopaque // import "go.opentelemetry.io/collector/config/configopaque" diff --git a/config/configopaque/go.mod b/config/configopaque/go.mod index c5242b315ae..c2c9a683f4f 100644 --- a/config/configopaque/go.mod +++ b/config/configopaque/go.mod @@ -1,16 +1,27 @@ module go.opentelemetry.io/collector/config/configopaque -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 + go.opentelemetry.io/collector/confmap v0.96.0 + go.uber.org/goleak v1.3.0 gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/kr/pretty v0.3.1 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect + go.uber.org/multierr v1.11.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect ) + +replace go.opentelemetry.io/collector/confmap => ../../confmap diff --git a/config/configopaque/go.sum b/config/configopaque/go.sum index 3ee4af40e76..ea17c4438d6 100644 --- a/config/configopaque/go.sum +++ b/config/configopaque/go.sum @@ -1,6 +1,14 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -8,6 +16,10 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -16,6 +28,10 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 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/configopaque/opaque.go b/config/configopaque/opaque.go index 3e4505d246f..b1712a212f7 100644 --- a/config/configopaque/opaque.go +++ b/config/configopaque/opaque.go @@ -4,17 +4,33 @@ package configopaque // import "go.opentelemetry.io/collector/config/configopaque" import ( - "encoding" + "fmt" ) -// String alias that is marshaled in an opaque way. +// String alias that is marshaled and printed in an opaque way. +// To recover the original value, cast it to a string. type String string const maskedString = "[REDACTED]" -var _ encoding.TextMarshaler = String("") - // MarshalText marshals the string as `[REDACTED]`. func (s String) MarshalText() ([]byte, error) { return []byte(maskedString), nil } + +// String formats the string as `[REDACTED]`. +// This is used for the %s and %q verbs. +func (s String) String() string { + return maskedString +} + +// GoString formats the string as `[REDACTED]`. +// This is used for the %#v verb. +func (s String) GoString() string { + return fmt.Sprintf("%#v", maskedString) +} + +// MarshalBinary marshals the string `[REDACTED]` as []byte. +func (s String) MarshalBinary() (text []byte, err error) { + return []byte(maskedString), nil +} diff --git a/config/configopaque/opaque_test.go b/config/configopaque/opaque_test.go index 50d2f3ea0f1..820ae995593 100644 --- a/config/configopaque/opaque_test.go +++ b/config/configopaque/opaque_test.go @@ -4,17 +4,99 @@ package configopaque // import "go.opentelemetry.io/collector/config/configopaque" import ( + "encoding" + "encoding/json" + "fmt" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/confmap" ) +var _ encoding.TextMarshaler = String("") + +var _ fmt.Stringer = String("") + +var _ fmt.GoStringer = String("") + +var _ encoding.BinaryMarshaler = String("") + func TestStringMarshalText(t *testing.T) { examples := []String{"opaque", "s", "veryveryveryveryveryveryveryveryveryverylong"} for _, example := range examples { opaque, err := example.MarshalText() require.NoError(t, err) - assert.Equal(t, "[REDACTED]", string(opaque)) + assert.Equal(t, maskedString, string(opaque)) + } +} + +type TestStruct struct { + Opaque String `json:"opaque" yaml:"opaque"` + Plain string `json:"plain" yaml:"plain"` +} + +var example = TestStruct{ + Opaque: "opaque", + Plain: "plain", +} + +func TestStringJSON(t *testing.T) { + bytes, err := json.Marshal(example) + require.NoError(t, err) + assert.Equal(t, `{"opaque":"[REDACTED]","plain":"plain"}`, string(bytes)) +} + +func TestConfMapMarshalConfigOpaque(t *testing.T) { + conf := confmap.New() + assert.NoError(t, conf.Marshal(example)) + assert.Equal(t, "[REDACTED]", conf.Get("opaque")) + assert.Equal(t, "plain", conf.Get("plain")) +} + +func TestStringFmt(t *testing.T) { + examples := []String{"opaque", "s", "veryveryveryveryveryveryveryveryveryverylong"} + verbs := []string{"%s", "%q", "%v", "%#v", "%+v", "%x"} + for _, example := range examples { + for _, verb := range verbs { + t.Run(fmt.Sprintf("%s/%s", string(example), verb), func(t *testing.T) { + assert.Equal(t, + fmt.Sprintf(verb, maskedString), + fmt.Sprintf(verb, example), + ) + }) + } + + for _, verb := range verbs { + t.Run(fmt.Sprintf("string(%s)/%s", string(example), verb), func(t *testing.T) { + // converting to a string allows to output as an unredacted string still: + var expected string + switch verb { + case "%s", "%v", "%+v": + expected = string(example) + case "%q", "%#v": + expected = "\"" + string(example) + "\"" + case "%x": + expected = fmt.Sprintf("%x", []byte(example)) + default: + t.Errorf("unexpected verb %q", verb) + } + + assert.Equal(t, + expected, + fmt.Sprintf(verb, string(example)), + ) + }) + } + } +} + +func TestStringMarshalBinary(t *testing.T) { + examples := []String{"opaque", "s", "veryveryveryveryveryveryveryveryveryverylong"} + for _, example := range examples { + opaque, err := example.MarshalBinary() + require.NoError(t, err) + assert.Equal(t, []byte("[REDACTED]"), opaque) } } diff --git a/config/configopaque/package_test.go b/config/configopaque/package_test.go new file mode 100644 index 00000000000..cf4a05faa12 --- /dev/null +++ b/config/configopaque/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package configopaque + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/config/configretry/Makefile b/config/configretry/Makefile new file mode 100644 index 00000000000..ded7a36092d --- /dev/null +++ b/config/configretry/Makefile @@ -0,0 +1 @@ +include ../../Makefile.Common diff --git a/config/configretry/backoff.go b/config/configretry/backoff.go new file mode 100644 index 00000000000..1fc3f8c5852 --- /dev/null +++ b/config/configretry/backoff.go @@ -0,0 +1,74 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package configretry // import "go.opentelemetry.io/collector/config/configretry" + +import ( + "errors" + "time" + + "github.com/cenkalti/backoff/v4" +) + +// NewDefaultBackOffConfig returns the default settings for RetryConfig. +func NewDefaultBackOffConfig() BackOffConfig { + return BackOffConfig{ + Enabled: true, + InitialInterval: 5 * time.Second, + RandomizationFactor: backoff.DefaultRandomizationFactor, + Multiplier: backoff.DefaultMultiplier, + MaxInterval: 30 * time.Second, + MaxElapsedTime: 5 * time.Minute, + } +} + +// BackOffConfig defines configuration for retrying batches in case of export failure. +// The current supported strategy is exponential backoff. +type BackOffConfig struct { + // Enabled indicates whether to not retry sending batches in case of export failure. + Enabled bool `mapstructure:"enabled"` + // InitialInterval the time to wait after the first failure before retrying. + InitialInterval time.Duration `mapstructure:"initial_interval"` + // RandomizationFactor is a random factor used to calculate next backoffs + // Randomized interval = RetryInterval * (1 ± RandomizationFactor) + RandomizationFactor float64 `mapstructure:"randomization_factor"` + // Multiplier is the value multiplied by the backoff interval bounds + Multiplier float64 `mapstructure:"multiplier"` + // MaxInterval is the upper bound on backoff interval. Once this value is reached the delay between + // consecutive retries will always be `MaxInterval`. + MaxInterval time.Duration `mapstructure:"max_interval"` + // MaxElapsedTime is the maximum amount of time (including retries) spent trying to send a request/batch. + // Once this value is reached, the data is discarded. If set to 0, the retries are never stopped. + MaxElapsedTime time.Duration `mapstructure:"max_elapsed_time"` +} + +func (bs *BackOffConfig) Validate() error { + if !bs.Enabled { + return nil + } + if bs.InitialInterval < 0 { + return errors.New("'initial_interval' must be non-negative") + } + if bs.RandomizationFactor < 0 || bs.RandomizationFactor > 1 { + return errors.New("'randomization_factor' must be within [0, 1]") + } + if bs.Multiplier < 0 { + return errors.New("'multiplier' must be non-negative") + } + if bs.MaxInterval < 0 { + return errors.New("'max_interval' must be non-negative") + } + if bs.MaxElapsedTime < 0 { + return errors.New("'max_elapsed_time' must be non-negative") + } + if bs.MaxElapsedTime > 0 { + if bs.MaxElapsedTime < bs.InitialInterval { + return errors.New("'max_elapsed_time' must not be less than 'initial_interval'") + } + if bs.MaxElapsedTime < bs.MaxInterval { + return errors.New("'max_elapsed_time' must not be less than 'max_interval'") + } + + } + return nil +} diff --git a/config/configretry/backoff_test.go b/config/configretry/backoff_test.go new file mode 100644 index 00000000000..a0adb3ceaf3 --- /dev/null +++ b/config/configretry/backoff_test.go @@ -0,0 +1,93 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package configretry + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestNewDefaultBackOffSettings(t *testing.T) { + cfg := NewDefaultBackOffConfig() + assert.NoError(t, cfg.Validate()) + assert.Equal(t, + BackOffConfig{ + Enabled: true, + InitialInterval: 5 * time.Second, + RandomizationFactor: 0.5, + Multiplier: 1.5, + MaxInterval: 30 * time.Second, + MaxElapsedTime: 5 * time.Minute, + }, cfg) +} + +func TestInvalidInitialInterval(t *testing.T) { + cfg := NewDefaultBackOffConfig() + assert.NoError(t, cfg.Validate()) + cfg.InitialInterval = -1 + assert.Error(t, cfg.Validate()) +} + +func TestInvalidRandomizationFactor(t *testing.T) { + cfg := NewDefaultBackOffConfig() + assert.NoError(t, cfg.Validate()) + cfg.RandomizationFactor = -1 + assert.Error(t, cfg.Validate()) + cfg.RandomizationFactor = 2 + assert.Error(t, cfg.Validate()) +} + +func TestInvalidMultiplier(t *testing.T) { + cfg := NewDefaultBackOffConfig() + assert.NoError(t, cfg.Validate()) + cfg.Multiplier = -1 + assert.Error(t, cfg.Validate()) +} + +func TestZeroMultiplierIsValid(t *testing.T) { + cfg := NewDefaultBackOffConfig() + assert.NoError(t, cfg.Validate()) + cfg.Multiplier = 0 + assert.NoError(t, cfg.Validate()) +} + +func TestInvalidMaxInterval(t *testing.T) { + cfg := NewDefaultBackOffConfig() + assert.NoError(t, cfg.Validate()) + cfg.MaxInterval = -1 + assert.Error(t, cfg.Validate()) +} + +func TestInvalidMaxElapsedTime(t *testing.T) { + cfg := NewDefaultBackOffConfig() + assert.NoError(t, cfg.Validate()) + cfg.MaxElapsedTime = -1 + assert.Error(t, cfg.Validate()) + cfg.MaxElapsedTime = 60 + // MaxElapsedTime is 60, InitialInterval is 5s, so it should be invalid + assert.Error(t, cfg.Validate()) + cfg.InitialInterval = 0 + // MaxElapsedTime is 60, MaxInterval is 30s, so it should be invalid + assert.Error(t, cfg.Validate()) + cfg.MaxInterval = 0 + assert.NoError(t, cfg.Validate()) + cfg.InitialInterval = 50 + // MaxElapsedTime is 0, so it should be valid + cfg.MaxElapsedTime = 0 + assert.NoError(t, cfg.Validate()) +} + +func TestDisabledWithInvalidValues(t *testing.T) { + cfg := BackOffConfig{ + Enabled: false, + InitialInterval: -1, + RandomizationFactor: -1, + Multiplier: 0, + MaxInterval: -1, + MaxElapsedTime: -1, + } + assert.NoError(t, cfg.Validate()) +} diff --git a/config/configretry/go.mod b/config/configretry/go.mod new file mode 100644 index 00000000000..aeeab554eb9 --- /dev/null +++ b/config/configretry/go.mod @@ -0,0 +1,18 @@ +module go.opentelemetry.io/collector/config/configretry + +go 1.21 + +require ( + github.com/cenkalti/backoff/v4 v4.2.1 + github.com/stretchr/testify v1.8.4 + go.uber.org/goleak v1.3.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/config/configretry/go.sum b/config/configretry/go.sum new file mode 100644 index 00000000000..33516e2c95b --- /dev/null +++ b/config/configretry/go.sum @@ -0,0 +1,27 @@ +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +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= +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/config/configretry/package_test.go b/config/configretry/package_test.go new file mode 100644 index 00000000000..56873ecaa43 --- /dev/null +++ b/config/configretry/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package configretry + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/config/configtelemetry/configtelemetry.go b/config/configtelemetry/configtelemetry.go index 0ec660bd77c..b8c0967c905 100644 --- a/config/configtelemetry/configtelemetry.go +++ b/config/configtelemetry/configtelemetry.go @@ -4,7 +4,6 @@ package configtelemetry // import "go.opentelemetry.io/collector/config/configtelemetry" import ( - "encoding" "errors" "fmt" "strings" @@ -30,9 +29,6 @@ const ( // that every component should generate. type Level int32 -var _ encoding.TextMarshaler = (*Level)(nil) -var _ encoding.TextUnmarshaler = (*Level)(nil) - func (l Level) String() string { switch l { case LevelNone: diff --git a/config/configtelemetry/configtelemetry_test.go b/config/configtelemetry/configtelemetry_test.go index 409a60cd6e1..27236bbe32b 100644 --- a/config/configtelemetry/configtelemetry_test.go +++ b/config/configtelemetry/configtelemetry_test.go @@ -4,11 +4,15 @@ package configtelemetry import ( + "encoding" "testing" "github.com/stretchr/testify/assert" ) +var _ encoding.TextMarshaler = (*Level)(nil) +var _ encoding.TextUnmarshaler = (*Level)(nil) + func TestUnmarshalText(t *testing.T) { tests := []struct { str []string diff --git a/config/configtelemetry/go.mod b/config/configtelemetry/go.mod index e1f8119ba7a..32161410cfd 100644 --- a/config/configtelemetry/go.mod +++ b/config/configtelemetry/go.mod @@ -1,8 +1,11 @@ module go.opentelemetry.io/collector/config/configtelemetry -go 1.20 +go 1.21 -require github.com/stretchr/testify v1.8.4 +require ( + github.com/stretchr/testify v1.8.4 + go.uber.org/goleak v1.3.0 +) require ( github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/config/configtelemetry/go.sum b/config/configtelemetry/go.sum index 3ee4af40e76..b4eccab6a53 100644 --- a/config/configtelemetry/go.sum +++ b/config/configtelemetry/go.sum @@ -16,6 +16,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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/configtelemetry/package_test.go b/config/configtelemetry/package_test.go new file mode 100644 index 00000000000..aa3d005b05c --- /dev/null +++ b/config/configtelemetry/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package configtelemetry + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/config/configtls/README.md b/config/configtls/README.md index f8901de94fa..aecfc284b41 100644 --- a/config/configtls/README.md +++ b/config/configtls/README.md @@ -31,6 +31,11 @@ A certificate authority may also need to be defined: system root CA. Should only be used if `insecure` is set to false. - `ca_pem`: Alternative to `ca_file`. Provide the CA cert contents as a string instead of a filepath. +You can also combine defining a certificate authority with the system certificate authorities. + +- `include_system_ca_certs_pool` (default = false): whether to load the system certificate authorities pool + alongside the certificate authority. + Additionally you can configure TLS to be enabled but skip verifying the server's certificate chain. This cannot be combined with `insecure` since `insecure` won't use TLS at all. @@ -48,6 +53,17 @@ __IMPORTANT__: TLS 1.0 and 1.1 are deprecated due to known vulnerabilities and s - `max_version` (default = "" handled by [crypto/tls](https://github.com/golang/go/blob/ed9db1d36ad6ef61095d5941ad9ee6da7ab6d05a/src/crypto/tls/common.go#L700) - currently TLS 1.3): Maximum acceptable TLS version. - options: ["1.0", "1.1", "1.2", "1.3"] +Explicit cipher suites can be set. If left blank, a safe default list is used. See https://go.dev/src/crypto/tls/cipher_suites.go for a list of supported cipher suites. +- `cipher_suites`: (default = []): List of cipher suites to use. + +Example: +``` + cipher_suites: + - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 +``` + Additionally certificates may be reloaded by setting the below configuration. - `reload_interval` (optional) : ReloadInterval specifies the duration after which the certificate will be reloaded. diff --git a/config/configtls/configtls.go b/config/configtls/configtls.go index ca15f12d08b..bdd80cb56cb 100644 --- a/config/configtls/configtls.go +++ b/config/configtls/configtls.go @@ -6,6 +6,7 @@ package configtls // import "go.opentelemetry.io/collector/config/configtls" import ( "crypto/tls" "crypto/x509" + "errors" "fmt" "os" "path/filepath" @@ -22,10 +23,16 @@ const defaultMinTLSVersion = tls.VersionTLS12 // Uses the default MaxVersion from "crypto/tls" which is the maximum supported version const defaultMaxTLSVersion = 0 +var systemCertPool = x509.SystemCertPool + // TLSSetting exposes the common client and server TLS configurations. +// Deprecated: [v0.96.0] Use Config instead. +type TLSSetting = Config + +// Config exposes the common client and server TLS configurations. // Note: Since there isn't anything specific to a server connection. Components -// with server connections should use TLSSetting. -type TLSSetting struct { +// with server connections should use Config. +type Config struct { // Path to the CA cert. For a client this verifies the server certificate. // For a server this verifies client certificates. If empty uses system root CA. // (optional) @@ -34,6 +41,10 @@ type TLSSetting struct { // In memory PEM encoded cert. (optional) CAPem configopaque.String `mapstructure:"ca_pem"` + // If true, load system CA certificates pool in addition to the certificates + // configured in this struct. + IncludeSystemCACertsPool bool `mapstructure:"include_system_ca_certs_pool"` + // Path to the TLS cert to use for TLS required connections. (optional) CertFile string `mapstructure:"cert_file"` @@ -54,15 +65,25 @@ type TLSSetting struct { // If not set, refer to crypto/tls for defaults. (optional) MaxVersion string `mapstructure:"max_version"` + // CipherSuites is a list of TLS cipher suites that the TLS transport can use. + // If left blank, a safe default list is used. + // See https://go.dev/src/crypto/tls/cipher_suites.go for a list of supported cipher suites. + CipherSuites []string `mapstructure:"cipher_suites"` + // 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"` } -// TLSClientSetting contains TLS configurations that are specific to client +// TSLClientSetting contains TLS configurations that are specific to client +// connections in addition to the common configurations. +// Deprecated: [v0.96.0] Use ClientConfig instead. +type TLSClientSetting = ClientConfig + +// ClientConfig contains TLS configurations that are specific to client // connections in addition to the common configurations. This should be used by // components configuring TLS client connections. -type TLSClientSetting struct { +type ClientConfig struct { // squash ensures fields are correctly decoded in embedded struct. TLSSetting `mapstructure:",squash"` @@ -84,9 +105,14 @@ type TLSClientSetting struct { } // TLSServerSetting contains TLS configurations that are specific to server +// connections in addition to the common configurations. +// Deprecated: [v0.96.0] Use ServerConfig instead. +type TLSServerSetting = ServerConfig + +// ServerConfig contains TLS configurations that are specific to server // connections in addition to the common configurations. This should be used by // components configuring TLS server connections. -type TLSServerSetting struct { +type ServerConfig struct { // squash ensures fields are correctly decoded in embedded struct. TLSSetting `mapstructure:",squash"` @@ -109,10 +135,10 @@ type certReloader struct { nextReload time.Time cert *tls.Certificate lock sync.RWMutex - tls TLSSetting + tls Config } -func (c TLSSetting) newCertReloader() (*certReloader, error) { +func (c Config) newCertReloader() (*certReloader, error) { cert, err := c.loadCertificate() if err != nil { return nil, err @@ -149,7 +175,7 @@ func (r *certReloader) GetCertificate() (*tls.Certificate, error) { // loadTLSConfig loads TLS certificates and returns a tls.Config. // This will set the RootCAs and Certificates of a tls.Config. -func (c TLSSetting) loadTLSConfig() (*tls.Config, error) { +func (c Config) loadTLSConfig() (*tls.Config, error) { certPool, err := c.loadCACertPool() if err != nil { return nil, err @@ -163,8 +189,8 @@ func (c TLSSetting) loadTLSConfig() (*tls.Config, error) { if err != nil { return nil, fmt.Errorf("failed to load TLS cert and key: %w", err) } - getCertificate = func(chi *tls.ClientHelloInfo) (*tls.Certificate, error) { return certReloader.GetCertificate() } - getClientCertificate = func(cri *tls.CertificateRequestInfo) (*tls.Certificate, error) { return certReloader.GetCertificate() } + getCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) { return certReloader.GetCertificate() } + getClientCertificate = func(*tls.CertificateRequestInfo) (*tls.Certificate, error) { return certReloader.GetCertificate() } } minTLS, err := convertVersion(c.MinVersion, defaultMinTLSVersion) @@ -175,6 +201,10 @@ func (c TLSSetting) loadTLSConfig() (*tls.Config, error) { if err != nil { return nil, fmt.Errorf("invalid TLS max_version: %w", err) } + cipherSuites, err := convertCipherSuites(c.CipherSuites) + if err != nil { + return nil, err + } return &tls.Config{ RootCAs: certPool, @@ -182,10 +212,30 @@ func (c TLSSetting) loadTLSConfig() (*tls.Config, error) { GetClientCertificate: getClientCertificate, MinVersion: minTLS, MaxVersion: maxTLS, + CipherSuites: cipherSuites, }, nil } -func (c TLSSetting) loadCACertPool() (*x509.CertPool, error) { +func convertCipherSuites(cipherSuites []string) ([]uint16, error) { + var result []uint16 + var errs []error + for _, suite := range cipherSuites { + found := false + for _, supported := range tls.CipherSuites() { + if suite == supported.Name { + result = append(result, supported.ID) + found = true + break + } + } + if !found { + errs = append(errs, fmt.Errorf("invalid TLS cipher suite: %q", suite)) + } + } + return result, errors.Join(errs...) +} + +func (c Config) loadCACertPool() (*x509.CertPool, error) { // There is no need to load the System Certs for RootCAs because // if the value is nil, it will default to checking against th System Certs. var err error @@ -211,7 +261,7 @@ func (c TLSSetting) loadCACertPool() (*x509.CertPool, error) { return certPool, nil } -func (c TLSSetting) loadCertFile(certPath string) (*x509.CertPool, error) { +func (c Config) loadCertFile(certPath string) (*x509.CertPool, error) { certPem, err := os.ReadFile(filepath.Clean(certPath)) if err != nil { return nil, fmt.Errorf("failed to load cert %s: %w", certPath, err) @@ -220,7 +270,7 @@ func (c TLSSetting) loadCertFile(certPath string) (*x509.CertPool, error) { return c.loadCertPem(certPem) } -func (c TLSSetting) loadCertPem(certPem []byte) (*x509.CertPool, error) { +func (c Config) loadCertPem(certPem []byte) (*x509.CertPool, error) { certPool := x509.NewCertPool() if !certPool.AppendCertsFromPEM(certPem) { return nil, fmt.Errorf("failed to parse cert") @@ -228,7 +278,7 @@ func (c TLSSetting) loadCertPem(certPem []byte) (*x509.CertPool, error) { return certPool, nil } -func (c TLSSetting) loadCertificate() (tls.Certificate, error) { +func (c Config) loadCertificate() (tls.Certificate, error) { switch { case c.hasCert() != c.hasKey(): return tls.Certificate{}, fmt.Errorf("for auth via TLS, provide both certificate and key, or neither") @@ -268,13 +318,21 @@ func (c TLSSetting) loadCertificate() (tls.Certificate, error) { return certificate, err } -func (c TLSSetting) loadCert(caPath string) (*x509.CertPool, error) { +func (c Config) loadCert(caPath string) (*x509.CertPool, error) { caPEM, err := os.ReadFile(filepath.Clean(caPath)) if err != nil { return nil, fmt.Errorf("failed to load CA %s: %w", caPath, err) } - certPool := x509.NewCertPool() + var certPool *x509.CertPool + if c.IncludeSystemCACertsPool { + if certPool, err = systemCertPool(); err != nil { + return nil, err + } + } + if certPool == nil { + certPool = x509.NewCertPool() + } if !certPool.AppendCertsFromPEM(caPEM) { return nil, fmt.Errorf("failed to parse CA %s", caPath) } @@ -282,7 +340,7 @@ func (c TLSSetting) loadCert(caPath string) (*x509.CertPool, error) { } // LoadTLSConfig loads the TLS configuration. -func (c TLSClientSetting) LoadTLSConfig() (*tls.Config, error) { +func (c ClientConfig) LoadTLSConfig() (*tls.Config, error) { if c.Insecure && !c.hasCA() { return nil, nil } @@ -297,7 +355,7 @@ func (c TLSClientSetting) LoadTLSConfig() (*tls.Config, error) { } // LoadTLSConfig loads the TLS configuration. -func (c TLSServerSetting) LoadTLSConfig() (*tls.Config, error) { +func (c ServerConfig) LoadTLSConfig() (*tls.Config, error) { tlsCfg, err := c.loadTLSConfig() if err != nil { return nil, fmt.Errorf("failed to load TLS config: %w", err) @@ -312,7 +370,7 @@ func (c TLSServerSetting) LoadTLSConfig() (*tls.Config, error) { if err != nil { return nil, err } - tlsCfg.GetConfigForClient = func(t *tls.ClientHelloInfo) (*tls.Config, error) { return reloader.getClientConfig(tlsCfg) } + tlsCfg.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { return reloader.getClientConfig(tlsCfg) } } tlsCfg.ClientCAs = reloader.certPool tlsCfg.ClientAuth = tls.RequireAndVerifyClientCert @@ -320,22 +378,22 @@ func (c TLSServerSetting) LoadTLSConfig() (*tls.Config, error) { return tlsCfg, nil } -func (c TLSServerSetting) loadClientCAFile() (*x509.CertPool, error) { +func (c ServerConfig) loadClientCAFile() (*x509.CertPool, error) { return c.loadCert(c.ClientCAFile) } -func (c TLSSetting) hasCA() bool { return c.hasCAFile() || c.hasCAPem() } -func (c TLSSetting) hasCert() bool { return c.hasCertFile() || c.hasCertPem() } -func (c TLSSetting) hasKey() bool { return c.hasKeyFile() || c.hasKeyPem() } +func (c Config) hasCA() bool { return c.hasCAFile() || c.hasCAPem() } +func (c Config) hasCert() bool { return c.hasCertFile() || c.hasCertPem() } +func (c Config) hasKey() bool { return c.hasKeyFile() || c.hasKeyPem() } -func (c TLSSetting) hasCAFile() bool { return c.CAFile != "" } -func (c TLSSetting) hasCAPem() bool { return len(c.CAPem) != 0 } +func (c Config) hasCAFile() bool { return c.CAFile != "" } +func (c Config) hasCAPem() bool { return len(c.CAPem) != 0 } -func (c TLSSetting) hasCertFile() bool { return c.CertFile != "" } -func (c TLSSetting) hasCertPem() bool { return len(c.CertPem) != 0 } +func (c Config) hasCertFile() bool { return c.CertFile != "" } +func (c Config) hasCertPem() bool { return len(c.CertPem) != 0 } -func (c TLSSetting) hasKeyFile() bool { return c.KeyFile != "" } -func (c TLSSetting) hasKeyPem() bool { return len(c.KeyPem) != 0 } +func (c Config) hasKeyFile() bool { return c.KeyFile != "" } +func (c Config) hasKeyPem() bool { return len(c.KeyPem) != 0 } func convertVersion(v string, defaultVersion uint16) (uint16, error) { // Use a default that is explicitly defined diff --git a/config/configtls/configtls_test.go b/config/configtls/configtls_test.go index db1658f1dbf..47a50f58a3e 100644 --- a/config/configtls/configtls_test.go +++ b/config/configtls/configtls_test.go @@ -6,6 +6,7 @@ package configtls import ( "crypto/tls" "crypto/x509" + "errors" "fmt" "io" "os" @@ -22,30 +23,34 @@ import ( func TestOptionsToConfig(t *testing.T) { tests := []struct { name string - options TLSSetting + options Config expectError string }{ { name: "should load system CA", - options: TLSSetting{CAFile: ""}, + options: Config{CAFile: ""}, }, { name: "should load custom CA", - options: TLSSetting{CAFile: filepath.Join("testdata", "ca-1.crt")}, + options: Config{CAFile: filepath.Join("testdata", "ca-1.crt")}, + }, + { + name: "should load system CA and custom CA", + options: TLSSetting{IncludeSystemCACertsPool: true, CAFile: filepath.Join("testdata", "ca-1.crt")}, }, { name: "should fail with invalid CA file path", - options: TLSSetting{CAFile: filepath.Join("testdata", "not/valid")}, + options: Config{CAFile: filepath.Join("testdata", "not/valid")}, expectError: "failed to load CA", }, { name: "should fail with invalid CA file content", - options: TLSSetting{CAFile: filepath.Join("testdata", "testCA-bad.txt")}, + options: Config{CAFile: filepath.Join("testdata", "testCA-bad.txt")}, expectError: "failed to parse cert", }, { name: "should load valid TLS settings", - options: TLSSetting{ + options: Config{ CAFile: filepath.Join("testdata", "ca-1.crt"), CertFile: filepath.Join("testdata", "server-1.crt"), KeyFile: filepath.Join("testdata", "server-1.key"), @@ -53,7 +58,7 @@ func TestOptionsToConfig(t *testing.T) { }, { name: "should fail with missing TLS KeyFile", - options: TLSSetting{ + options: Config{ CAFile: filepath.Join("testdata", "ca-1.crt"), CertFile: filepath.Join("testdata", "server-1.crt"), }, @@ -61,7 +66,7 @@ func TestOptionsToConfig(t *testing.T) { }, { name: "should fail with invalid TLS KeyFile", - options: TLSSetting{ + options: Config{ CAFile: filepath.Join("testdata", "ca-1.crt"), CertFile: filepath.Join("testdata", "server-1.crt"), KeyFile: filepath.Join("testdata", "not/valid"), @@ -70,7 +75,7 @@ func TestOptionsToConfig(t *testing.T) { }, { name: "should fail with missing TLS Cert", - options: TLSSetting{ + options: Config{ CAFile: filepath.Join("testdata", "ca-1.crt"), KeyFile: filepath.Join("testdata", "server-1.key"), }, @@ -78,7 +83,7 @@ func TestOptionsToConfig(t *testing.T) { }, { name: "should fail with invalid TLS Cert", - options: TLSSetting{ + options: Config{ CAFile: filepath.Join("testdata", "ca-1.crt"), CertFile: filepath.Join("testdata", "not/valid"), KeyFile: filepath.Join("testdata", "server-1.key"), @@ -87,52 +92,52 @@ func TestOptionsToConfig(t *testing.T) { }, { name: "should fail with invalid TLS CA", - options: TLSSetting{ + options: Config{ CAFile: filepath.Join("testdata", "not/valid"), }, expectError: "failed to load CA", }, { name: "should fail with invalid CA pool", - options: TLSSetting{ + options: Config{ CAFile: filepath.Join("testdata", "testCA-bad.txt"), }, expectError: "failed to parse cert", }, { name: "should pass with valid CA pool", - options: TLSSetting{ + options: Config{ CAFile: filepath.Join("testdata", "ca-1.crt"), }, }, { name: "should pass with valid min and max version", - options: TLSSetting{ + options: Config{ MinVersion: "1.1", MaxVersion: "1.2", }, }, { name: "should pass with invalid min", - options: TLSSetting{ + options: Config{ MinVersion: "1.7", }, expectError: "invalid TLS min_", }, { name: "should pass with invalid max", - options: TLSSetting{ + options: Config{ MaxVersion: "1.7", }, expectError: "invalid TLS max_", }, { name: "should load custom CA PEM", - options: TLSSetting{CAPem: readFilePanics("testdata/ca-1.crt")}, + options: Config{CAPem: readFilePanics("testdata/ca-1.crt")}, }, { name: "should load valid TLS settings with PEMs", - options: TLSSetting{ + options: Config{ CAPem: readFilePanics("testdata/ca-1.crt"), CertPem: readFilePanics("testdata/server-1.crt"), KeyPem: readFilePanics("testdata/server-1.key"), @@ -140,26 +145,26 @@ func TestOptionsToConfig(t *testing.T) { }, { name: "mix Cert file and Key PEM provided", - options: TLSSetting{ + options: Config{ CertFile: "testdata/server-1.crt", KeyPem: readFilePanics("testdata/server-1.key"), }, }, { name: "mix Cert PEM and Key File provided", - options: TLSSetting{ + options: Config{ CertPem: readFilePanics("testdata/server-1.crt"), KeyFile: "testdata/server-1.key", }, }, { name: "should fail with invalid CA PEM", - options: TLSSetting{CAPem: readFilePanics("testdata/testCA-bad.txt")}, + options: Config{CAPem: readFilePanics("testdata/testCA-bad.txt")}, expectError: "failed to parse cert", }, { name: "should fail CA file and PEM both provided", - options: TLSSetting{ + options: Config{ CAFile: "testdata/ca-1.crt", CAPem: readFilePanics("testdata/ca-1.crt"), }, @@ -167,7 +172,7 @@ func TestOptionsToConfig(t *testing.T) { }, { name: "should fail Cert file and PEM both provided", - options: TLSSetting{ + options: Config{ CertFile: "testdata/server-1.crt", CertPem: readFilePanics("testdata/server-1.crt"), KeyFile: "testdata/server-1.key", @@ -176,7 +181,7 @@ func TestOptionsToConfig(t *testing.T) { }, { name: "should fail Key file and PEM both provided", - options: TLSSetting{ + options: Config{ CertFile: "testdata/server-1.crt", KeyFile: "testdata/ca-1.crt", KeyPem: readFilePanics("testdata/server-1.key"), @@ -185,7 +190,7 @@ func TestOptionsToConfig(t *testing.T) { }, { name: "should fail to load valid TLS settings with bad Cert PEM", - options: TLSSetting{ + options: Config{ CAPem: readFilePanics("testdata/ca-1.crt"), CertPem: readFilePanics("testdata/testCA-bad.txt"), KeyPem: readFilePanics("testdata/server-1.key"), @@ -194,7 +199,7 @@ func TestOptionsToConfig(t *testing.T) { }, { name: "should fail to load valid TLS settings with bad Key PEM", - options: TLSSetting{ + options: Config{ CAPem: readFilePanics("testdata/ca-1.crt"), CertPem: readFilePanics("testdata/server-1.crt"), KeyPem: readFilePanics("testdata/testCA-bad.txt"), @@ -203,7 +208,7 @@ func TestOptionsToConfig(t *testing.T) { }, { name: "should fail with missing TLS KeyPem", - options: TLSSetting{ + options: Config{ CAPem: readFilePanics("testdata/ca-1.crt"), CertPem: readFilePanics("testdata/server-1.crt"), }, @@ -211,7 +216,7 @@ func TestOptionsToConfig(t *testing.T) { }, { name: "should fail with missing TLS Cert PEM", - options: TLSSetting{ + options: Config{ CAPem: readFilePanics("testdata/ca-1.crt"), KeyPem: readFilePanics("testdata/server-1.key"), }, @@ -243,8 +248,8 @@ func readFilePanics(filePath string) configopaque.String { } func TestLoadTLSClientConfigError(t *testing.T) { - tlsSetting := TLSClientSetting{ - TLSSetting: TLSSetting{ + tlsSetting := ClientConfig{ + TLSSetting: Config{ CertFile: "doesnt/exist", KeyFile: "doesnt/exist", }, @@ -254,19 +259,19 @@ func TestLoadTLSClientConfigError(t *testing.T) { } func TestLoadTLSClientConfig(t *testing.T) { - tlsSetting := TLSClientSetting{ + tlsSetting := ClientConfig{ Insecure: true, } tlsCfg, err := tlsSetting.LoadTLSConfig() assert.NoError(t, err) assert.Nil(t, tlsCfg) - tlsSetting = TLSClientSetting{} + tlsSetting = ClientConfig{} tlsCfg, err = tlsSetting.LoadTLSConfig() assert.NoError(t, err) assert.NotNil(t, tlsCfg) - tlsSetting = TLSClientSetting{ + tlsSetting = ClientConfig{ InsecureSkipVerify: true, } tlsCfg, err = tlsSetting.LoadTLSConfig() @@ -276,8 +281,8 @@ func TestLoadTLSClientConfig(t *testing.T) { } func TestLoadTLSServerConfigError(t *testing.T) { - tlsSetting := TLSServerSetting{ - TLSSetting: TLSSetting{ + tlsSetting := ServerConfig{ + TLSSetting: Config{ CertFile: "doesnt/exist", KeyFile: "doesnt/exist", }, @@ -285,7 +290,7 @@ func TestLoadTLSServerConfigError(t *testing.T) { _, err := tlsSetting.LoadTLSConfig() assert.Error(t, err) - tlsSetting = TLSServerSetting{ + tlsSetting = ServerConfig{ ClientCAFile: "doesnt/exist", } _, err = tlsSetting.LoadTLSConfig() @@ -293,7 +298,7 @@ func TestLoadTLSServerConfigError(t *testing.T) { } func TestLoadTLSServerConfig(t *testing.T) { - tlsSetting := TLSServerSetting{} + tlsSetting := ServerConfig{} tlsCfg, err := tlsSetting.LoadTLSConfig() assert.NoError(t, err) assert.NotNil(t, tlsCfg) @@ -305,7 +310,7 @@ func TestLoadTLSServerConfigReload(t *testing.T) { overwriteClientCA(t, tmpCaPath, "ca-1.crt") - tlsSetting := TLSServerSetting{ + tlsSetting := ServerConfig{ ClientCAFile: tmpCaPath, ReloadClientCAFile: true, } @@ -336,7 +341,7 @@ func TestLoadTLSServerConfigFailingReload(t *testing.T) { overwriteClientCA(t, tmpCaPath, "ca-1.crt") - tlsSetting := TLSServerSetting{ + tlsSetting := ServerConfig{ ClientCAFile: tmpCaPath, ReloadClientCAFile: true, } @@ -367,7 +372,7 @@ func TestLoadTLSServerConfigFailingInitialLoad(t *testing.T) { overwriteClientCA(t, tmpCaPath, "testCA-bad.txt") - tlsSetting := TLSServerSetting{ + tlsSetting := ServerConfig{ ClientCAFile: tmpCaPath, ReloadClientCAFile: true, } @@ -381,7 +386,7 @@ func TestLoadTLSServerConfigWrongPath(t *testing.T) { tmpCaPath := createTempClientCaFile(t) - tlsSetting := TLSServerSetting{ + tlsSetting := ServerConfig{ ClientCAFile: tmpCaPath + "wrong-path", ReloadClientCAFile: true, } @@ -397,7 +402,7 @@ func TestLoadTLSServerConfigFailing(t *testing.T) { overwriteClientCA(t, tmpCaPath, "ca-1.crt") - tlsSetting := TLSServerSetting{ + tlsSetting := ServerConfig{ ClientCAFile: tmpCaPath, ReloadClientCAFile: true, } @@ -443,7 +448,7 @@ func createTempClientCaFile(t *testing.T) string { } func TestEagerlyLoadCertificate(t *testing.T) { - options := TLSSetting{ + options := Config{ CertFile: filepath.Join("testdata", "client-1.crt"), KeyFile: filepath.Join("testdata", "client-1.key"), } @@ -530,7 +535,7 @@ func TestCertificateReload(t *testing.T) { assert.NoError(t, err) assert.NoError(t, fdk.Close()) - options := TLSSetting{ + options := Config{ CertFile: certFile.Name(), KeyFile: keyFile.Name(), ReloadInterval: test.reloadInterval, @@ -611,7 +616,7 @@ func TestMinMaxTLSVersions(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - setting := TLSSetting{ + setting := Config{ MinVersion: test.minVersion, MaxVersion: test.maxVersion, } @@ -627,3 +632,114 @@ func TestMinMaxTLSVersions(t *testing.T) { }) } } + +func TestCipherSuites(t *testing.T) { + tests := []struct { + name string + tlsSetting Config + wantErr string + result []uint16 + }{ + { + name: "no suites set", + tlsSetting: Config{}, + result: nil, + }, + { + name: "one cipher suite set", + tlsSetting: Config{ + CipherSuites: []string{"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"}, + }, + result: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, + }, + { + name: "invalid cipher suite set", + tlsSetting: Config{ + CipherSuites: []string{"FOO"}, + }, + wantErr: `invalid TLS cipher suite: "FOO"`, + }, + { + name: "multiple invalid cipher suites set", + tlsSetting: Config{ + CipherSuites: []string{"FOO", "BAR"}, + }, + wantErr: `invalid TLS cipher suite: "FOO" +invalid TLS cipher suite: "BAR"`, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + config, err := test.tlsSetting.loadTLSConfig() + if test.wantErr != "" { + assert.EqualError(t, err, test.wantErr) + } else { + assert.NoError(t, err) + assert.Equal(t, test.result, config.CipherSuites) + } + }) + } +} + +func TestSystemCertPool(t *testing.T) { + anError := errors.New("my error") + tests := []struct { + name string + tlsSetting TLSSetting + wantErr error + systemCertFn func() (*x509.CertPool, error) + }{ + { + name: "not using system cert pool", + tlsSetting: TLSSetting{ + IncludeSystemCACertsPool: false, + }, + wantErr: nil, + systemCertFn: x509.SystemCertPool, + }, + { + name: "using system cert pool", + tlsSetting: TLSSetting{ + IncludeSystemCACertsPool: true, + }, + wantErr: nil, + systemCertFn: x509.SystemCertPool, + }, + { + name: "error loading system cert pool", + tlsSetting: TLSSetting{ + IncludeSystemCACertsPool: true, + }, + wantErr: anError, + systemCertFn: func() (*x509.CertPool, error) { + return nil, anError + }, + }, + { + name: "nil system cert pool", + tlsSetting: TLSSetting{ + IncludeSystemCACertsPool: true, + }, + wantErr: nil, + systemCertFn: func() (*x509.CertPool, error) { + return nil, nil + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + oldSystemCertPool := systemCertPool + systemCertPool = test.systemCertFn + defer func() { + systemCertPool = oldSystemCertPool + }() + certPool, err := test.tlsSetting.loadCert(filepath.Join("testdata", "ca-1.crt")) + if test.wantErr != nil { + assert.Equal(t, test.wantErr, err) + } else { + assert.NotNil(t, certPool) + } + }) + } +} diff --git a/config/configtls/go.mod b/config/configtls/go.mod index e5878446df0..865c82a969e 100644 --- a/config/configtls/go.mod +++ b/config/configtls/go.mod @@ -1,19 +1,21 @@ module go.opentelemetry.io/collector/config/configtls -go 1.20 +go 1.21 require ( - github.com/fsnotify/fsnotify v1.6.0 + github.com/fsnotify/fsnotify v1.7.0 github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/config/configopaque v0.85.0 + go.opentelemetry.io/collector/config/configopaque v1.3.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.12.0 // indirect + golang.org/x/sys v0.14.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) replace go.opentelemetry.io/collector/config/configopaque => ../configopaque + +replace go.opentelemetry.io/collector/confmap => ../../confmap diff --git a/config/configtls/go.sum b/config/configtls/go.sum index 45e413628af..352be822f6e 100644 --- a/config/configtls/go.sum +++ b/config/configtls/go.sum @@ -1,20 +1,38 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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= 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/config/internal/go.mod b/config/internal/go.mod index 647749fb92f..7d5daac8dab 100644 --- a/config/internal/go.mod +++ b/config/internal/go.mod @@ -1,18 +1,33 @@ module go.opentelemetry.io/collector/config/internal -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.uber.org/zap v1.26.0 + go.opentelemetry.io/collector v0.96.0 + go.uber.org/goleak v1.3.0 + go.uber.org/zap v1.27.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/kr/pretty v0.3.1 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect + go.opentelemetry.io/collector/featuregate v1.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace go.opentelemetry.io/collector => ../../ + +replace go.opentelemetry.io/collector/featuregate => ../../featuregate + +replace go.opentelemetry.io/collector/confmap => ../../confmap + +replace go.opentelemetry.io/collector/config/configtelemetry => ../configtelemetry + +replace go.opentelemetry.io/collector/pdata => ../../pdata + +replace go.opentelemetry.io/collector/consumer => ../../consumer + +replace go.opentelemetry.io/collector/component => ../../component diff --git a/config/internal/go.sum b/config/internal/go.sum index 4c930736df1..d7bcd0e2f73 100644 --- a/config/internal/go.sum +++ b/config/internal/go.sum @@ -1,26 +1,23 @@ -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= 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/internal/package_test.go b/config/internal/package_test.go new file mode 100644 index 00000000000..4486cdb28aa --- /dev/null +++ b/config/internal/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package internal + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/config/internal/warning.go b/config/internal/warning.go index f403967da2f..28d55bfd4dc 100644 --- a/config/internal/warning.go +++ b/config/internal/warning.go @@ -9,6 +9,8 @@ import ( "strings" "go.uber.org/zap" + + "go.opentelemetry.io/collector/internal/localhostgate" ) func shouldWarn(endpoint string) bool { @@ -38,11 +40,12 @@ func shouldWarn(endpoint string) bool { func WarnOnUnspecifiedHost(logger *zap.Logger, endpoint string) { if shouldWarn(endpoint) { logger.Warn( - "Using the 0.0.0.0 address exposes this server to every network interface, which may facilitate Denial of Service attacks", + "Using the 0.0.0.0 address exposes this server to every network interface, which may facilitate Denial of Service attacks. Enable the feature gate to change the default and remove this warning.", zap.String( "documentation", "https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/security-best-practices.md#safeguards-against-denial-of-service-attacks", ), + zap.String("feature gate ID", localhostgate.UseLocalHostAsDefaultHostID), ) } } diff --git a/confmap/confmap.go b/confmap/confmap.go index 254f0813433..213e4a332d9 100644 --- a/confmap/confmap.go +++ b/confmap/confmap.go @@ -8,10 +8,10 @@ import ( "fmt" "reflect" + "github.com/go-viper/mapstructure/v2" "github.com/knadh/koanf/maps" "github.com/knadh/koanf/providers/confmap" "github.com/knadh/koanf/v2" - "github.com/mitchellh/mapstructure" encoder "go.opentelemetry.io/collector/confmap/internal/mapstructure" ) @@ -51,15 +51,15 @@ type UnmarshalOption interface { } type unmarshalOption struct { - errorUnused bool + ignoreUnused bool } -// WithErrorUnused sets an option to error when there are existing -// keys in the original Conf that were unused in the decoding process +// WithIgnoreUnused sets an option to ignore errors if existing +// keys in the original Conf were unused in the decoding process // (extra keys). -func WithErrorUnused() UnmarshalOption { +func WithIgnoreUnused() UnmarshalOption { return unmarshalOptionFunc(func(uo *unmarshalOption) { - uo.errorUnused = true + uo.ignoreUnused = true }) } @@ -76,7 +76,7 @@ func (l *Conf) Unmarshal(result any, opts ...UnmarshalOption) error { for _, opt := range opts { opt.apply(&set) } - return decodeConfig(l, result, set.errorUnused) + return decodeConfig(l, result, !set.ignoreUnused) } type marshalOption struct{} diff --git a/confmap/confmap_test.go b/confmap/confmap_test.go index 211eca429aa..6680a1bc517 100644 --- a/confmap/confmap_test.go +++ b/confmap/confmap_test.go @@ -143,13 +143,14 @@ func TestExpandNilStructPointersHookFuncDefaultNotNilConfigNil(t *testing.T) { assert.Equal(t, &Struct{}, cfg.MapStruct["struct"]) } -func TestUnmarshalWithErrorUnused(t *testing.T) { +func TestUnmarshalWithIgnoreUnused(t *testing.T) { stringMap := map[string]any{ "boolean": true, "string": "this is a string", } conf := NewFromStringMap(stringMap) - assert.Error(t, conf.Unmarshal(&TestIDConfig{}, WithErrorUnused())) + assert.Error(t, conf.Unmarshal(&TestIDConfig{})) + assert.NoError(t, conf.Unmarshal(&TestIDConfig{}, WithIgnoreUnused())) } type TestConfig struct { @@ -393,7 +394,7 @@ type errConfig struct { Foo string `mapstructure:"foo"` } -func (tc *errConfig) Unmarshal(_ *Conf) error { +func (tc *errConfig) Unmarshal(*Conf) error { return errors.New("never works") } diff --git a/confmap/confmaptest/configtest_test.go b/confmap/confmaptest/configtest_test.go index 4a885d9655f..151a1c9275a 100644 --- a/confmap/confmaptest/configtest_test.go +++ b/confmap/confmaptest/configtest_test.go @@ -54,6 +54,6 @@ func (s schemeProvider) Scheme() string { return s.scheme } -func (s schemeProvider) Shutdown(_ context.Context) error { +func (s schemeProvider) Shutdown(context.Context) error { return nil } diff --git a/confmap/confmaptest/package_test.go b/confmap/confmaptest/package_test.go new file mode 100644 index 00000000000..77bb79e7696 --- /dev/null +++ b/confmap/confmaptest/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package confmaptest + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/confmap/converter.go b/confmap/converter.go index 233d86f5d79..17316d10304 100644 --- a/confmap/converter.go +++ b/confmap/converter.go @@ -7,6 +7,10 @@ import ( "context" ) +// ConverterSettings are the settings to initialize a Converter. +// Any Converter should take this as a parameter in its constructor. +type ConverterSettings struct{} + // Converter is a converter interface for the confmap.Conf that allows distributions // (in the future components as well) to build backwards compatible config converters. type Converter interface { diff --git a/confmap/converter/expandconverter/Makefile b/confmap/converter/expandconverter/Makefile new file mode 100644 index 00000000000..bdd863a203b --- /dev/null +++ b/confmap/converter/expandconverter/Makefile @@ -0,0 +1 @@ +include ../../../Makefile.Common diff --git a/confmap/converter/expandconverter/expand.go b/confmap/converter/expandconverter/expand.go index d2cd5e963e8..dc3a89812c4 100644 --- a/confmap/converter/expandconverter/expand.go +++ b/confmap/converter/expandconverter/expand.go @@ -15,7 +15,7 @@ type converter struct{} // New returns a confmap.Converter, that expands all environment variables for a given confmap.Conf. // // Notice: This API is experimental. -func New() confmap.Converter { +func New(confmap.ConverterSettings) confmap.Converter { return converter{} } diff --git a/confmap/converter/expandconverter/expand_test.go b/confmap/converter/expandconverter/expand_test.go index 7b4a9553a3d..731dd52e9b6 100644 --- a/confmap/converter/expandconverter/expand_test.go +++ b/confmap/converter/expandconverter/expand_test.go @@ -45,7 +45,7 @@ func TestNewExpandConverter(t *testing.T) { require.NoError(t, err, "Unable to get config") // Test that expanded configs are the same with the simple config with no env vars. - require.NoError(t, New().Convert(context.Background(), conf)) + require.NoError(t, New(confmap.ConverterSettings{}).Convert(context.Background(), conf)) assert.Equal(t, expectedCfgMap.ToStringMap(), conf.ToStringMap()) }) } @@ -64,7 +64,7 @@ func TestNewExpandConverter_EscapedMaps(t *testing.T) { "recv": "$MAP_VALUE", }}, ) - require.NoError(t, New().Convert(context.Background(), conf)) + require.NoError(t, New(confmap.ConverterSettings{}).Convert(context.Background(), conf)) expectedMap := map[string]any{ "test_string_map": map[string]any{ @@ -101,7 +101,7 @@ func TestNewExpandConverter_EscapedEnvVars(t *testing.T) { // escaped $ alone "recv.7": "$", }} - require.NoError(t, New().Convert(context.Background(), conf)) + require.NoError(t, New(confmap.ConverterSettings{}).Convert(context.Background(), conf)) assert.Equal(t, expectedMap, conf.ToStringMap()) } @@ -154,7 +154,7 @@ func TestNewExpandConverterHostPort(t *testing.T) { for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { conf := confmap.NewFromStringMap(tt.input) - require.NoError(t, New().Convert(context.Background(), conf)) + require.NoError(t, New(confmap.ConverterSettings{}).Convert(context.Background(), conf)) assert.Equal(t, tt.expected, conf.ToStringMap()) }) } diff --git a/confmap/converter/expandconverter/go.mod b/confmap/converter/expandconverter/go.mod new file mode 100644 index 00000000000..81efa808243 --- /dev/null +++ b/confmap/converter/expandconverter/go.mod @@ -0,0 +1,24 @@ +module go.opentelemetry.io/collector/confmap/converter/expandconverter + +go 1.21 + +require ( + github.com/stretchr/testify v1.8.4 + go.opentelemetry.io/collector/confmap v0.96.0 + go.uber.org/goleak v1.3.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace go.opentelemetry.io/collector/confmap => ../../ diff --git a/confmap/converter/expandconverter/go.sum b/confmap/converter/expandconverter/go.sum new file mode 100644 index 00000000000..69f4a4f6724 --- /dev/null +++ b/confmap/converter/expandconverter/go.sum @@ -0,0 +1,31 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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/confmap/converter/expandconverter/package_test.go b/confmap/converter/expandconverter/package_test.go new file mode 100644 index 00000000000..39c682a02e2 --- /dev/null +++ b/confmap/converter/expandconverter/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package expandconverter + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/confmap/go.mod b/confmap/go.mod index 9d93476f6bf..869cdedbe72 100644 --- a/confmap/go.mod +++ b/confmap/go.mod @@ -1,14 +1,14 @@ module go.opentelemetry.io/collector/confmap -go 1.20 +go 1.21 require ( + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 github.com/knadh/koanf/maps v0.1.1 github.com/knadh/koanf/providers/confmap v0.1.0 - github.com/knadh/koanf/v2 v2.0.1 - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 + github.com/knadh/koanf/v2 v2.1.0 github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 + go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -21,8 +21,6 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect ) -replace go.opentelemetry.io/collector/featuregate => ../featuregate - retract ( v0.76.0 // Depends on retracted pdata v1.0.0-rc10 module, use v0.76.1 v0.69.0 // Release failed, use v0.69.1 diff --git a/confmap/go.sum b/confmap/go.sum index 02cbe57eb22..386dd5d4525 100644 --- a/confmap/go.sum +++ b/confmap/go.sum @@ -1,29 +1,32 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 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-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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/confmap/internal/mapstructure/encoder.go b/confmap/internal/mapstructure/encoder.go index feb5eefa76b..408560e2262 100644 --- a/confmap/internal/mapstructure/encoder.go +++ b/confmap/internal/mapstructure/encoder.go @@ -10,7 +10,7 @@ import ( "reflect" "strings" - "github.com/mitchellh/mapstructure" + "github.com/go-viper/mapstructure/v2" ) const ( diff --git a/confmap/internal/mapstructure/encoder_test.go b/confmap/internal/mapstructure/encoder_test.go index b557c91735a..fac12e8a6df 100644 --- a/confmap/internal/mapstructure/encoder_test.go +++ b/confmap/internal/mapstructure/encoder_test.go @@ -10,7 +10,7 @@ import ( "strings" "testing" - "github.com/mitchellh/mapstructure" + "github.com/go-viper/mapstructure/v2" "github.com/stretchr/testify/require" ) diff --git a/confmap/internal/mapstructure/package_test.go b/confmap/internal/mapstructure/package_test.go new file mode 100644 index 00000000000..626ac10579c --- /dev/null +++ b/confmap/internal/mapstructure/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package mapstructure + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/confmap/package_test.go b/confmap/package_test.go new file mode 100644 index 00000000000..ad90b748909 --- /dev/null +++ b/confmap/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package confmap + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/confmap/provider.go b/confmap/provider.go index 93735b83f4d..91c2a60065a 100644 --- a/confmap/provider.go +++ b/confmap/provider.go @@ -8,6 +8,10 @@ import ( "fmt" ) +// ProviderSettings are the settings to initialize a Provider. +// Any Provider should take this as a parameter in its constructor. +type ProviderSettings struct{} + // Provider is an interface that helps to retrieve a config map and watch for any // changes to the config map. Implementations may load the config from a file, // a database or any other source. diff --git a/confmap/provider/envprovider/Makefile b/confmap/provider/envprovider/Makefile new file mode 100644 index 00000000000..bdd863a203b --- /dev/null +++ b/confmap/provider/envprovider/Makefile @@ -0,0 +1 @@ +include ../../../Makefile.Common diff --git a/confmap/provider/envprovider/go.mod b/confmap/provider/envprovider/go.mod new file mode 100644 index 00000000000..86036ea552f --- /dev/null +++ b/confmap/provider/envprovider/go.mod @@ -0,0 +1,24 @@ +module go.opentelemetry.io/collector/confmap/provider/envprovider + +go 1.21 + +require ( + github.com/stretchr/testify v1.8.4 + go.opentelemetry.io/collector/confmap v0.96.0 + go.uber.org/goleak v1.3.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace go.opentelemetry.io/collector/confmap => ../../ diff --git a/confmap/provider/envprovider/go.sum b/confmap/provider/envprovider/go.sum new file mode 100644 index 00000000000..69f4a4f6724 --- /dev/null +++ b/confmap/provider/envprovider/go.sum @@ -0,0 +1,31 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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/confmap/provider/envprovider/package_test.go b/confmap/provider/envprovider/package_test.go new file mode 100644 index 00000000000..1465f46f8af --- /dev/null +++ b/confmap/provider/envprovider/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package envprovider + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/confmap/provider/envprovider/provider.go b/confmap/provider/envprovider/provider.go index d548a4594aa..61e8df8fbbf 100644 --- a/confmap/provider/envprovider/provider.go +++ b/confmap/provider/envprovider/provider.go @@ -17,12 +17,21 @@ const schemeName = "env" type provider struct{} +// NewWithSettings returns a new confmap.Provider that reads the configuration from the given environment variable. +// +// This Provider supports "env" scheme, and can be called with a selector: +// `env:NAME_OF_ENVIRONMENT_VARIABLE` +func NewWithSettings(confmap.ProviderSettings) confmap.Provider { + return &provider{} +} + // New returns a new confmap.Provider that reads the configuration from the given environment variable. // // This Provider supports "env" scheme, and can be called with a selector: // `env:NAME_OF_ENVIRONMENT_VARIABLE` +// Deprecated: [v0.94.0] Use NewWithSettings instead. func New() confmap.Provider { - return &provider{} + return NewWithSettings(confmap.ProviderSettings{}) } func (emp *provider) Retrieve(_ context.Context, uri string, _ confmap.WatcherFunc) (*confmap.Retrieved, error) { diff --git a/confmap/provider/fileprovider/Makefile b/confmap/provider/fileprovider/Makefile new file mode 100644 index 00000000000..bdd863a203b --- /dev/null +++ b/confmap/provider/fileprovider/Makefile @@ -0,0 +1 @@ +include ../../../Makefile.Common diff --git a/confmap/provider/fileprovider/go.mod b/confmap/provider/fileprovider/go.mod new file mode 100644 index 00000000000..bc546c4634b --- /dev/null +++ b/confmap/provider/fileprovider/go.mod @@ -0,0 +1,24 @@ +module go.opentelemetry.io/collector/confmap/provider/fileprovider + +go 1.21 + +require ( + github.com/stretchr/testify v1.8.4 + go.opentelemetry.io/collector/confmap v0.96.0 + go.uber.org/goleak v1.3.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace go.opentelemetry.io/collector/confmap => ../../ diff --git a/confmap/provider/fileprovider/go.sum b/confmap/provider/fileprovider/go.sum new file mode 100644 index 00000000000..69f4a4f6724 --- /dev/null +++ b/confmap/provider/fileprovider/go.sum @@ -0,0 +1,31 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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/confmap/provider/fileprovider/package_test.go b/confmap/provider/fileprovider/package_test.go new file mode 100644 index 00000000000..e94f125d2e3 --- /dev/null +++ b/confmap/provider/fileprovider/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package fileprovider + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/confmap/provider/fileprovider/provider.go b/confmap/provider/fileprovider/provider.go index 4d5377e6603..a4da3af387f 100644 --- a/confmap/provider/fileprovider/provider.go +++ b/confmap/provider/fileprovider/provider.go @@ -33,10 +33,30 @@ type provider struct{} // `file:/path/to/file` - absolute path (unix, windows) // `file:c:/path/to/file` - absolute path including drive-letter (windows) // `file:c:\path\to\file` - absolute path including drive-letter (windows) -func New() confmap.Provider { +func NewWithSettings(confmap.ProviderSettings) confmap.Provider { return &provider{} } +// New returns a new confmap.Provider that reads the configuration from a file. +// +// This Provider supports "file" scheme, and can be called with a "uri" that follows: +// +// file-uri = "file:" local-path +// local-path = [ drive-letter ] file-path +// drive-letter = ALPHA ":" +// +// The "file-path" can be relative or absolute, and it can be any OS supported format. +// +// Examples: +// `file:path/to/file` - relative path (unix, windows) +// `file:/path/to/file` - absolute path (unix, windows) +// `file:c:/path/to/file` - absolute path including drive-letter (windows) +// `file:c:\path\to\file` - absolute path including drive-letter (windows) +// Deprecated: [v0.94.0] Use NewWithSettings instead. +func New() confmap.Provider { + return NewWithSettings(confmap.ProviderSettings{}) +} + func (fmp *provider) Retrieve(_ context.Context, uri string, _ confmap.WatcherFunc) (*confmap.Retrieved, error) { if !strings.HasPrefix(uri, schemeName+":") { return nil, fmt.Errorf("%q uri is not supported by %q provider", uri, schemeName) diff --git a/confmap/provider/httpprovider/Makefile b/confmap/provider/httpprovider/Makefile new file mode 100644 index 00000000000..bdd863a203b --- /dev/null +++ b/confmap/provider/httpprovider/Makefile @@ -0,0 +1 @@ +include ../../../Makefile.Common diff --git a/confmap/provider/httpprovider/go.mod b/confmap/provider/httpprovider/go.mod new file mode 100644 index 00000000000..130befa5dea --- /dev/null +++ b/confmap/provider/httpprovider/go.mod @@ -0,0 +1,24 @@ +module go.opentelemetry.io/collector/confmap/provider/httpprovider + +go 1.21 + +require ( + github.com/stretchr/testify v1.8.4 + go.opentelemetry.io/collector/confmap v0.96.0 + go.uber.org/goleak v1.3.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace go.opentelemetry.io/collector/confmap => ../../ diff --git a/confmap/provider/httpprovider/go.sum b/confmap/provider/httpprovider/go.sum new file mode 100644 index 00000000000..69f4a4f6724 --- /dev/null +++ b/confmap/provider/httpprovider/go.sum @@ -0,0 +1,31 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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/confmap/provider/httpprovider/package_test.go b/confmap/provider/httpprovider/package_test.go new file mode 100644 index 00000000000..0faa72a1207 --- /dev/null +++ b/confmap/provider/httpprovider/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package httpprovider + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/confmap/provider/httpprovider/provider.go b/confmap/provider/httpprovider/provider.go index 458f7d5edbe..966faa510fb 100644 --- a/confmap/provider/httpprovider/provider.go +++ b/confmap/provider/httpprovider/provider.go @@ -8,11 +8,21 @@ import ( "go.opentelemetry.io/collector/confmap/provider/internal/configurablehttpprovider" ) +// NewWithSettings returns a new confmap.Provider that reads the configuration from a http server. +// +// This Provider supports "http" scheme. +// +// One example for HTTP URI is: http://localhost:3333/getConfig +func NewWithSettings(set confmap.ProviderSettings) confmap.Provider { + return configurablehttpprovider.New(configurablehttpprovider.HTTPScheme, set) +} + // New returns a new confmap.Provider that reads the configuration from a http server. // // This Provider supports "http" scheme. // // One example for HTTP URI is: http://localhost:3333/getConfig +// Deprecated: [v0.94.0] Use NewWithSettings instead. func New() confmap.Provider { - return configurablehttpprovider.New(configurablehttpprovider.HTTPScheme) + return NewWithSettings(confmap.ProviderSettings{}) } diff --git a/confmap/provider/httpsprovider/Makefile b/confmap/provider/httpsprovider/Makefile new file mode 100644 index 00000000000..bdd863a203b --- /dev/null +++ b/confmap/provider/httpsprovider/Makefile @@ -0,0 +1 @@ +include ../../../Makefile.Common diff --git a/confmap/provider/httpsprovider/go.mod b/confmap/provider/httpsprovider/go.mod new file mode 100644 index 00000000000..5bb4b5ae1d4 --- /dev/null +++ b/confmap/provider/httpsprovider/go.mod @@ -0,0 +1,24 @@ +module go.opentelemetry.io/collector/confmap/provider/httpsprovider + +go 1.21 + +require ( + github.com/stretchr/testify v1.8.4 + go.opentelemetry.io/collector/confmap v0.96.0 + go.uber.org/goleak v1.3.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace go.opentelemetry.io/collector/confmap => ../../ diff --git a/confmap/provider/httpsprovider/go.sum b/confmap/provider/httpsprovider/go.sum new file mode 100644 index 00000000000..69f4a4f6724 --- /dev/null +++ b/confmap/provider/httpsprovider/go.sum @@ -0,0 +1,31 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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/confmap/provider/httpsprovider/package_test.go b/confmap/provider/httpsprovider/package_test.go new file mode 100644 index 00000000000..7ed3dc83e10 --- /dev/null +++ b/confmap/provider/httpsprovider/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package httpsprovider + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/confmap/provider/httpsprovider/provider.go b/confmap/provider/httpsprovider/provider.go index 1afe0b54e35..6db2cc9b151 100644 --- a/confmap/provider/httpsprovider/provider.go +++ b/confmap/provider/httpsprovider/provider.go @@ -14,6 +14,17 @@ import ( // // To add extra CA certificates you need to install certificates in the system pool. This procedure is operating system // dependent. E.g.: on Linux please refer to the `update-ca-trust` command. +func NewWithSettings(set confmap.ProviderSettings) confmap.Provider { + return configurablehttpprovider.New(configurablehttpprovider.HTTPSScheme, set) +} + +// New returns a new confmap.Provider that reads the configuration from a https server. +// +// This Provider supports "https" scheme. One example of an HTTPS URI is: https://localhost:3333/getConfig +// +// To add extra CA certificates you need to install certificates in the system pool. This procedure is operating system +// dependent. E.g.: on Linux please refer to the `update-ca-trust` command. +// Deprecated: [v0.94.0] Use NewWithSettings instead. func New() confmap.Provider { - return configurablehttpprovider.New(configurablehttpprovider.HTTPSScheme) + return NewWithSettings(confmap.ProviderSettings{}) } diff --git a/confmap/provider/internal/configurablehttpprovider/package_test.go b/confmap/provider/internal/configurablehttpprovider/package_test.go new file mode 100644 index 00000000000..31c287dae4d --- /dev/null +++ b/confmap/provider/internal/configurablehttpprovider/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package configurablehttpprovider + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/confmap/provider/internal/configurablehttpprovider/provider.go b/confmap/provider/internal/configurablehttpprovider/provider.go index d4e3efcc6e1..c683d3d9a4e 100644 --- a/confmap/provider/internal/configurablehttpprovider/provider.go +++ b/confmap/provider/internal/configurablehttpprovider/provider.go @@ -38,7 +38,7 @@ type provider struct { // One example for http-uri: http://localhost:3333/getConfig // One example for https-uri: https://localhost:3333/getConfig // This is used by the http and https external implementations. -func New(scheme SchemeType) confmap.Provider { +func New(scheme SchemeType, _ confmap.ProviderSettings) confmap.Provider { return &provider{scheme: scheme} } diff --git a/confmap/provider/internal/configurablehttpprovider/provider_test.go b/confmap/provider/internal/configurablehttpprovider/provider_test.go index 7a3c5a5034f..ad4659879c4 100644 --- a/confmap/provider/internal/configurablehttpprovider/provider_test.go +++ b/confmap/provider/internal/configurablehttpprovider/provider_test.go @@ -23,11 +23,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/confmap" "go.opentelemetry.io/collector/confmap/confmaptest" ) -func newConfigurableHTTPProvider(scheme SchemeType) *provider { - return New(scheme).(*provider) +func newConfigurableHTTPProvider(scheme SchemeType, set confmap.ProviderSettings) *provider { + return New(scheme, set).(*provider) } func answerGet(w http.ResponseWriter, _ *http.Request) { @@ -122,7 +123,7 @@ func generateCertificate(hostname string) (cert string, key string, err error) { } func TestFunctionalityDownloadFileHTTP(t *testing.T) { - fp := newConfigurableHTTPProvider(HTTPScheme) + fp := newConfigurableHTTPProvider(HTTPScheme, confmap.ProviderSettings{}) ts := httptest.NewServer(http.HandlerFunc(answerGet)) defer ts.Close() _, err := fp.Retrieve(context.Background(), ts.URL, nil) @@ -210,7 +211,7 @@ func TestFunctionalityDownloadFileHTTPS(t *testing.T) { for _, tt := range tests { t.Run(tt.testName, func(t *testing.T) { - fp := newConfigurableHTTPProvider(HTTPSScheme) + fp := newConfigurableHTTPProvider(HTTPSScheme, confmap.ProviderSettings{}) // Parse url of the test server to get the port number. tsURL, err := url.Parse(ts.URL) require.NoError(t, err) @@ -229,20 +230,20 @@ func TestFunctionalityDownloadFileHTTPS(t *testing.T) { } func TestUnsupportedScheme(t *testing.T) { - fp := New(HTTPScheme) + fp := New(HTTPScheme, confmap.ProviderSettings{}) _, err := fp.Retrieve(context.Background(), "https://...", nil) assert.Error(t, err) assert.NoError(t, fp.Shutdown(context.Background())) - fp = New(HTTPSScheme) + fp = New(HTTPSScheme, confmap.ProviderSettings{}) _, err = fp.Retrieve(context.Background(), "http://...", nil) assert.Error(t, err) assert.NoError(t, fp.Shutdown(context.Background())) } func TestEmptyURI(t *testing.T) { - fp := New(HTTPScheme) - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fp := New(HTTPScheme, confmap.ProviderSettings{}) + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) })) defer ts.Close() @@ -252,8 +253,8 @@ func TestEmptyURI(t *testing.T) { } func TestRetrieveFromShutdownServer(t *testing.T) { - fp := New(HTTPScheme) - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) + fp := New(HTTPScheme, confmap.ProviderSettings{}) + ts := httptest.NewServer(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})) ts.Close() _, err := fp.Retrieve(context.Background(), ts.URL, nil) assert.Error(t, err) @@ -261,8 +262,8 @@ func TestRetrieveFromShutdownServer(t *testing.T) { } func TestNonExistent(t *testing.T) { - fp := New(HTTPScheme) - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fp := New(HTTPScheme, confmap.ProviderSettings{}) + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) })) defer ts.Close() @@ -272,8 +273,8 @@ func TestNonExistent(t *testing.T) { } func TestInvalidYAML(t *testing.T) { - fp := New(HTTPScheme) - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fp := New(HTTPScheme, confmap.ProviderSettings{}) + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) _, err := w.Write([]byte("wrong : [")) if err != nil { @@ -287,17 +288,17 @@ func TestInvalidYAML(t *testing.T) { } func TestScheme(t *testing.T) { - fp := New(HTTPScheme) + fp := New(HTTPScheme, confmap.ProviderSettings{}) assert.Equal(t, "http", fp.Scheme()) require.NoError(t, fp.Shutdown(context.Background())) } func TestValidateProviderScheme(t *testing.T) { - assert.NoError(t, confmaptest.ValidateProviderScheme(New(HTTPScheme))) + assert.NoError(t, confmaptest.ValidateProviderScheme(New(HTTPScheme, confmap.ProviderSettings{}))) } func TestInvalidTransport(t *testing.T) { - fp := New("foo") + fp := New("foo", confmap.ProviderSettings{}) _, err := fp.Retrieve(context.Background(), "foo://..", nil) assert.Error(t, err) diff --git a/confmap/provider/internal/configurablehttpprovider/testdata/otel-config.yaml b/confmap/provider/internal/configurablehttpprovider/testdata/otel-config.yaml index 8505ef55936..ac27ba4c851 100644 --- a/confmap/provider/internal/configurablehttpprovider/testdata/otel-config.yaml +++ b/confmap/provider/internal/configurablehttpprovider/testdata/otel-config.yaml @@ -1,6 +1,4 @@ extensions: - memory_ballast: - size_mib: 512 zpages: endpoint: 0.0.0.0:55679 @@ -13,7 +11,7 @@ receivers: processors: batch: memory_limiter: - # 75% of maximum memory up to 4G + # 75% of maximum memory up to 2G limit_mib: 1536 # 25% of limit up to 2G spike_limit_mib: 512 @@ -34,4 +32,4 @@ service: processors: [memory_limiter, batch] exporters: [debug] - extensions: [memory_ballast, zpages] + extensions: [zpages] diff --git a/confmap/provider/internal/package_test.go b/confmap/provider/internal/package_test.go new file mode 100644 index 00000000000..4486cdb28aa --- /dev/null +++ b/confmap/provider/internal/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package internal + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/confmap/provider/yamlprovider/Makefile b/confmap/provider/yamlprovider/Makefile new file mode 100644 index 00000000000..bdd863a203b --- /dev/null +++ b/confmap/provider/yamlprovider/Makefile @@ -0,0 +1 @@ +include ../../../Makefile.Common diff --git a/confmap/provider/yamlprovider/go.mod b/confmap/provider/yamlprovider/go.mod new file mode 100644 index 00000000000..482eaa6531c --- /dev/null +++ b/confmap/provider/yamlprovider/go.mod @@ -0,0 +1,24 @@ +module go.opentelemetry.io/collector/confmap/provider/yamlprovider + +go 1.21 + +require ( + github.com/stretchr/testify v1.8.4 + go.opentelemetry.io/collector/confmap v0.96.0 + go.uber.org/goleak v1.3.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace go.opentelemetry.io/collector/confmap => ../../ diff --git a/confmap/provider/yamlprovider/go.sum b/confmap/provider/yamlprovider/go.sum new file mode 100644 index 00000000000..69f4a4f6724 --- /dev/null +++ b/confmap/provider/yamlprovider/go.sum @@ -0,0 +1,31 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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/confmap/provider/yamlprovider/package_test.go b/confmap/provider/yamlprovider/package_test.go new file mode 100644 index 00000000000..50b62480e04 --- /dev/null +++ b/confmap/provider/yamlprovider/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package yamlprovider + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/confmap/provider/yamlprovider/provider.go b/confmap/provider/yamlprovider/provider.go index 8573318ea55..45fca8a1fc4 100644 --- a/confmap/provider/yamlprovider/provider.go +++ b/confmap/provider/yamlprovider/provider.go @@ -16,6 +16,19 @@ const schemeName = "yaml" type provider struct{} +// NewWithSettings returns a new confmap.Provider that allows to provide yaml bytes. +// +// This Provider supports "yaml" scheme, and can be called with a "uri" that follows: +// +// bytes-uri = "yaml:" yaml-bytes +// +// Examples: +// `yaml:processors::batch::timeout: 2s` +// `yaml:processors::batch/foo::timeout: 3s` +func NewWithSettings(confmap.ProviderSettings) confmap.Provider { + return &provider{} +} + // New returns a new confmap.Provider that allows to provide yaml bytes. // // This Provider supports "yaml" scheme, and can be called with a "uri" that follows: @@ -25,8 +38,9 @@ type provider struct{} // Examples: // `yaml:processors::batch::timeout: 2s` // `yaml:processors::batch/foo::timeout: 3s` +// Deprecated: [v0.94.0] Use NewWithSettings instead. func New() confmap.Provider { - return &provider{} + return NewWithSettings(confmap.ProviderSettings{}) } func (s *provider) Retrieve(_ context.Context, uri string, _ confmap.WatcherFunc) (*confmap.Retrieved, error) { diff --git a/confmap/resolver.go b/confmap/resolver.go index 91bf848d478..f056d18d1ec 100644 --- a/confmap/resolver.go +++ b/confmap/resolver.go @@ -11,20 +11,12 @@ import ( "strings" "go.uber.org/multierr" - - "go.opentelemetry.io/collector/featuregate" ) // follows drive-letter specification: // https://datatracker.ietf.org/doc/html/draft-kerwin-file-scheme-07.html#section-2.2 var driverLetterRegexp = regexp.MustCompile("^[A-z]:") -var _ = featuregate.GlobalRegistry().MustRegister( - "confmap.expandEnabled", - featuregate.StageStable, - featuregate.WithRegisterToVersion("v0.75.0"), - featuregate.WithRegisterDescription("controls whether expanding embedded external config providers URIs")) - // Resolver resolves a configuration as a Conf. type Resolver struct { uris []location diff --git a/confmap/resolver_test.go b/confmap/resolver_test.go index 08e2088dad2..aa1442d161a 100644 --- a/confmap/resolver_test.go +++ b/confmap/resolver_test.go @@ -155,7 +155,7 @@ func TestResolverErrors(t *testing.T) { locations: []string{"mock:", "err:"}, providers: []Provider{ &mockProvider{}, - &mockProvider{scheme: "err", retM: map[string]any{}, closeFunc: func(ctx context.Context) error { return errors.New("close_err") }}, + &mockProvider{scheme: "err", retM: map[string]any{}, closeFunc: func(context.Context) error { return errors.New("close_err") }}, }, expectCloseErr: true, }, @@ -270,7 +270,7 @@ func TestResolver(t *testing.T) { numCalls := atomic.Int32{} resolver, err := NewResolver(ResolverSettings{ URIs: []string{"mock:"}, - Providers: makeMapProvidersMap(&mockProvider{retM: map[string]any{}, closeFunc: func(ctx context.Context) error { + Providers: makeMapProvidersMap(&mockProvider{retM: map[string]any{}, closeFunc: func(context.Context) error { numCalls.Add(1) return nil }}), diff --git a/connector/connector.go b/connector/connector.go index 3a85add44a6..94927092117 100644 --- a/connector/connector.go +++ b/connector/connector.go @@ -5,6 +5,7 @@ package connector // import "go.opentelemetry.io/collector/connector" import ( "context" + "errors" "fmt" "go.uber.org/zap" @@ -13,6 +14,10 @@ import ( "go.opentelemetry.io/collector/consumer" ) +var ( + errNilNextConsumer = errors.New("nil next Consumer") +) + // A Traces connector acts as an exporter from a traces pipeline and a receiver // to one or more traces, metrics, or logs pipelines. // Traces feeds a consumer.Traces, consumer.Metrics, or consumer.Logs with data. @@ -30,13 +35,6 @@ type Traces interface { consumer.Traces } -// TracesRouter feeds the first consumer.Traces in each of the specified pipelines. -// The router will create a fanout consumer for the set of pipelines and return a uuid -type TracesRouter interface { - Consumer(...component.ID) (consumer.Traces, error) - PipelineIDs() []component.ID -} - // A Metrics connector acts as an exporter from a metrics pipeline and a receiver // to one or more traces, metrics, or logs pipelines. // Metrics feeds a consumer.Traces, consumer.Metrics, or consumer.Logs with data. @@ -53,15 +51,9 @@ type Metrics interface { consumer.Metrics } -// MetricsRouter feeds the first consumer.Metrics in each of the specified pipelines. -type MetricsRouter interface { - Consumer(...component.ID) (consumer.Metrics, error) - PipelineIDs() []component.ID -} - // A Logs connector acts as an exporter from a logs pipeline and a receiver // to one or more traces, metrics, or logs pipelines. -// Logs feeds a consumer.Logs, consumer.Metrics, or consumer.Logs with data. +// Logs feeds a consumer.Traces, consumer.Metrics, or consumer.Logs with data. // // Examples: // - Structured logs containing span information could be consumed and emitted as traces. @@ -74,12 +66,6 @@ type Logs interface { consumer.Logs } -// LogsRouter feeds the first consumer.Logs in each of the specified pipelines. -type LogsRouter interface { - Consumer(...component.ID) (consumer.Logs, error) - PipelineIDs() []component.ID -} - // CreateSettings configures Connector creators. type CreateSettings struct { // ID returns the ID of the component that will be created. @@ -475,6 +461,9 @@ func NewBuilder(cfgs map[component.ID]component.Config, factories map[component. // CreateTracesToTraces creates a Traces connector based on the settings and config. func (b *Builder) CreateTracesToTraces(ctx context.Context, set CreateSettings, next consumer.Traces) (Traces, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("connector %q is not configured", set.ID) @@ -491,6 +480,9 @@ func (b *Builder) CreateTracesToTraces(ctx context.Context, set CreateSettings, // CreateTracesToMetrics creates a Traces connector based on the settings and config. func (b *Builder) CreateTracesToMetrics(ctx context.Context, set CreateSettings, next consumer.Metrics) (Traces, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("connector %q is not configured", set.ID) @@ -507,6 +499,9 @@ func (b *Builder) CreateTracesToMetrics(ctx context.Context, set CreateSettings, // CreateTracesToLogs creates a Traces connector based on the settings and config. func (b *Builder) CreateTracesToLogs(ctx context.Context, set CreateSettings, next consumer.Logs) (Traces, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("connector %q is not configured", set.ID) @@ -523,6 +518,9 @@ func (b *Builder) CreateTracesToLogs(ctx context.Context, set CreateSettings, ne // CreateMetricsToTraces creates a Metrics connector based on the settings and config. func (b *Builder) CreateMetricsToTraces(ctx context.Context, set CreateSettings, next consumer.Traces) (Metrics, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("connector %q is not configured", set.ID) @@ -539,6 +537,9 @@ func (b *Builder) CreateMetricsToTraces(ctx context.Context, set CreateSettings, // CreateMetricsToMetrics creates a Metrics connector based on the settings and config. func (b *Builder) CreateMetricsToMetrics(ctx context.Context, set CreateSettings, next consumer.Metrics) (Metrics, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("connector %q is not configured", set.ID) @@ -555,6 +556,9 @@ func (b *Builder) CreateMetricsToMetrics(ctx context.Context, set CreateSettings // CreateMetricsToLogs creates a Metrics connector based on the settings and config. func (b *Builder) CreateMetricsToLogs(ctx context.Context, set CreateSettings, next consumer.Logs) (Metrics, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("connector %q is not configured", set.ID) @@ -571,6 +575,9 @@ func (b *Builder) CreateMetricsToLogs(ctx context.Context, set CreateSettings, n // CreateLogsToTraces creates a Logs connector based on the settings and config. func (b *Builder) CreateLogsToTraces(ctx context.Context, set CreateSettings, next consumer.Traces) (Logs, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("connector %q is not configured", set.ID) @@ -587,6 +594,9 @@ func (b *Builder) CreateLogsToTraces(ctx context.Context, set CreateSettings, ne // CreateLogsToMetrics creates a Logs connector based on the settings and config. func (b *Builder) CreateLogsToMetrics(ctx context.Context, set CreateSettings, next consumer.Metrics) (Logs, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("connector %q is not configured", set.ID) @@ -603,6 +613,9 @@ func (b *Builder) CreateLogsToMetrics(ctx context.Context, set CreateSettings, n // CreateLogsToLogs creates a Logs connector based on the settings and config. func (b *Builder) CreateLogsToLogs(ctx context.Context, set CreateSettings, next consumer.Logs) (Logs, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("connector %q is not configured", set.ID) diff --git a/connector/connector_test.go b/connector/connector_test.go index a2dc1305dfb..7384b50621d 100644 --- a/connector/connector_test.go +++ b/connector/connector_test.go @@ -17,128 +17,123 @@ import ( "go.opentelemetry.io/collector/consumer/consumertest" ) +var ( + testType = component.MustNewType("test") + testID = component.MustNewIDWithName("type", "name") +) + func TestNewFactoryNoOptions(t *testing.T) { - const typeStr = "test" defaultCfg := struct{}{} - factory := NewFactory(typeStr, func() component.Config { return &defaultCfg }) - assert.EqualValues(t, typeStr, factory.Type()) + factory := NewFactory(testType, func() component.Config { return &defaultCfg }) + assert.EqualValues(t, testType, factory.Type()) assert.EqualValues(t, &defaultCfg, factory.CreateDefaultConfig()) - testID := component.NewIDWithName("type", "name") - - _, err := factory.CreateTracesToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err := factory.CreateTracesToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeTraces, component.DataTypeTraces)) - _, err = factory.CreateTracesToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateTracesToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeTraces, component.DataTypeMetrics)) - _, err = factory.CreateTracesToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateTracesToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeTraces, component.DataTypeLogs)) - _, err = factory.CreateMetricsToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateMetricsToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeMetrics, component.DataTypeTraces)) - _, err = factory.CreateMetricsToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateMetricsToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeMetrics, component.DataTypeMetrics)) - _, err = factory.CreateMetricsToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateMetricsToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeMetrics, component.DataTypeLogs)) - _, err = factory.CreateLogsToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateLogsToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeLogs, component.DataTypeTraces)) - _, err = factory.CreateLogsToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateLogsToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeLogs, component.DataTypeMetrics)) - _, err = factory.CreateLogsToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateLogsToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeLogs, component.DataTypeLogs)) } func TestNewFactoryWithSameTypes(t *testing.T) { - const typeStr = "test" defaultCfg := struct{}{} - factory := NewFactory(typeStr, func() component.Config { return &defaultCfg }, + factory := NewFactory(testType, func() component.Config { return &defaultCfg }, WithTracesToTraces(createTracesToTraces, component.StabilityLevelAlpha), WithMetricsToMetrics(createMetricsToMetrics, component.StabilityLevelBeta), WithLogsToLogs(createLogsToLogs, component.StabilityLevelUnmaintained)) - assert.EqualValues(t, typeStr, factory.Type()) + assert.EqualValues(t, testType, factory.Type()) assert.EqualValues(t, &defaultCfg, factory.CreateDefaultConfig()) - testID := component.NewIDWithName("type", "name") - assert.Equal(t, component.StabilityLevelAlpha, factory.TracesToTracesStability()) - _, err := factory.CreateTracesToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err := factory.CreateTracesToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelBeta, factory.MetricsToMetricsStability()) - _, err = factory.CreateMetricsToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateMetricsToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelUnmaintained, factory.LogsToLogsStability()) - _, err = factory.CreateLogsToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateLogsToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) - _, err = factory.CreateTracesToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateTracesToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeTraces, component.DataTypeMetrics)) - _, err = factory.CreateTracesToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateTracesToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeTraces, component.DataTypeLogs)) - _, err = factory.CreateMetricsToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateMetricsToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeMetrics, component.DataTypeTraces)) - _, err = factory.CreateMetricsToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateMetricsToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeMetrics, component.DataTypeLogs)) - _, err = factory.CreateLogsToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateLogsToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeLogs, component.DataTypeTraces)) - _, err = factory.CreateLogsToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateLogsToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeLogs, component.DataTypeMetrics)) } func TestNewFactoryWithTranslateTypes(t *testing.T) { - const typeStr = "test" defaultCfg := struct{}{} - factory := NewFactory(typeStr, func() component.Config { return &defaultCfg }, + factory := NewFactory(testType, func() component.Config { return &defaultCfg }, WithTracesToMetrics(createTracesToMetrics, component.StabilityLevelDevelopment), WithTracesToLogs(createTracesToLogs, component.StabilityLevelAlpha), WithMetricsToTraces(createMetricsToTraces, component.StabilityLevelBeta), WithMetricsToLogs(createMetricsToLogs, component.StabilityLevelStable), WithLogsToTraces(createLogsToTraces, component.StabilityLevelDeprecated), WithLogsToMetrics(createLogsToMetrics, component.StabilityLevelUnmaintained)) - assert.EqualValues(t, typeStr, factory.Type()) + assert.EqualValues(t, testType, factory.Type()) assert.EqualValues(t, &defaultCfg, factory.CreateDefaultConfig()) - testID := component.NewIDWithName("type", "name") - - _, err := factory.CreateTracesToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err := factory.CreateTracesToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeTraces, component.DataTypeTraces)) - _, err = factory.CreateMetricsToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateMetricsToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeMetrics, component.DataTypeMetrics)) - _, err = factory.CreateLogsToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateLogsToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.Equal(t, err, errDataTypes(testID, component.DataTypeLogs, component.DataTypeLogs)) assert.Equal(t, component.StabilityLevelDevelopment, factory.TracesToMetricsStability()) - _, err = factory.CreateTracesToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateTracesToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelAlpha, factory.TracesToLogsStability()) - _, err = factory.CreateTracesToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateTracesToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelBeta, factory.MetricsToTracesStability()) - _, err = factory.CreateMetricsToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateMetricsToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelStable, factory.MetricsToLogsStability()) - _, err = factory.CreateMetricsToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateMetricsToLogs(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelDeprecated, factory.LogsToTracesStability()) - _, err = factory.CreateLogsToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateLogsToTraces(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelUnmaintained, factory.LogsToMetricsStability()) - _, err = factory.CreateLogsToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, nil) + _, err = factory.CreateLogsToMetrics(context.Background(), CreateSettings{ID: testID}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) } func TestNewFactoryWithAllTypes(t *testing.T) { - const typeStr = "test" defaultCfg := struct{}{} - factory := NewFactory(typeStr, func() component.Config { return &defaultCfg }, + factory := NewFactory(testType, func() component.Config { return &defaultCfg }, WithTracesToTraces(createTracesToTraces, component.StabilityLevelAlpha), WithTracesToMetrics(createTracesToMetrics, component.StabilityLevelDevelopment), WithTracesToLogs(createTracesToLogs, component.StabilityLevelAlpha), @@ -148,37 +143,37 @@ func TestNewFactoryWithAllTypes(t *testing.T) { WithLogsToTraces(createLogsToTraces, component.StabilityLevelDeprecated), WithLogsToMetrics(createLogsToMetrics, component.StabilityLevelUnmaintained), WithLogsToLogs(createLogsToLogs, component.StabilityLevelUnmaintained)) - assert.EqualValues(t, typeStr, factory.Type()) + assert.EqualValues(t, testType, factory.Type()) assert.EqualValues(t, &defaultCfg, factory.CreateDefaultConfig()) assert.Equal(t, component.StabilityLevelAlpha, factory.TracesToTracesStability()) - _, err := factory.CreateTracesToTraces(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err := factory.CreateTracesToTraces(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelDevelopment, factory.TracesToMetricsStability()) - _, err = factory.CreateTracesToMetrics(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err = factory.CreateTracesToMetrics(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelAlpha, factory.TracesToLogsStability()) - _, err = factory.CreateTracesToLogs(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err = factory.CreateTracesToLogs(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelBeta, factory.MetricsToTracesStability()) - _, err = factory.CreateMetricsToTraces(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err = factory.CreateMetricsToTraces(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelBeta, factory.MetricsToMetricsStability()) - _, err = factory.CreateMetricsToMetrics(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err = factory.CreateMetricsToMetrics(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelStable, factory.MetricsToLogsStability()) - _, err = factory.CreateMetricsToLogs(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err = factory.CreateMetricsToLogs(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelDeprecated, factory.LogsToTracesStability()) - _, err = factory.CreateLogsToTraces(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err = factory.CreateLogsToTraces(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelUnmaintained, factory.LogsToMetricsStability()) - _, err = factory.CreateLogsToMetrics(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err = factory.CreateLogsToMetrics(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelUnmaintained, factory.LogsToLogsStability()) - _, err = factory.CreateLogsToLogs(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err = factory.CreateLogsToLogs(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) } @@ -189,8 +184,8 @@ func TestMakeFactoryMap(t *testing.T) { out map[component.Type]Factory } - p1 := NewFactory("p1", nil) - p2 := NewFactory("p2", nil) + p1 := NewFactory(component.MustNewType("p1"), nil) + p2 := NewFactory(component.MustNewType("p2"), nil) testCases := []testCase{ { name: "different names", @@ -202,7 +197,7 @@ func TestMakeFactoryMap(t *testing.T) { }, { name: "same name", - in: []Factory{p1, p2, NewFactory("p1", nil)}, + in: []Factory{p1, p2, NewFactory(component.MustNewType("p1"), nil)}, }, } @@ -223,9 +218,9 @@ func TestMakeFactoryMap(t *testing.T) { func TestBuilder(t *testing.T) { defaultCfg := struct{}{} factories, err := MakeFactoryMap([]Factory{ - NewFactory("err", nil), + NewFactory(component.MustNewType("err"), nil), NewFactory( - "all", + component.MustNewType("all"), func() component.Config { return &defaultCfg }, WithTracesToTraces(createTracesToTraces, component.StabilityLevelDevelopment), WithTracesToMetrics(createTracesToMetrics, component.StabilityLevelDevelopment), @@ -241,37 +236,62 @@ func TestBuilder(t *testing.T) { require.NoError(t, err) testCases := []struct { - name string - id component.ID - err func(component.DataType, component.DataType) string + name string + id component.ID + err func(component.DataType, component.DataType) string + nextTraces consumer.Traces + nextLogs consumer.Logs + nextMetrics consumer.Metrics }{ { name: "unknown", - id: component.NewID("unknown"), - err: func(_, _ component.DataType) string { + id: component.MustNewID("unknown"), + err: func(component.DataType, component.DataType) string { return "connector factory not available for: \"unknown\"" }, + nextTraces: consumertest.NewNop(), + nextLogs: consumertest.NewNop(), + nextMetrics: consumertest.NewNop(), }, { name: "err", - id: component.NewID("err"), + id: component.MustNewID("err"), err: func(expType, rcvType component.DataType) string { return fmt.Sprintf("connector \"err\" cannot connect from %s to %s: telemetry type is not supported", expType, rcvType) }, + nextTraces: consumertest.NewNop(), + nextLogs: consumertest.NewNop(), + nextMetrics: consumertest.NewNop(), }, { name: "all", - id: component.NewID("all"), - err: func(_, _ component.DataType) string { + id: component.MustNewID("all"), + err: func(component.DataType, component.DataType) string { return "" }, + nextTraces: consumertest.NewNop(), + nextLogs: consumertest.NewNop(), + nextMetrics: consumertest.NewNop(), }, { name: "all/named", - id: component.NewIDWithName("all", "named"), - err: func(_, _ component.DataType) string { + id: component.MustNewIDWithName("all", "named"), + err: func(component.DataType, component.DataType) string { return "" }, + nextTraces: consumertest.NewNop(), + nextLogs: consumertest.NewNop(), + nextMetrics: consumertest.NewNop(), + }, + { + name: "no next consumer", + id: component.MustNewID("unknown"), + err: func(_, _ component.DataType) string { + return "nil next Consumer" + }, + nextTraces: nil, + nextLogs: nil, + nextMetrics: nil, }, } @@ -280,7 +300,7 @@ func TestBuilder(t *testing.T) { cfgs := map[component.ID]component.Config{tt.id: defaultCfg} b := NewBuilder(cfgs, factories) - t2t, err := b.CreateTracesToTraces(context.Background(), createSettings(tt.id), nil) + t2t, err := b.CreateTracesToTraces(context.Background(), createSettings(tt.id), tt.nextTraces) if expectedErr := tt.err(component.DataTypeTraces, component.DataTypeTraces); expectedErr != "" { assert.EqualError(t, err, expectedErr) assert.Nil(t, t2t) @@ -288,7 +308,7 @@ func TestBuilder(t *testing.T) { assert.NoError(t, err) assert.Equal(t, nopInstance, t2t) } - t2m, err := b.CreateTracesToMetrics(context.Background(), createSettings(tt.id), nil) + t2m, err := b.CreateTracesToMetrics(context.Background(), createSettings(tt.id), tt.nextMetrics) if expectedErr := tt.err(component.DataTypeTraces, component.DataTypeMetrics); expectedErr != "" { assert.EqualError(t, err, expectedErr) assert.Nil(t, t2m) @@ -296,7 +316,7 @@ func TestBuilder(t *testing.T) { assert.NoError(t, err) assert.Equal(t, nopInstance, t2m) } - t2l, err := b.CreateTracesToLogs(context.Background(), createSettings(tt.id), nil) + t2l, err := b.CreateTracesToLogs(context.Background(), createSettings(tt.id), tt.nextLogs) if expectedErr := tt.err(component.DataTypeTraces, component.DataTypeLogs); expectedErr != "" { assert.EqualError(t, err, expectedErr) assert.Nil(t, t2l) @@ -305,7 +325,7 @@ func TestBuilder(t *testing.T) { assert.Equal(t, nopInstance, t2l) } - m2t, err := b.CreateMetricsToTraces(context.Background(), createSettings(tt.id), nil) + m2t, err := b.CreateMetricsToTraces(context.Background(), createSettings(tt.id), tt.nextTraces) if expectedErr := tt.err(component.DataTypeMetrics, component.DataTypeTraces); expectedErr != "" { assert.EqualError(t, err, expectedErr) assert.Nil(t, m2t) @@ -314,7 +334,7 @@ func TestBuilder(t *testing.T) { assert.Equal(t, nopInstance, m2t) } - m2m, err := b.CreateMetricsToMetrics(context.Background(), createSettings(tt.id), nil) + m2m, err := b.CreateMetricsToMetrics(context.Background(), createSettings(tt.id), tt.nextMetrics) if expectedErr := tt.err(component.DataTypeMetrics, component.DataTypeMetrics); expectedErr != "" { assert.EqualError(t, err, expectedErr) assert.Nil(t, m2m) @@ -323,7 +343,7 @@ func TestBuilder(t *testing.T) { assert.Equal(t, nopInstance, m2m) } - m2l, err := b.CreateMetricsToLogs(context.Background(), createSettings(tt.id), nil) + m2l, err := b.CreateMetricsToLogs(context.Background(), createSettings(tt.id), tt.nextLogs) if expectedErr := tt.err(component.DataTypeMetrics, component.DataTypeLogs); expectedErr != "" { assert.EqualError(t, err, expectedErr) assert.Nil(t, m2l) @@ -332,7 +352,7 @@ func TestBuilder(t *testing.T) { assert.Equal(t, nopInstance, m2l) } - l2t, err := b.CreateLogsToTraces(context.Background(), createSettings(tt.id), nil) + l2t, err := b.CreateLogsToTraces(context.Background(), createSettings(tt.id), tt.nextTraces) if expectedErr := tt.err(component.DataTypeLogs, component.DataTypeTraces); expectedErr != "" { assert.EqualError(t, err, expectedErr) assert.Nil(t, l2t) @@ -341,7 +361,7 @@ func TestBuilder(t *testing.T) { assert.Equal(t, nopInstance, l2t) } - l2m, err := b.CreateLogsToMetrics(context.Background(), createSettings(tt.id), nil) + l2m, err := b.CreateLogsToMetrics(context.Background(), createSettings(tt.id), tt.nextMetrics) if expectedErr := tt.err(component.DataTypeLogs, component.DataTypeMetrics); expectedErr != "" { assert.EqualError(t, err, expectedErr) assert.Nil(t, l2m) @@ -350,7 +370,7 @@ func TestBuilder(t *testing.T) { assert.Equal(t, nopInstance, l2m) } - l2l, err := b.CreateLogsToLogs(context.Background(), createSettings(tt.id), nil) + l2l, err := b.CreateLogsToLogs(context.Background(), createSettings(tt.id), tt.nextLogs) if expectedErr := tt.err(component.DataTypeLogs, component.DataTypeLogs); expectedErr != "" { assert.EqualError(t, err, expectedErr) assert.Nil(t, l2l) @@ -366,7 +386,7 @@ func TestBuilderMissingConfig(t *testing.T) { defaultCfg := struct{}{} factories, err := MakeFactoryMap([]Factory{ NewFactory( - "all", + component.MustNewType("all"), func() component.Config { return &defaultCfg }, WithTracesToTraces(createTracesToTraces, component.StabilityLevelDevelopment), WithTracesToMetrics(createTracesToMetrics, component.StabilityLevelDevelopment), @@ -383,57 +403,57 @@ func TestBuilderMissingConfig(t *testing.T) { require.NoError(t, err) bErr := NewBuilder(map[component.ID]component.Config{}, factories) - missingID := component.NewIDWithName("all", "missing") + missingID := component.MustNewIDWithName("all", "missing") - t2t, err := bErr.CreateTracesToTraces(context.Background(), createSettings(missingID), nil) + t2t, err := bErr.CreateTracesToTraces(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "connector \"all/missing\" is not configured") assert.Nil(t, t2t) - t2m, err := bErr.CreateTracesToMetrics(context.Background(), createSettings(missingID), nil) + t2m, err := bErr.CreateTracesToMetrics(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "connector \"all/missing\" is not configured") assert.Nil(t, t2m) - t2l, err := bErr.CreateTracesToLogs(context.Background(), createSettings(missingID), nil) + t2l, err := bErr.CreateTracesToLogs(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "connector \"all/missing\" is not configured") assert.Nil(t, t2l) - m2t, err := bErr.CreateMetricsToTraces(context.Background(), createSettings(missingID), nil) + m2t, err := bErr.CreateMetricsToTraces(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "connector \"all/missing\" is not configured") assert.Nil(t, m2t) - m2m, err := bErr.CreateMetricsToMetrics(context.Background(), createSettings(missingID), nil) + m2m, err := bErr.CreateMetricsToMetrics(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "connector \"all/missing\" is not configured") assert.Nil(t, m2m) - m2l, err := bErr.CreateMetricsToLogs(context.Background(), createSettings(missingID), nil) + m2l, err := bErr.CreateMetricsToLogs(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "connector \"all/missing\" is not configured") assert.Nil(t, m2l) - l2t, err := bErr.CreateLogsToTraces(context.Background(), createSettings(missingID), nil) + l2t, err := bErr.CreateLogsToTraces(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "connector \"all/missing\" is not configured") assert.Nil(t, l2t) - l2m, err := bErr.CreateLogsToMetrics(context.Background(), createSettings(missingID), nil) + l2m, err := bErr.CreateLogsToMetrics(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "connector \"all/missing\" is not configured") assert.Nil(t, l2m) - l2l, err := bErr.CreateLogsToLogs(context.Background(), createSettings(missingID), nil) + l2l, err := bErr.CreateLogsToLogs(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "connector \"all/missing\" is not configured") assert.Nil(t, l2l) } func TestBuilderGetters(t *testing.T) { - factories, err := MakeFactoryMap([]Factory{NewFactory("foo", nil)}...) + factories, err := MakeFactoryMap([]Factory{NewFactory(component.MustNewType("foo"), nil)}...) require.NoError(t, err) - cfgs := map[component.ID]component.Config{component.NewID("foo"): struct{}{}} + cfgs := map[component.ID]component.Config{component.MustNewID("foo"): struct{}{}} b := NewBuilder(cfgs, factories) - assert.True(t, b.IsConfigured(component.NewID("foo"))) - assert.False(t, b.IsConfigured(component.NewID("bar"))) + assert.True(t, b.IsConfigured(component.MustNewID("foo"))) + assert.False(t, b.IsConfigured(component.MustNewID("bar"))) - assert.NotNil(t, b.Factory(component.NewID("foo").Type())) - assert.Nil(t, b.Factory(component.NewID("bar").Type())) + assert.NotNil(t, b.Factory(component.MustNewID("foo").Type())) + assert.Nil(t, b.Factory(component.MustNewID("bar").Type())) } var nopInstance = &nopConnector{ diff --git a/connector/connectortest/connector.go b/connector/connectortest/connector.go index 137a353423c..d30fb65b6a5 100644 --- a/connector/connectortest/connector.go +++ b/connector/connectortest/connector.go @@ -13,11 +13,12 @@ import ( "go.opentelemetry.io/collector/consumer/consumertest" ) -const typeStr = "nop" +var nopType = component.MustNewType("nop") // NewNopCreateSettings returns a new nop settings for Create* functions. func NewNopCreateSettings() connector.CreateSettings { return connector.CreateSettings{ + ID: component.NewID(nopType), TelemetrySettings: componenttest.NewNopTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo(), } @@ -28,7 +29,7 @@ type nopConfig struct{} // NewNopFactory returns a connector.Factory that constructs nop processors. func NewNopFactory() connector.Factory { return connector.NewFactory( - "nop", + nopType, func() component.Config { return &nopConfig{} }, @@ -93,8 +94,8 @@ func NewNopBuilder() *connector.Builder { // Use a different ID than receivertest and exportertest to avoid ambiguous // configuration scenarios. Ambiguous IDs are detected in the 'otelcol' package, // but lower level packages such as 'service' assume that IDs are disambiguated. - connID := component.NewIDWithName(typeStr, "conn") + connID := component.NewIDWithName(nopType, "conn") return connector.NewBuilder( map[component.ID]component.Config{connID: nopFactory.CreateDefaultConfig()}, - map[component.Type]connector.Factory{typeStr: nopFactory}) + map[component.Type]connector.Factory{nopType: nopFactory}) } diff --git a/connector/connectortest/connector_test.go b/connector/connectortest/connector_test.go index d8db553d9a1..4a2894f8544 100644 --- a/connector/connectortest/connector_test.go +++ b/connector/connectortest/connector_test.go @@ -21,7 +21,7 @@ import ( func TestNewNopConnectorFactory(t *testing.T) { factory := NewNopFactory() require.NotNil(t, factory) - assert.Equal(t, component.Type("nop"), factory.Type()) + assert.Equal(t, component.MustNewType("nop"), factory.Type()) cfg := factory.CreateDefaultConfig() assert.Equal(t, &nopConfig{}, cfg) @@ -87,7 +87,7 @@ func TestNewNopBuilder(t *testing.T) { factory := NewNopFactory() cfg := factory.CreateDefaultConfig() set := NewNopCreateSettings() - set.ID = component.NewIDWithName(typeStr, "conn") + set.ID = component.NewIDWithName(nopType, "conn") tracesToTraces, err := factory.CreateTracesToTraces(context.Background(), set, cfg, consumertest.NewNop()) require.NoError(t, err) diff --git a/connector/connectortest/package_test.go b/connector/connectortest/package_test.go new file mode 100644 index 00000000000..3d343e0071a --- /dev/null +++ b/connector/connectortest/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package connectortest + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/connector/connectortest/router.go b/connector/connectortest/router.go deleted file mode 100644 index 390e9502c59..00000000000 --- a/connector/connectortest/router.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package connectortest // import "go.opentelemetry.io/collector/connector/connectortest" - -import ( - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/connector" - "go.opentelemetry.io/collector/consumer" - "go.opentelemetry.io/collector/consumer/consumertest" - "go.opentelemetry.io/collector/internal/fanoutconsumer" -) - -type TracesRouterOption struct { - id component.ID - cons consumer.Traces -} - -// WithNopTraces creates a nop consumer for a connector.TracesRouter -func WithNopTraces(id component.ID) TracesRouterOption { - return TracesRouterOption{id: id, cons: consumertest.NewNop()} -} - -// WithTracesSink adds a consumer to a connector.TracesRouter -func WithTracesSink(id component.ID, sink *consumertest.TracesSink) TracesRouterOption { - return TracesRouterOption{id: id, cons: sink} -} - -// NewTracesRouter returns a connector.TracesRouter with sinks based on the options provided -func NewTracesRouter(opts ...TracesRouterOption) connector.TracesRouter { - consumers := make(map[component.ID]consumer.Traces) - for _, opt := range opts { - consumers[opt.id] = opt.cons - } - return fanoutconsumer.NewTracesRouter(consumers).(connector.TracesRouter) -} - -type MetricsRouterOption struct { - id component.ID - cons consumer.Metrics -} - -// WithNopMetrics creates a nop consumer for a connector.MetricsRouter -func WithNopMetrics(id component.ID) MetricsRouterOption { - return MetricsRouterOption{id: id, cons: consumertest.NewNop()} -} - -// WithMetricsSink adds a consumer to a connector.MetricsRouter -func WithMetricsSink(id component.ID, sink *consumertest.MetricsSink) MetricsRouterOption { - return MetricsRouterOption{id: id, cons: sink} -} - -// NewMetricsRouter returns a connector.MetricsRouter with sinks based on the options provided -func NewMetricsRouter(opts ...MetricsRouterOption) connector.MetricsRouter { - consumers := make(map[component.ID]consumer.Metrics) - for _, opt := range opts { - consumers[opt.id] = opt.cons - } - return fanoutconsumer.NewMetricsRouter(consumers).(connector.MetricsRouter) -} - -type LogsRouterOption struct { - id component.ID - cons consumer.Logs -} - -// WithNopLogs creates a nop consumer for a connector.LogsRouter -func WithNopLogs(id component.ID) LogsRouterOption { - return LogsRouterOption{id: id, cons: consumertest.NewNop()} -} - -// WithLogsSink adds a consumer to a connector.LogsRouter -func WithLogsSink(id component.ID, sink *consumertest.LogsSink) LogsRouterOption { - return LogsRouterOption{id: id, cons: sink} -} - -// NewLogsRouter returns a connector.LogsRouter with sinks based on the options provided -func NewLogsRouter(opts ...LogsRouterOption) connector.LogsRouter { - consumers := make(map[component.ID]consumer.Logs) - for _, opt := range opts { - consumers[opt.id] = opt.cons - } - return fanoutconsumer.NewLogsRouter(consumers).(connector.LogsRouter) -} diff --git a/connector/connectortest/router_test.go b/connector/connectortest/router_test.go deleted file mode 100644 index ba7cd30fc40..00000000000 --- a/connector/connectortest/router_test.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package connectortest - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/consumer" - "go.opentelemetry.io/collector/consumer/consumertest" - "go.opentelemetry.io/collector/internal/testdata" -) - -func TestTracesRouterWithNop(t *testing.T) { - tr := NewTracesRouter( - WithNopTraces(component.NewIDWithName(component.DataTypeTraces, "0")), - WithNopTraces(component.NewIDWithName(component.DataTypeTraces, "1")), - ) - - td := testdata.GenerateTraces(1) - err := tr.(consumer.Traces).ConsumeTraces(context.Background(), td) - - require.NoError(t, err) -} - -func TestTracesRouterWithSink(t *testing.T) { - var sink0, sink1 consumertest.TracesSink - - tr := NewTracesRouter( - WithTracesSink(component.NewIDWithName(component.DataTypeTraces, "0"), &sink0), - WithTracesSink(component.NewIDWithName(component.DataTypeTraces, "1"), &sink1), - ) - - require.Equal(t, 0, sink0.SpanCount()) - require.Equal(t, 0, sink1.SpanCount()) - - td := testdata.GenerateTraces(1) - err := tr.(consumer.Traces).ConsumeTraces(context.Background(), td) - - require.NoError(t, err) - require.Equal(t, 1, sink0.SpanCount()) - require.Equal(t, 1, sink1.SpanCount()) -} - -func TestMetricsRouterWithNop(t *testing.T) { - mr := NewMetricsRouter( - WithNopMetrics(component.NewIDWithName(component.DataTypeMetrics, "0")), - WithNopMetrics(component.NewIDWithName(component.DataTypeMetrics, "1")), - ) - - md := testdata.GenerateMetrics(1) - err := mr.(consumer.Metrics).ConsumeMetrics(context.Background(), md) - - require.NoError(t, err) -} - -func TestMetricsRouterWithSink(t *testing.T) { - var sink0, sink1 consumertest.MetricsSink - - mr := NewMetricsRouter( - WithMetricsSink(component.NewIDWithName(component.DataTypeMetrics, "0"), &sink0), - WithMetricsSink(component.NewIDWithName(component.DataTypeMetrics, "1"), &sink1), - ) - - require.Len(t, sink0.AllMetrics(), 0) - require.Len(t, sink1.AllMetrics(), 0) - - md := testdata.GenerateMetrics(1) - err := mr.(consumer.Metrics).ConsumeMetrics(context.Background(), md) - - require.NoError(t, err) - require.Len(t, sink0.AllMetrics(), 1) - require.Len(t, sink1.AllMetrics(), 1) -} - -func TestLogsRouterWithNop(t *testing.T) { - lr := NewLogsRouter( - WithNopLogs(component.NewIDWithName(component.DataTypeLogs, "0")), - WithNopLogs(component.NewIDWithName(component.DataTypeLogs, "1")), - ) - - ld := testdata.GenerateLogs(1) - err := lr.(consumer.Logs).ConsumeLogs(context.Background(), ld) - - require.NoError(t, err) -} - -func TestLogsRouterWithSink(t *testing.T) { - var sink0, sink1 consumertest.LogsSink - - lr := NewLogsRouter( - WithLogsSink(component.NewIDWithName(component.DataTypeLogs, "0"), &sink0), - WithLogsSink(component.NewIDWithName(component.DataTypeLogs, "1"), &sink1), - ) - - require.Equal(t, 0, sink0.LogRecordCount()) - require.Equal(t, 0, sink1.LogRecordCount()) - - ld := testdata.GenerateLogs(1) - err := lr.(consumer.Logs).ConsumeLogs(context.Background(), ld) - - require.NoError(t, err) - require.Equal(t, 1, sink0.LogRecordCount()) - require.Equal(t, 1, sink1.LogRecordCount()) -} diff --git a/connector/forwardconnector/README.md b/connector/forwardconnector/README.md index ffe666e76e6..fad3289c1e2 100644 --- a/connector/forwardconnector/README.md +++ b/connector/forwardconnector/README.md @@ -1,20 +1,29 @@ # Forward Connector -| Status | | -|------------------------- |---------------------------------------------------------- | -| Stability | [beta] | -| Supported pipeline types | See [Supported Pipeline Types](#supported-pipeline-types) | -| Distributions | [core, contrib] | + +| Status | | +| ------------- |-----------| +| Distributions | [core], [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aconnector%2Fforward%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aconnector%2Fforward) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aconnector%2Fforward%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aconnector%2Fforward) | -The `forward` connector can merge or fork pipelines of the same type. +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib ## Supported Pipeline Types -| [Exporter Pipeline Type] | [Receiver Pipeline Type] | -| ------------------------ | ------------------------ | -| traces | traces | -| metrics | metrics | -| logs | logs | +| [Exporter Pipeline Type] | [Receiver Pipeline Type] | [Stability Level] | +| ------------------------ | ------------------------ | ----------------- | +| traces | traces | [beta] | +| metrics | metrics | [beta] | +| logs | logs | [beta] | + +[Exporter Pipeline Type]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/connector/README.md#exporter-pipeline-type +[Receiver Pipeline Type]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/connector/README.md#receiver-pipeline-type +[Stability Level]: https://github.com/open-telemetry/opentelemetry-collector#stability-levels + + +The `forward` connector can merge or fork pipelines of the same type. ## Configuration @@ -122,9 +131,4 @@ service: # exporters: [logging] ``` -[beta]:https://github.com/open-telemetry/opentelemetry-collector#beta -[core]:https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol -[contrib]:https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib -[Connectors README]:https://github.com/open-telemetry/opentelemetry-collector/blob/main/connector/README.md -[Exporter Pipeline Type]:https://github.com/open-telemetry/opentelemetry-collector/blob/main/connector/README.md#exporter-pipeline-type -[Receiver Pipeline Type]:https://github.com/open-telemetry/opentelemetry-collector/blob/main/connector/README.md#receiver-pipeline-type +[Connectors README]:../README.md diff --git a/connector/forwardconnector/doc.go b/connector/forwardconnector/doc.go index 656e06d94bd..04c6ee06bdc 100644 --- a/connector/forwardconnector/doc.go +++ b/connector/forwardconnector/doc.go @@ -1,5 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +//go:generate mdatagen metadata.yaml + // Package forwardconnector passes signals from one pipeline to another. package forwardconnector // import "go.opentelemetry.io/collector/connector/forwardconnector" diff --git a/connector/forwardconnector/forward.go b/connector/forwardconnector/forward.go index 21ef6a15a94..a34cd15bd09 100644 --- a/connector/forwardconnector/forward.go +++ b/connector/forwardconnector/forward.go @@ -8,27 +8,26 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/connector" + "go.opentelemetry.io/collector/connector/forwardconnector/internal/metadata" "go.opentelemetry.io/collector/consumer" ) -const ( - typeStr = "forward" -) - // NewFactory returns a connector.Factory. func NewFactory() connector.Factory { return connector.NewFactory( - typeStr, + metadata.Type, createDefaultConfig, - connector.WithTracesToTraces(createTracesToTraces, component.StabilityLevelBeta), - connector.WithMetricsToMetrics(createMetricsToMetrics, component.StabilityLevelBeta), - connector.WithLogsToLogs(createLogsToLogs, component.StabilityLevelBeta), + connector.WithTracesToTraces(createTracesToTraces, metadata.TracesToTracesStability), + connector.WithMetricsToMetrics(createMetricsToMetrics, metadata.MetricsToMetricsStability), + connector.WithLogsToLogs(createLogsToLogs, metadata.LogsToLogsStability), ) } +type Config struct{} + // createDefaultConfig creates the default configuration. func createDefaultConfig() component.Config { - return &struct{}{} + return &Config{} } // createTracesToTraces creates a trace receiver based on provided config. diff --git a/connector/forwardconnector/forward_test.go b/connector/forwardconnector/forward_test.go index 3783a1f59a0..3ce18c4f530 100644 --- a/connector/forwardconnector/forward_test.go +++ b/connector/forwardconnector/forward_test.go @@ -19,7 +19,7 @@ import ( func TestForward(t *testing.T) { f := NewFactory() cfg := f.CreateDefaultConfig() - assert.Equal(t, &struct{}{}, cfg) + assert.Equal(t, &Config{}, cfg) ctx := context.Background() set := connectortest.NewNopCreateSettings() diff --git a/connector/forwardconnector/go.mod b/connector/forwardconnector/go.mod index 08087bfc876..656652fbfe1 100644 --- a/connector/forwardconnector/go.mod +++ b/connector/forwardconnector/go.mod @@ -1,44 +1,55 @@ module go.opentelemetry.io/collector/connector/forwardconnector -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/connector v0.85.0 - go.opentelemetry.io/collector/consumer v0.85.0 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/connector v0.96.0 + go.opentelemetry.io/collector/consumer v0.96.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 ) require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/collector v0.85.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 // indirect - go.opentelemetry.io/collector/confmap v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector v0.96.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/confmap v0.96.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -48,20 +59,8 @@ replace go.opentelemetry.io/collector/component => ../../component replace go.opentelemetry.io/collector/connector => ../ -replace go.opentelemetry.io/collector/exporter => ../../exporter - -replace go.opentelemetry.io/collector/extension => ../../extension - replace go.opentelemetry.io/collector/pdata => ../../pdata -replace go.opentelemetry.io/collector/processor => ../../processor - -replace go.opentelemetry.io/collector/receiver => ../../receiver - -replace go.opentelemetry.io/collector/semconv => ../../semconv - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension - replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/consumer => ../../consumer @@ -73,8 +72,4 @@ retract ( v0.69.0 // Release failed, use v0.69.1 ) -replace go.opentelemetry.io/collector/config/confignet => ../../config/confignet - replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry - -replace go.opentelemetry.io/collector/service => ../../service diff --git a/connector/forwardconnector/go.sum b/connector/forwardconnector/go.sum index 4b853ef5c40..06616cda85d 100644 --- a/connector/forwardconnector/go.sum +++ b/connector/forwardconnector/go.sum @@ -1,15 +1,25 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= @@ -19,14 +29,14 @@ github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NI github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -36,24 +46,40 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -63,20 +89,20 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -85,15 +111,16 @@ 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-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= 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/connector/forwardconnector/internal/metadata/generated_status.go b/connector/forwardconnector/internal/metadata/generated_status.go new file mode 100644 index 00000000000..201502cd3e2 --- /dev/null +++ b/connector/forwardconnector/internal/metadata/generated_status.go @@ -0,0 +1,29 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("forward") + scopeName = "go.opentelemetry.io/collector/connector/forwardconnector" +) + +const ( + TracesToTracesStability = component.StabilityLevelBeta + MetricsToMetricsStability = component.StabilityLevelBeta + LogsToLogsStability = component.StabilityLevelBeta +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} diff --git a/connector/forwardconnector/metadata.yaml b/connector/forwardconnector/metadata.yaml new file mode 100644 index 00000000000..41fc2707019 --- /dev/null +++ b/connector/forwardconnector/metadata.yaml @@ -0,0 +1,7 @@ +type: forward + +status: + class: connector + stability: + beta: [traces_to_traces, metrics_to_metrics, logs_to_logs] + distributions: [core, contrib] diff --git a/connector/forwardconnector/package_test.go b/connector/forwardconnector/package_test.go new file mode 100644 index 00000000000..54cc0fd73ce --- /dev/null +++ b/connector/forwardconnector/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package forwardconnector + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/connector/go.mod b/connector/go.mod index 7d24c5e397b..3e1b6496f98 100644 --- a/connector/go.mod +++ b/connector/go.mod @@ -1,43 +1,54 @@ module go.opentelemetry.io/collector/connector -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/consumer v0.85.0 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.uber.org/zap v1.26.0 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/consumer v0.96.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.uber.org/goleak v1.3.0 + go.uber.org/multierr v1.11.0 + go.uber.org/zap v1.27.0 ) require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 // indirect - go.opentelemetry.io/collector/confmap v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect - go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/confmap v0.96.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -51,22 +62,6 @@ replace go.opentelemetry.io/collector/confmap => ../confmap replace go.opentelemetry.io/collector/consumer => ../consumer -replace go.opentelemetry.io/collector/extension => ../extension - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../extension/zpagesextension - replace go.opentelemetry.io/collector/featuregate => ../featuregate replace go.opentelemetry.io/collector/pdata => ../pdata - -replace go.opentelemetry.io/collector/processor => ../processor - -replace go.opentelemetry.io/collector/receiver => ../receiver - -replace go.opentelemetry.io/collector/semconv => ../semconv - -replace go.opentelemetry.io/collector/exporter => ../exporter - -replace go.opentelemetry.io/collector/config/confignet => ../config/confignet - -replace go.opentelemetry.io/collector/service => ../service diff --git a/connector/go.sum b/connector/go.sum index 4b853ef5c40..06616cda85d 100644 --- a/connector/go.sum +++ b/connector/go.sum @@ -1,15 +1,25 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= @@ -19,14 +29,14 @@ github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NI github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -36,24 +46,40 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -63,20 +89,20 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -85,15 +111,16 @@ 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-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= 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/connector/logs_router.go b/connector/logs_router.go new file mode 100644 index 00000000000..e5594327ffc --- /dev/null +++ b/connector/logs_router.go @@ -0,0 +1,75 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package connector // import "go.opentelemetry.io/collector/connector" + +import ( + "fmt" + + "go.uber.org/multierr" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/internal/fanoutconsumer" +) + +// Deprecated: [v0.92.0] use LogsRouterAndConsumer +type LogsRouter interface { + Consumer(...component.ID) (consumer.Logs, error) + PipelineIDs() []component.ID +} + +// LogsRouterAndConsumer feeds the first consumer.Logs in each of the specified pipelines. +type LogsRouterAndConsumer interface { + consumer.Logs + Consumer(...component.ID) (consumer.Logs, error) + PipelineIDs() []component.ID + privateFunc() +} + +type logsRouter struct { + consumer.Logs + consumers map[component.ID]consumer.Logs +} + +func NewLogsRouter(cm map[component.ID]consumer.Logs) LogsRouterAndConsumer { + consumers := make([]consumer.Logs, 0, len(cm)) + for _, consumer := range cm { + consumers = append(consumers, consumer) + } + return &logsRouter{ + Logs: fanoutconsumer.NewLogs(consumers), + consumers: cm, + } +} + +func (r *logsRouter) PipelineIDs() []component.ID { + ids := make([]component.ID, 0, len(r.consumers)) + for id := range r.consumers { + ids = append(ids, id) + } + return ids +} + +func (r *logsRouter) Consumer(pipelineIDs ...component.ID) (consumer.Logs, error) { + if len(pipelineIDs) == 0 { + return nil, fmt.Errorf("missing consumers") + } + consumers := make([]consumer.Logs, 0, len(pipelineIDs)) + var errors error + for _, pipelineID := range pipelineIDs { + c, ok := r.consumers[pipelineID] + if ok { + consumers = append(consumers, c) + } else { + errors = multierr.Append(errors, fmt.Errorf("missing consumer: %q", pipelineID)) + } + } + if errors != nil { + // TODO potentially this could return a NewLogs with the valid consumers + return nil, errors + } + return fanoutconsumer.NewLogs(consumers), nil +} + +func (r *logsRouter) privateFunc() {} diff --git a/connector/logs_router_test.go b/connector/logs_router_test.go new file mode 100644 index 00000000000..accce0a03cd --- /dev/null +++ b/connector/logs_router_test.go @@ -0,0 +1,156 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package connector + +import ( + "context" + "fmt" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/internal/testdata" + "go.opentelemetry.io/collector/pdata/plog" +) + +type mutatingLogsSink struct { + *consumertest.LogsSink +} + +func (mts *mutatingLogsSink) Capabilities() consumer.Capabilities { + return consumer.Capabilities{MutatesData: true} +} + +func TestLogsRouterMultiplexing(t *testing.T) { + var max = 20 + for numIDs := 1; numIDs < max; numIDs++ { + for numCons := 1; numCons < max; numCons++ { + for numLogs := 1; numLogs < max; numLogs++ { + t.Run( + fmt.Sprintf("%d-ids/%d-cons/%d-logs", numIDs, numCons, numLogs), + fuzzLogs(numIDs, numCons, numLogs), + ) + } + } + } +} + +func fuzzLogs(numIDs, numCons, numLogs int) func(*testing.T) { + return func(t *testing.T) { + allIDs := make([]component.ID, 0, numCons) + allCons := make([]consumer.Logs, 0, numCons) + allConsMap := make(map[component.ID]consumer.Logs) + + // If any consumer is mutating, the router must report mutating + for i := 0; i < numCons; i++ { + allIDs = append(allIDs, component.MustNewIDWithName("sink", strconv.Itoa(numCons))) + // Random chance for each consumer to be mutating + if (numCons+numLogs+i)%4 == 0 { + allCons = append(allCons, &mutatingLogsSink{LogsSink: new(consumertest.LogsSink)}) + } else { + allCons = append(allCons, new(consumertest.LogsSink)) + } + allConsMap[allIDs[i]] = allCons[i] + } + + r := NewLogsRouter(allConsMap) + ld := testdata.GenerateLogs(1) + + // Keep track of how many logs each consumer should receive. + // This will be validated after every call to RouteLogs. + expected := make(map[component.ID]int, numCons) + + for i := 0; i < numLogs; i++ { + // Build a random set of ids (no duplicates) + randCons := make(map[component.ID]bool, numIDs) + for j := 0; j < numIDs; j++ { + // This number should be pretty random and less than numCons + conNum := (numCons + numIDs + i + j) % numCons + randCons[allIDs[conNum]] = true + } + + // Convert to slice, update expectations + conIDs := make([]component.ID, 0, len(randCons)) + for id := range randCons { + conIDs = append(conIDs, id) + expected[id]++ + } + + // Route to list of consumers + fanout, err := r.Consumer(conIDs...) + assert.NoError(t, err) + assert.NoError(t, fanout.ConsumeLogs(context.Background(), ld)) + + // Validate expectations for all consumers + for id := range expected { + logs := []plog.Logs{} + switch con := allConsMap[id].(type) { + case *consumertest.LogsSink: + logs = con.AllLogs() + case *mutatingLogsSink: + logs = con.AllLogs() + } + assert.Len(t, logs, expected[id]) + for n := 0; n < len(logs); n++ { + assert.EqualValues(t, ld, logs[n]) + } + } + } + } +} + +func TestLogsRouterConsumers(t *testing.T) { + ctx := context.Background() + ld := testdata.GenerateLogs(1) + + fooID := component.MustNewID("foo") + barID := component.MustNewID("bar") + + foo := new(consumertest.LogsSink) + bar := new(consumertest.LogsSink) + r := NewLogsRouter(map[component.ID]consumer.Logs{fooID: foo, barID: bar}) + + rcs := r.PipelineIDs() + assert.Len(t, rcs, 2) + assert.ElementsMatch(t, []component.ID{fooID, barID}, rcs) + + assert.Len(t, foo.AllLogs(), 0) + assert.Len(t, bar.AllLogs(), 0) + + both, err := r.Consumer(fooID, barID) + assert.NotNil(t, both) + assert.NoError(t, err) + + assert.NoError(t, both.ConsumeLogs(ctx, ld)) + assert.Len(t, foo.AllLogs(), 1) + assert.Len(t, bar.AllLogs(), 1) + + fooOnly, err := r.Consumer(fooID) + assert.NotNil(t, fooOnly) + assert.NoError(t, err) + + assert.NoError(t, fooOnly.ConsumeLogs(ctx, ld)) + assert.Len(t, foo.AllLogs(), 2) + assert.Len(t, bar.AllLogs(), 1) + + barOnly, err := r.Consumer(barID) + assert.NotNil(t, barOnly) + assert.NoError(t, err) + + assert.NoError(t, barOnly.ConsumeLogs(ctx, ld)) + assert.Len(t, foo.AllLogs(), 2) + assert.Len(t, bar.AllLogs(), 2) + + none, err := r.Consumer() + assert.Nil(t, none) + assert.Error(t, err) + + fake, err := r.Consumer(component.MustNewID("fake")) + assert.Nil(t, fake) + assert.Error(t, err) +} diff --git a/connector/metrics_router.go b/connector/metrics_router.go new file mode 100644 index 00000000000..8e2b8e900a1 --- /dev/null +++ b/connector/metrics_router.go @@ -0,0 +1,75 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package connector // import "go.opentelemetry.io/collector/connector" + +import ( + "fmt" + + "go.uber.org/multierr" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/internal/fanoutconsumer" +) + +// Deprecated: [v0.92.0] use MetricsRouterAndConsumer. +type MetricsRouter interface { + Consumer(...component.ID) (consumer.Metrics, error) + PipelineIDs() []component.ID +} + +// MetricsRouterAndConsumer feeds the first consumer.Metrics in each of the specified pipelines. +type MetricsRouterAndConsumer interface { + consumer.Metrics + Consumer(...component.ID) (consumer.Metrics, error) + PipelineIDs() []component.ID + privateFunc() +} + +type metricsRouter struct { + consumer.Metrics + consumers map[component.ID]consumer.Metrics +} + +func NewMetricsRouter(cm map[component.ID]consumer.Metrics) MetricsRouterAndConsumer { + consumers := make([]consumer.Metrics, 0, len(cm)) + for _, cons := range cm { + consumers = append(consumers, cons) + } + return &metricsRouter{ + Metrics: fanoutconsumer.NewMetrics(consumers), + consumers: cm, + } +} + +func (r *metricsRouter) PipelineIDs() []component.ID { + ids := make([]component.ID, 0, len(r.consumers)) + for id := range r.consumers { + ids = append(ids, id) + } + return ids +} + +func (r *metricsRouter) Consumer(pipelineIDs ...component.ID) (consumer.Metrics, error) { + if len(pipelineIDs) == 0 { + return nil, fmt.Errorf("missing consumers") + } + consumers := make([]consumer.Metrics, 0, len(pipelineIDs)) + var errors error + for _, pipelineID := range pipelineIDs { + c, ok := r.consumers[pipelineID] + if ok { + consumers = append(consumers, c) + } else { + errors = multierr.Append(errors, fmt.Errorf("missing consumer: %q", pipelineID)) + } + } + if errors != nil { + // TODO potentially this could return a NewMetrics with the valid consumers + return nil, errors + } + return fanoutconsumer.NewMetrics(consumers), nil +} + +func (r *metricsRouter) privateFunc() {} diff --git a/connector/metrics_router_test.go b/connector/metrics_router_test.go new file mode 100644 index 00000000000..62dd54c11e0 --- /dev/null +++ b/connector/metrics_router_test.go @@ -0,0 +1,156 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package connector + +import ( + "context" + "fmt" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/internal/testdata" + "go.opentelemetry.io/collector/pdata/pmetric" +) + +type mutatingMetricsSink struct { + *consumertest.MetricsSink +} + +func (mts *mutatingMetricsSink) Capabilities() consumer.Capabilities { + return consumer.Capabilities{MutatesData: true} +} + +func TestMetricsRouterMultiplexing(t *testing.T) { + var max = 20 + for numIDs := 1; numIDs < max; numIDs++ { + for numCons := 1; numCons < max; numCons++ { + for numMetrics := 1; numMetrics < max; numMetrics++ { + t.Run( + fmt.Sprintf("%d-ids/%d-cons/%d-logs", numIDs, numCons, numMetrics), + fuzzMetrics(numIDs, numCons, numMetrics), + ) + } + } + } +} + +func fuzzMetrics(numIDs, numCons, numMetrics int) func(*testing.T) { + return func(t *testing.T) { + allIDs := make([]component.ID, 0, numCons) + allCons := make([]consumer.Metrics, 0, numCons) + allConsMap := make(map[component.ID]consumer.Metrics) + + // If any consumer is mutating, the router must report mutating + for i := 0; i < numCons; i++ { + allIDs = append(allIDs, component.MustNewIDWithName("sink", strconv.Itoa(numCons))) + // Random chance for each consumer to be mutating + if (numCons+numMetrics+i)%4 == 0 { + allCons = append(allCons, &mutatingMetricsSink{MetricsSink: new(consumertest.MetricsSink)}) + } else { + allCons = append(allCons, new(consumertest.MetricsSink)) + } + allConsMap[allIDs[i]] = allCons[i] + } + + r := NewMetricsRouter(allConsMap) + md := testdata.GenerateMetrics(1) + + // Keep track of how many logs each consumer should receive. + // This will be validated after every call to RouteMetrics. + expected := make(map[component.ID]int, numCons) + + for i := 0; i < numMetrics; i++ { + // Build a random set of ids (no duplicates) + randCons := make(map[component.ID]bool, numIDs) + for j := 0; j < numIDs; j++ { + // This number should be pretty random and less than numCons + conNum := (numCons + numIDs + i + j) % numCons + randCons[allIDs[conNum]] = true + } + + // Convert to slice, update expectations + conIDs := make([]component.ID, 0, len(randCons)) + for id := range randCons { + conIDs = append(conIDs, id) + expected[id]++ + } + + // Route to list of consumers + fanout, err := r.Consumer(conIDs...) + assert.NoError(t, err) + assert.NoError(t, fanout.ConsumeMetrics(context.Background(), md)) + + // Validate expectations for all consumers + for id := range expected { + metrics := []pmetric.Metrics{} + switch con := allConsMap[id].(type) { + case *consumertest.MetricsSink: + metrics = con.AllMetrics() + case *mutatingMetricsSink: + metrics = con.AllMetrics() + } + assert.Len(t, metrics, expected[id]) + for n := 0; n < len(metrics); n++ { + assert.EqualValues(t, md, metrics[n]) + } + } + } + } +} + +func TestMetricsRouterConsumers(t *testing.T) { + ctx := context.Background() + md := testdata.GenerateMetrics(1) + + fooID := component.MustNewID("foo") + barID := component.MustNewID("bar") + + foo := new(consumertest.MetricsSink) + bar := new(consumertest.MetricsSink) + r := NewMetricsRouter(map[component.ID]consumer.Metrics{fooID: foo, barID: bar}) + + rcs := r.PipelineIDs() + assert.Len(t, rcs, 2) + assert.ElementsMatch(t, []component.ID{fooID, barID}, rcs) + + assert.Len(t, foo.AllMetrics(), 0) + assert.Len(t, bar.AllMetrics(), 0) + + both, err := r.Consumer(fooID, barID) + assert.NotNil(t, both) + assert.NoError(t, err) + + assert.NoError(t, both.ConsumeMetrics(ctx, md)) + assert.Len(t, foo.AllMetrics(), 1) + assert.Len(t, bar.AllMetrics(), 1) + + fooOnly, err := r.Consumer(fooID) + assert.NotNil(t, fooOnly) + assert.NoError(t, err) + + assert.NoError(t, fooOnly.ConsumeMetrics(ctx, md)) + assert.Len(t, foo.AllMetrics(), 2) + assert.Len(t, bar.AllMetrics(), 1) + + barOnly, err := r.Consumer(barID) + assert.NotNil(t, barOnly) + assert.NoError(t, err) + + assert.NoError(t, barOnly.ConsumeMetrics(ctx, md)) + assert.Len(t, foo.AllMetrics(), 2) + assert.Len(t, bar.AllMetrics(), 2) + + none, err := r.Consumer() + assert.Nil(t, none) + assert.Error(t, err) + + fake, err := r.Consumer(component.MustNewID("fake")) + assert.Nil(t, fake) + assert.Error(t, err) +} diff --git a/connector/package_test.go b/connector/package_test.go new file mode 100644 index 00000000000..01379e8ae20 --- /dev/null +++ b/connector/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package connector + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/connector/traces_router.go b/connector/traces_router.go new file mode 100644 index 00000000000..97c31d7920c --- /dev/null +++ b/connector/traces_router.go @@ -0,0 +1,75 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package connector // import "go.opentelemetry.io/collector/connector" + +import ( + "fmt" + + "go.uber.org/multierr" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/internal/fanoutconsumer" +) + +// Deprecated: [v0.92.0] use TracesRouterAndConsumer +type TracesRouter interface { + Consumer(...component.ID) (consumer.Traces, error) + PipelineIDs() []component.ID +} + +// TracesRouterAndConsumer feeds the first consumer.Traces in each of the specified pipelines. +type TracesRouterAndConsumer interface { + consumer.Traces + Consumer(...component.ID) (consumer.Traces, error) + PipelineIDs() []component.ID + privateFunc() +} + +type tracesRouter struct { + consumer.Traces + consumers map[component.ID]consumer.Traces +} + +func NewTracesRouter(cm map[component.ID]consumer.Traces) TracesRouterAndConsumer { + consumers := make([]consumer.Traces, 0, len(cm)) + for _, c := range cm { + consumers = append(consumers, c) + } + return &tracesRouter{ + Traces: fanoutconsumer.NewTraces(consumers), + consumers: cm, + } +} + +func (r *tracesRouter) PipelineIDs() []component.ID { + ids := make([]component.ID, 0, len(r.consumers)) + for id := range r.consumers { + ids = append(ids, id) + } + return ids +} + +func (r *tracesRouter) Consumer(pipelineIDs ...component.ID) (consumer.Traces, error) { + if len(pipelineIDs) == 0 { + return nil, fmt.Errorf("missing consumers") + } + consumers := make([]consumer.Traces, 0, len(pipelineIDs)) + var errors error + for _, pipelineID := range pipelineIDs { + c, ok := r.consumers[pipelineID] + if ok { + consumers = append(consumers, c) + } else { + errors = multierr.Append(errors, fmt.Errorf("missing consumer: %q", pipelineID)) + } + } + if errors != nil { + // TODO potentially this could return a NewTraces with the valid consumers + return nil, errors + } + return fanoutconsumer.NewTraces(consumers), nil +} + +func (r *tracesRouter) privateFunc() {} diff --git a/connector/traces_router_test.go b/connector/traces_router_test.go new file mode 100644 index 00000000000..33a2124ed3e --- /dev/null +++ b/connector/traces_router_test.go @@ -0,0 +1,156 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package connector + +import ( + "context" + "fmt" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/internal/testdata" + "go.opentelemetry.io/collector/pdata/ptrace" +) + +type mutatingTracesSink struct { + *consumertest.TracesSink +} + +func (mts *mutatingTracesSink) Capabilities() consumer.Capabilities { + return consumer.Capabilities{MutatesData: true} +} + +func TestTracesRouterMultiplexing(t *testing.T) { + var max = 20 + for numIDs := 1; numIDs < max; numIDs++ { + for numCons := 1; numCons < max; numCons++ { + for numTraces := 1; numTraces < max; numTraces++ { + t.Run( + fmt.Sprintf("%d-ids/%d-cons/%d-logs", numIDs, numCons, numTraces), + fuzzTraces(numIDs, numCons, numTraces), + ) + } + } + } +} + +func fuzzTraces(numIDs, numCons, numTraces int) func(*testing.T) { + return func(t *testing.T) { + allIDs := make([]component.ID, 0, numCons) + allCons := make([]consumer.Traces, 0, numCons) + allConsMap := make(map[component.ID]consumer.Traces) + + // If any consumer is mutating, the router must report mutating + for i := 0; i < numCons; i++ { + allIDs = append(allIDs, component.MustNewIDWithName("sink", strconv.Itoa(numCons))) + // Random chance for each consumer to be mutating + if (numCons+numTraces+i)%4 == 0 { + allCons = append(allCons, &mutatingTracesSink{TracesSink: new(consumertest.TracesSink)}) + } else { + allCons = append(allCons, new(consumertest.TracesSink)) + } + allConsMap[allIDs[i]] = allCons[i] + } + + r := NewTracesRouter(allConsMap) + td := testdata.GenerateTraces(1) + + // Keep track of how many logs each consumer should receive. + // This will be validated after every call to RouteTraces. + expected := make(map[component.ID]int, numCons) + + for i := 0; i < numTraces; i++ { + // Build a random set of ids (no duplicates) + randCons := make(map[component.ID]bool, numIDs) + for j := 0; j < numIDs; j++ { + // This number should be pretty random and less than numCons + conNum := (numCons + numIDs + i + j) % numCons + randCons[allIDs[conNum]] = true + } + + // Convert to slice, update expectations + conIDs := make([]component.ID, 0, len(randCons)) + for id := range randCons { + conIDs = append(conIDs, id) + expected[id]++ + } + + // Route to list of consumers + fanout, err := r.Consumer(conIDs...) + assert.NoError(t, err) + assert.NoError(t, fanout.ConsumeTraces(context.Background(), td)) + + // Validate expectations for all consumers + for id := range expected { + traces := []ptrace.Traces{} + switch con := allConsMap[id].(type) { + case *consumertest.TracesSink: + traces = con.AllTraces() + case *mutatingTracesSink: + traces = con.AllTraces() + } + assert.Len(t, traces, expected[id]) + for n := 0; n < len(traces); n++ { + assert.EqualValues(t, td, traces[n]) + } + } + } + } +} + +func TestTracesRouterConsumer(t *testing.T) { + ctx := context.Background() + td := testdata.GenerateTraces(1) + + fooID := component.MustNewID("foo") + barID := component.MustNewID("bar") + + foo := new(consumertest.TracesSink) + bar := new(consumertest.TracesSink) + r := NewTracesRouter(map[component.ID]consumer.Traces{fooID: foo, barID: bar}) + + rcs := r.PipelineIDs() + assert.Len(t, rcs, 2) + assert.ElementsMatch(t, []component.ID{fooID, barID}, rcs) + + assert.Len(t, foo.AllTraces(), 0) + assert.Len(t, bar.AllTraces(), 0) + + both, err := r.Consumer(fooID, barID) + assert.NotNil(t, both) + assert.NoError(t, err) + + assert.NoError(t, both.ConsumeTraces(ctx, td)) + assert.Len(t, foo.AllTraces(), 1) + assert.Len(t, bar.AllTraces(), 1) + + fooOnly, err := r.Consumer(fooID) + assert.NotNil(t, fooOnly) + assert.NoError(t, err) + + assert.NoError(t, fooOnly.ConsumeTraces(ctx, td)) + assert.Len(t, foo.AllTraces(), 2) + assert.Len(t, bar.AllTraces(), 1) + + barOnly, err := r.Consumer(barID) + assert.NotNil(t, barOnly) + assert.NoError(t, err) + + assert.NoError(t, barOnly.ConsumeTraces(ctx, td)) + assert.Len(t, foo.AllTraces(), 2) + assert.Len(t, bar.AllTraces(), 2) + + none, err := r.Consumer() + assert.Nil(t, none) + assert.Error(t, err) + + fake, err := r.Consumer(component.MustNewID("fake")) + assert.Nil(t, fake) + assert.Error(t, err) +} diff --git a/consumer/consumer.go b/consumer/consumer.go index 37a9baba4f5..503750ad7cb 100644 --- a/consumer/consumer.go +++ b/consumer/consumer.go @@ -10,7 +10,7 @@ import ( // Capabilities describes the capabilities of a Processor. type Capabilities struct { // MutatesData is set to true if Consume* function of the - // processor modifies the input TraceData or MetricsData argument. + // processor modifies the input Traces, Logs or Metrics argument. // Processors which modify the input data MUST set this flag to true. If the processor // does not modify the data it MUST set this flag to false. If the processor creates // a copy of the data before modifying then this flag can be safely set to false. @@ -38,7 +38,7 @@ func WithCapabilities(capabilities Capabilities) Option { } } -// Capabilities implementation of the base +// Capabilities returns the capabilities of the component func (bs baseImpl) Capabilities() Capabilities { return bs.capabilities } diff --git a/consumer/consumererror/package_test.go b/consumer/consumererror/package_test.go new file mode 100644 index 00000000000..3e9fdb39d01 --- /dev/null +++ b/consumer/consumererror/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package consumererror + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/consumer/consumertest/err.go b/consumer/consumertest/err.go index 279cf4baf29..d147453aaf7 100644 --- a/consumer/consumertest/err.go +++ b/consumer/consumertest/err.go @@ -13,8 +13,8 @@ import ( // NewErr returns a Consumer that just drops all received data and returns the specified error to Consume* callers. func NewErr(err error) Consumer { return &baseConsumer{ - ConsumeTracesFunc: func(ctx context.Context, td ptrace.Traces) error { return err }, - ConsumeMetricsFunc: func(ctx context.Context, md pmetric.Metrics) error { return err }, - ConsumeLogsFunc: func(ctx context.Context, ld plog.Logs) error { return err }, + ConsumeTracesFunc: func(context.Context, ptrace.Traces) error { return err }, + ConsumeMetricsFunc: func(context.Context, pmetric.Metrics) error { return err }, + ConsumeLogsFunc: func(context.Context, plog.Logs) error { return err }, } } diff --git a/consumer/consumertest/nop.go b/consumer/consumertest/nop.go index 157d0e4b3b2..fbb01e3bb98 100644 --- a/consumer/consumertest/nop.go +++ b/consumer/consumertest/nop.go @@ -14,8 +14,8 @@ import ( // NewNop returns a Consumer that just drops all received data and returns no error. func NewNop() Consumer { return &baseConsumer{ - ConsumeTracesFunc: func(ctx context.Context, td ptrace.Traces) error { return nil }, - ConsumeMetricsFunc: func(ctx context.Context, md pmetric.Metrics) error { return nil }, - ConsumeLogsFunc: func(ctx context.Context, ld plog.Logs) error { return nil }, + ConsumeTracesFunc: func(context.Context, ptrace.Traces) error { return nil }, + ConsumeMetricsFunc: func(context.Context, pmetric.Metrics) error { return nil }, + ConsumeLogsFunc: func(context.Context, plog.Logs) error { return nil }, } } diff --git a/consumer/consumertest/package_test.go b/consumer/consumertest/package_test.go new file mode 100644 index 00000000000..955ff17fa52 --- /dev/null +++ b/consumer/consumertest/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package consumertest + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/consumer/doc.go b/consumer/doc.go index 9f5bac07b88..b2ea0535b79 100644 --- a/consumer/doc.go +++ b/consumer/doc.go @@ -1,5 +1,5 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -// Package consumer contains interfaces that receive and process consumerdata. +// Package consumer contains interfaces that receive and process data. package consumer // import "go.opentelemetry.io/collector/consumer" diff --git a/consumer/go.mod b/consumer/go.mod index 72cb49e1d3b..a0d4cd6f95f 100644 --- a/consumer/go.mod +++ b/consumer/go.mod @@ -1,11 +1,12 @@ module go.opentelemetry.io/collector/consumer -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.uber.org/goleak v1.3.0 ) require ( @@ -18,12 +19,12 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -33,31 +34,13 @@ replace go.opentelemetry.io/collector/component => ../component replace go.opentelemetry.io/collector/confmap => ../confmap -replace go.opentelemetry.io/collector/exporter => ../exporter - -replace go.opentelemetry.io/collector/extension => ../extension - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../extension/zpagesextension - replace go.opentelemetry.io/collector/featuregate => ../featuregate replace go.opentelemetry.io/collector/pdata => ../pdata -replace go.opentelemetry.io/collector/processor => ../processor - -replace go.opentelemetry.io/collector/receiver => ../receiver - -replace go.opentelemetry.io/collector/semconv => ../semconv - retract ( v0.76.0 // Depends on retracted pdata v1.0.0-rc10 module, use v0.76.1 v0.69.0 // Release failed, use v0.69.1 ) -replace go.opentelemetry.io/collector/connector => ../connector - -replace go.opentelemetry.io/collector/config/confignet => ../config/confignet - replace go.opentelemetry.io/collector/config/configtelemetry => ../config/configtelemetry - -replace go.opentelemetry.io/collector/service => ../service diff --git a/consumer/go.sum b/consumer/go.sum index 9e7a7130b9f..834ba473908 100644 --- a/consumer/go.sum +++ b/consumer/go.sum @@ -8,13 +8,15 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -25,12 +27,15 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -42,20 +47,20 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -64,15 +69,16 @@ 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-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= 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/consumer/metrics.go b/consumer/metrics.go index d0bd6559c94..50df60f02d0 100644 --- a/consumer/metrics.go +++ b/consumer/metrics.go @@ -9,7 +9,7 @@ import ( "go.opentelemetry.io/collector/pdata/pmetric" ) -// Metrics is the new metrics consumer interface that receives pmetric.Metrics, processes it +// Metrics is an interface that receives pmetric.Metrics, processes it // as needed, and sends it to the next processing node if any or to the destination. type Metrics interface { baseConsumer @@ -18,11 +18,11 @@ type Metrics interface { } // ConsumeMetricsFunc is a helper function that is similar to ConsumeMetrics. -type ConsumeMetricsFunc func(ctx context.Context, ld pmetric.Metrics) error +type ConsumeMetricsFunc func(ctx context.Context, md pmetric.Metrics) error -// ConsumeMetrics calls f(ctx, ld). -func (f ConsumeMetricsFunc) ConsumeMetrics(ctx context.Context, ld pmetric.Metrics) error { - return f(ctx, ld) +// ConsumeMetrics calls f(ctx, md). +func (f ConsumeMetricsFunc) ConsumeMetrics(ctx context.Context, md pmetric.Metrics) error { + return f(ctx, md) } type baseMetrics struct { diff --git a/consumer/package_test.go b/consumer/package_test.go new file mode 100644 index 00000000000..f5e88f8cc07 --- /dev/null +++ b/consumer/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package consumer + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/consumer/traces.go b/consumer/traces.go index 7a0e8e6aa9e..56cebd53b37 100644 --- a/consumer/traces.go +++ b/consumer/traces.go @@ -18,11 +18,11 @@ type Traces interface { } // ConsumeTracesFunc is a helper function that is similar to ConsumeTraces. -type ConsumeTracesFunc func(ctx context.Context, ld ptrace.Traces) error +type ConsumeTracesFunc func(ctx context.Context, td ptrace.Traces) error -// ConsumeTraces calls f(ctx, ld). -func (f ConsumeTracesFunc) ConsumeTraces(ctx context.Context, ld ptrace.Traces) error { - return f(ctx, ld) +// ConsumeTraces calls f(ctx, td). +func (f ConsumeTracesFunc) ConsumeTraces(ctx context.Context, td ptrace.Traces) error { + return f(ctx, td) } type baseTraces struct { diff --git a/docs/design.md b/docs/design.md index 17cf2f6b853..51ed65bbbe5 100644 --- a/docs/design.md +++ b/docs/design.md @@ -120,7 +120,7 @@ In the above example `jaeger` exporter will get data from pipeline `traces` and A pipeline can contain sequentially connected processors. The first processor gets the data from one or more receivers that are configured for the pipeline, the last processor sends the data to one or more exporters that are configured for the pipeline. All processors between the first and last receive the data strictly only from one preceding processor and send data strictly only to the succeeding processor. -Processors can transform the data before forwarding it (i.e. add or remove attributes from spans), they can drop the data simply by deciding not to forward it (this is for example how the `probabilisticsampler` processor works), they can also generate new data. This is how a `spanmetrics` processor can produce metrics for spans processed by the pipeline. +Processors can transform the data before forwarding it (i.e. add or remove attributes from spans), they can drop the data simply by deciding not to forward it (this is for example how the `probabilisticsampler` processor works), they can also generate new data. The same name of the processor can be referenced in the `processors` key of multiple pipelines. In this case the same configuration will be used for each of these processors however each pipeline will always get its own instance of the processor. Each of these processors will have its own state, the processors are never shared between pipelines. For example if `batch` processor is used in several pipelines each pipeline will have its own batch processor (although each batch processor will be configured exactly the same way if they reference the same key in the configuration). As an example, given the following configuration: diff --git a/docs/images/design-service-lifecycle.png b/docs/images/design-service-lifecycle.png deleted file mode 100644 index ad55af383f0..00000000000 Binary files a/docs/images/design-service-lifecycle.png and /dev/null differ diff --git a/docs/monitoring.md b/docs/monitoring.md index 3b73d8f85b1..d50782db712 100644 --- a/docs/monitoring.md +++ b/docs/monitoring.md @@ -16,7 +16,7 @@ desired reliability level. ### Low on CPU Resources This depends on the CPU metrics available on the deployment, eg.: -`kube_pod_container_resource_limits_cpu_cores` for Kubernetes. Let's call it +`kube_pod_container_resource_limits{resource="cpu", unit="core"}` for Kubernetes. Let's call it `available_cores` below. The idea here is to have an upper bound of the number of available cores, and the maximum expected ingestion rate considered safe, let's call it `safe_rate`, per core. This should trigger increase of resources/ diff --git a/docs/observability.md b/docs/observability.md index bf33f082e5f..78933983217 100644 --- a/docs/observability.md +++ b/docs/observability.md @@ -76,9 +76,52 @@ For begin/stop events we need to define an appropriate hysteresis to avoid gener The service should collect host resource metrics in addition to service's own process metrics. This may help to understand that the problem that we observe in the service is induced by a different process on the same host. -## How We Expose Metrics/Traces - -Collector configuration must allow specifying the target for own metrics/traces (which can be different from the target of collected data). The metrics and traces must be clearly tagged to indicate that they are service’s own metrics (to avoid conflating with collected data in the backend). +## How We Expose Telemetry + +By default, the Collector exposes service telemetry in two ways currently: + +- internal metrics are exposed via a Prometheus interface which defaults to port `8888` +- logs are emitted to stdout + +Traces are not exposed by default. There is an effort underway to [change this][issue7532]. The work includes supporting +configuration of the OpenTelemetry SDK used to produce the Collector's internal telemetry. This feature is +currently behind two feature gates: + +```bash + --feature-gates=telemetry.useOtelWithSDKConfigurationForInternalTelemetry +``` + +The gate `useOtelWithSDKConfigurationForInternalTelemetry` enables the Collector to parse configuration +that aligns with the [OpenTelemetry Configuration] schema. The support for this schema is still +experimental, but it does allow telemetry to be exported via OTLP. + +The following configuration can be used in combination with the feature gates aforementioned +to emit internal metrics and traces from the Collector to an OTLP backend: + +```yaml +service: + telemetry: + metrics: + readers: + - periodic: + interval: 5000 + exporter: + otlp: + protocol: grpc/protobuf + endpoint: https://backend:4317 + traces: + processors: + - batch: + exporter: + otlp: + protocol: grpc/protobuf + endpoint: https://backend2:4317 +``` + +See the configuration's [example][kitchen-sink] for additional configuration options. + +Note that this configuration does not support emitting logs as there is no support for [logs] in +OpenTelemetry Go SDK at this time. ### Impact @@ -89,3 +132,9 @@ We need to be able to assess the impact of these observability improvements on t Some of the metrics/traces can be high volume and may not be desirable to always observe. We should consider adding an observability verboseness “level” that allows configuring the Collector to send more or less observability data (or even finer granularity to allow turning on/off specific metrics). The default level of observability must be defined in a way that has insignificant performance impact on the service. + +[issue7532]: https://github.com/open-telemetry/opentelemetry-collector/issues/7532 +[issue7454]: https://github.com/open-telemetry/opentelemetry-collector/issues/7454 +[logs]: https://github.com/open-telemetry/opentelemetry-go/issues/3827 +[OpenTelemetry Configuration]: https://github.com/open-telemetry/opentelemetry-configuration +[kitchen-sink]: https://github.com/open-telemetry/opentelemetry-configuration/blob/main/examples/kitchen-sink.yaml diff --git a/docs/performance.md b/docs/performance.md deleted file mode 100644 index 8854ae1e00f..00000000000 --- a/docs/performance.md +++ /dev/null @@ -1,72 +0,0 @@ -# OpenTelemetry Collector Performance - -The performance numbers that follow were generated using version 0.1.3 of the -OpenTelemetry Collector, are applicable primarily to the OpenTelemetry Collector and -are measured only for traces. In the future, more configurations will be tested. - -Note with the OpenTelemetry Agent you can expect as good if not better performance -with lower resource utilization. This is because the OpenTelemetry Agent does not -today support features such as batching or retries and will not support -tail_sampling. - -It is important to note that the performance of the OpenTelemetry Collector depends -on a variety of factors including: - -* The receiving format: OpenTelemetry (55678), Jaeger thrift (14268) or Zipkin v2 JSON (9411) -* The size of the spans (tests are based on number of attributes): 20 -* Whether tail_sampling is enabled or not -* CPU / Memory allocation -* Operating System: Linux - -## Testing - -Testing was completed on Linux using the [Synthetic Load Generator -utility](https://github.com/Omnition/synthetic-load-generator) running for a -minimum of one hour (i.e. sustained rate). You can reproduce these results in -your own environment using the parameters described in this document. It is -important to note that this utility has a few configurable parameters which can -impact the results of the tests. The parameters used are defined below. - -* FlushInterval(ms) [default: 1000] -* MaxQueueSize [default: 100] -* SubmissionRate(spans/sec): 100,000 - -## Results without tail-based sampling - -| Span
Format | CPU
(2+ GHz) | RAM
(GB) | Sustained
Rate | Recommended
Maximum | -| :---: | :---: | :---: | :---: | :---: | -| OpenTelemetry | 1 | 2 | ~12K | 10K | -| OpenTelemetry | 2 | 4 | ~24K | 20K | -| Jaeger Thrift | 1 | 2 | ~14K | 12K | -| Jaeger Thrift | 2 | 4 | ~27.5K | 24K | -| Zipkin v2 JSON | 1 | 2 | ~10.5K | 9K | -| Zipkin v2 JSON | 2 | 4 | ~22K | 18K | - -If you are NOT using tail-based sampling and you need higher rates then you can -either: - -* Divide traffic to different collector (e.g. by region) -* Scale-up by adding more resources (CPU/RAM) -* Scale-out by putting one or more collectors behind a load balancer or k8s -service - -## Results with tail-based sampling - -> Note: Additional memory is required for tail-based sampling - -| Span
Format | CPU
(2+ GHz) | RAM
(GB) | Sustained
Rate | Recommended
Maximum | -| :---: | :---: | :---: | :---: | :---: | -| OpenTelemetry | 1 | 2 | ~9K | 8K | -| OpenTelemetry | 2 | 4 | ~18K | 16K | -| Jaeger Thrift | 1 | 6 | ~11.5K | 10K | -| Jaeger Thrift | 2 | 8 | ~23K | 20K | -| Zipkin v2 JSON | 1 | 6 | ~8.5K | 7K | -| Zipkin v2 JSON | 2 | 8 | ~16K | 14K | - -If you are using tail-based sampling and you need higher rates then you can -either: - -* Scale-up by adding more resources (CPU/RAM) -* Scale-out by putting one or more collectors behind a load balancer or k8s -service, but the load balancer must support traceID-based routing (i.e. all -spans for a given traceID need to be received by the same collector instance) diff --git a/docs/platform-support.md b/docs/platform-support.md new file mode 100644 index 00000000000..7112bea89b5 --- /dev/null +++ b/docs/platform-support.md @@ -0,0 +1,72 @@ +# Platform Support + +The OpenTelemetry Collector will be supported following a tiered platform support model to balance between the aim to support as many platforms as possible and to guarantee stability for the most important platforms. A platform is described by the pair of operating system and processor architecture family as they are defined by the Go programming language as [known operating systems and architectures for use with the GOOS and GOARCH values](https://go.dev/src/go/build/syslist.go). + +For a supported platform, the OpenTelemetry Collector is supported when the [minimum requirements](https://github.com/golang/go/wiki/MinimumRequirements) of the Go release used by the collector are met for the operating system and architecture. Each supported platform requires the naming of designated owners. The platform support for the OpenTelemetry Collector is broken into three tiers with different levels of support for each tier and aligns with the current test strategy. + +For platforms not listed as supported by any of the tiers, support cannot be assumed to be provided. While the project may accept specific changes related to these platforms, there will be no official builds, support of issues and development of enhancements or bug fixes for these platforms. Future development of project for supported platforms may break the functionality of unsupported platforms. + +## Current Test Strategy + +The current verification process of the OpenTelemetry Collector includes unit and performance tests for core and additional end-to-end and integration tests for contrib. In the end-to-end tests, receivers, processors, and exporters etc. are tested in a testbed, while the integration tests rely on actual instances and available container images. Additional stability tests are in preparation for the future as well. All verification tests are run on the linux/amd64 as the primary platform today. In addition, unit tests are run for the _contrib_ collector on windows/amd64. The tests use as execution environments the latest Ubuntu and Windows Server versions [supported as Github runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources). + +The cross compile supports the following targets: +- darwin/amd64 and darwin/arm64 +- linux/amd64, linux/arm64, linux/386, linux/arm and linux/ppc64le +- windows/amd64, windows/386. + +Except of the mentioned tests for linux/amd64 and windows/amd64, no other platforms are tested by the CI/CD tooling. + +Container images of the _core_ and _contrib_ collector are built and published to Docker Hub and ghcr.io for the platforms specified in the [goreleaser configuration](https://github.com/open-telemetry/opentelemetry-collector-releases/blob/bf8002ec6d2109cdb4184fc6eb6f8bda59ea96a2/.goreleaser.yaml#L137). End-to-end tests of the _contrib_ container images are run on the latest Ubuntu Linux supported by GitHub runners and for the four most recent Kubernetes versions. + +## Tiered platform support model + +The platform support for the OpenTelemetry Collector is broken into three tiers with different levels of support for each tier. + +### Platform Support - Summary + +The following tables summarized the platform tiers of support by the verification tests performed for them and by the specification if dummy implementations are allowed for selected features, the availability of precompiled binaries incl. container images and if bugfix releases are provided for previous releases in case of critical defects. + +| Tier | Unit tests | Performance tests | End-to-end tests | Integrations tests | Dummy implementations | Precompiled binaries | Bugfix releases | +|------|------------|-------------------|------------------|--------------------|-----------------------|----------------------|-----------------| +| 1 | yes | yes | yes | yes | no | yes | yes | +| 2 | yes | optional | optional | optional | yes | yes | no | +| 3 | no | no | no | no | yes | yes | no | + +### Tier 1 – Primary Support + +The Tier 1 supported platforms are _guaranteed to work_. Precompiled binaries are built on the platform, fully supported for all collector add-ons (receivers, processor, exporters etc.), and continuously tested as part of the development processes to ensure any proposed change will function correctly. Build and test infrastructure is provided by the project. All tests are executed on the platform as part of automated continuous integration (CI) for each pull request and the [release cycle](https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/release.md#release-schedule). Any build or test failure block the release of the collector distribution for all platforms. Defects are addressed with priority and depending on severity fixed for previous release(s) in a bug fix release. + +Tier 1 platforms are currently: +| Platform | Owner(s) | +|-------------|-------------------------------------------------------------------------------------------------------------| +| linux/amd64 | [OpenTelemetry Collector approvers](https://github.com/open-telemetry/opentelemetry-collector#contributing) | + +### Tier 2 – Secondary Support + +Tier 2 platforms are _guaranteed to work with specified limitations_. Precompiled binaries are built and tested on the platform as part of the release cycle. Build and test infrastructure is provided by the platform maintainers. All tests are executed on the platform as far as they are applicable, and all prerequisites are fulfilled. Not executed tests and not tested collector add-ons (receivers, processors, exporters, etc.) are published on release of the collector distribution. Any build or test failure delays the release of the binaries for the respective platform but not the collector distribution for all other platforms. Defects are addressed but not with the priority as for Tier 1 and, if specific to the platform, require the support of the platform maintainers. + +Tier 2 platforms are currently: +| Platform | Owner(s) | +|---------------|-------------------------------------------------------------------------------------------------------------| +| windows/amd64 | [OpenTelemetry Collector approvers](https://github.com/open-telemetry/opentelemetry-collector#contributing) | + +### Tier 3 - Community Support + +Tier 3 platforms are _guaranteed to build_. Precompiled binaries are made available as part of the release process and as result of a cross compile build on Linux amd64 but the binaries are not tested at all. Any build failure delays the release of the binaries for the respective platform but not the collector distribution for all other platforms. Defects are addressed based on community contributions. Core developers might provide guidance or code reviews, but direct fixes may be limited. + +Tier 3 platforms are currently: +| Platform | Owner(s) | +|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| +| darwin/amd64 | [@h0cheung](https://github.com/h0cheung) | +| darwin/arm64 | [@MovieStoreGuy](https://github.com/MovieStoreGuy) | +| linux/arm64 | [@atoulme](https://github.com/atoulme) | +| linux/386 | [@astencel-sumo](https://github.com/astencel-sumo) | +| linux/arm | [@Wal8800](https://github.com/Wal8800), [@atoulme](https://github.com/atoulme) | +| linux/ppc64le | [@IBM-Currency-Helper](https://github.com/IBM-Currency-Helper), [@adilhusain-s](https://github.com/adilhusain-s), [@seth-priya](https://github.com/seth-priya) | +| linux/s390x | [@bwalk-at-ibm](https://github.com/bwalk-at-ibm), [@rrschulze](https://github.com/rrschulze) | +| windows/386 | [@pjanotti](https://github.com/pjanotti) | + +The proposed additional platform aix/ppc64 ([#19195](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/19195)) will be included into Tier 3 once it's added to the OpenTelemetry Collector as platform. + + diff --git a/docs/processing.md b/docs/processing.md index 63e5e21b705..331fa16c617 100644 --- a/docs/processing.md +++ b/docs/processing.md @@ -57,7 +57,7 @@ expectations. - Create new metrics based on information in spans, for example to create a duration metric that is not implemented in the SDK yet - Apply arithmetic between multiple incoming metrics to produce an output one, for example divide an `amount` and a `capacity` to create a `utilization` metric -The processors implementing this use case are `metricsgenerationprocessor`, `spanmetricsprocessor`. +The components implementing this use case are `metricsgenerationprocessor` and the former `spanmetricsprocessor` (now `spanmetricsconnector`). ### Grouping diff --git a/docs/release.md b/docs/release.md index 03f0a5a51fd..737279bf10f 100644 --- a/docs/release.md +++ b/docs/release.md @@ -27,12 +27,13 @@ It is possible that a core approver isn't a contrib approver. In that case, the 1. Update Contrib to use the latest in development version of Core. Run `make update-otel` in Contrib root directory and if it results in any changes submit a draft PR to Contrib. Ensure the CI passes before proceeding. This is to ensure that the latest core does not break contrib in any way. We’ll update it once more to the final release number later. -2. Determine the version number that will be assigned to the release. During the beta phase, we increment the minor version number and set the patch number to 0. In this document, we are using `v0.85.0` as the version to be released, following `v0.84.0`. - Check if stable modules have any changes since the last release by running `make check-changes PREVIOUS_VERSION=v1.0.0-rcv0014 MODSET=stable`. If there are no changes, there is no need to release new version for stable modules. +2. Determine the version number that will be assigned to the release. Usually, we increment the minor version number and set the patch number to 0. In this document, we are using `v0.85.0` as the version to be released, following `v0.84.0`. + Check if stable modules have any changes since the last release by running `make check-changes PREVIOUS_VERSION=v1.0.0 MODSET=stable`. If there are no changes, there is no need to release new version for stable modules. + If there are changes found but .chloggen directory doesn't have any corresponding entries, add missing changelog entries. If the changes are insignificant, consider not releasing a new version for stable modules. -3. Manually run the action [Automation - Prepare Release](https://github.com/open-telemetry/opentelemetry-collector/actions/workflows/prepare-release.yml). This action will create an issue to track the progress of the release and a pull request to update the changelog and version numbers in the repo. **While this PR is open all merging in Core should be haulted**. +3. Manually run the action [Automation - Prepare Release](https://github.com/open-telemetry/opentelemetry-collector/actions/workflows/prepare-release.yml). This action will create an issue to track the progress of the release and a pull request to update the changelog and version numbers in the repo. **While this PR is open all merging in Core should be halted**. - When prompted, enter the version numbers determined in Step 2, but do not include a leading `v`. - - If not intending to release stable modeles, do not specify a version for `Release candidate version stable`. + - If not intending to release stable modules, do not specify a version for `Release candidate version stable`. - If the PR needs updated in any way you can make the changes in a fork and PR those changes into the `prepare-release-prs/x` branch. You do not need to wait for the CI to pass in this prep-to-prep PR. - 🛑 **Do not move forward until this PR is merged.** 🛑 @@ -48,8 +49,8 @@ It is possible that a core approver isn't a contrib approver. In that case, the 7. A new `v0.85.0` release should be automatically created on Github by now. Edit it and use the contents from the CHANGELOG.md and CHANGELOG-API.md as the release's description. -8. If you created a draft PR to Contrib in step 3, update the PR to use the newly released Core version and set it to Ready for Review. - - Run `make update-otel OTEL_VERSION=v0.85.0 OTEL_RC_VERSION=v1.0.0-rcv0014` +8. Update the draft PR to Contrib created in step 1 to use the newly released Core version and set it to Ready for Review. + - Run `make update-otel OTEL_VERSION=v0.85.0 OTEL_STABLE_VERSION=v1.1.0` - Manually update `cmd/otelcontribcol/builder-config.yaml` - Manually update `cmd/oteltestbedcol/builder-config.yaml` - Run `make genotelcontribcol` @@ -58,7 +59,7 @@ It is possible that a core approver isn't a contrib approver. In that case, the ## Releasing opentelemetry-collector-contrib -1. Manually run the action [Automation - Prepare Release](https://github.com/open-telemetry/opentelemetry-collector-contrib/actions/workflows/prepare-release.yml). When prompted, enter the version numbers determined in Step 1, but do not include a leading `v`. This action will a pull request to update the changelog and version numbers in the repo. **While this PR is open all merging in Contrib should be haulted**. +1. Manually run the action [Automation - Prepare Release](https://github.com/open-telemetry/opentelemetry-collector-contrib/actions/workflows/prepare-release.yml). When prompted, enter the version numbers determined in Step 1, but do not include a leading `v`. This action will create a pull request to update the changelog and version numbers in the repo. **While this PR is open all merging in Contrib should be halted**. - If the PR needs updated in any way you can make the changes in a fork and PR those changes into the `prepare-release-prs/x` branch. You do not need to wait for the CI to pass in this prep-to-prep PR. - 🛑 **Do not move forward until this PR is merged.** 🛑 @@ -116,7 +117,7 @@ When considering making a bugfix release on the `v0.N.x` release cycle, the bug - Reverting a feature gate. - Changing the configuration to an easy to find value. 2. The bug happens in common setups. To gauge this, maintainers can consider the following: - - The bug is not specific to an uncommon platform + - If the bug is specific to a certain platform, and if that platform is in [Tier 1](../docs/platform-support.md#tiered-platform-support-model). - The bug happens with the default configuration or with a commonly used one (e.g. has been reported by multiple people) 3. The bug is sufficiently severe. For example (non-exhaustive list): - The bug makes the Collector crash reliably @@ -132,23 +133,34 @@ The OpenTelemetry Collector maintainers will ultimately have the responsibility The following documents the procedure to release a bugfix -1. Create a pull request against the `release/` (e.g. `release/v0.45.x`) branch to apply the fix. -2. Create a pull request to update version number against the `release/` branch. +1. Create a pull request against the `release/` (e.g. `release/v0.90.x`) branch to apply the fix. +2. Make sure you are on `release/`. Prepare release commits with `prepare-release` make target, e.g. `make prepare-release PREVIOUS_VERSION=0.90.0 RELEASE_CANDIDATE=0.90.1 MODSET=beta`, and create a pull request against the `release/` branch. 3. Once those changes have been merged, create a pull request to the `main` branch from the `release/` branch. -4. Enable the **Merge pull request** setting in the repository's **Settings** tab. -5. Tag all the modules with the new release version by running the `make add-tag` command (e.g. `make add-tag TAG=v0.85.0`). Push them to `open-telemetry/opentelemetry-collector` with `make push-tag TAG=v0.85.0`. Wait for the new tag build to pass successfully. -6. **IMPORTANT**: The pull request to bring the changes from the release branch *MUST* be merged using the **Merge pull request** method, and *NOT* squashed using “**Squash and merge**”. This is important as it allows us to ensure the commit SHA from the release branch is also on the main branch. **Not following this step will cause much go dependency sadness.** -7. Once the branch has been merged, it will be auto-deleted. Restore the release branch via GitHub. -8. Once the patch is release, disable the **Merge pull request** setting. +4. If you see merge conflicts when creating the pull request, do the following: + 1. Create a new branch from `origin:main`. + 2. Merge the `release/` branch into the new branch. + 3. Resolve the conflicts. + 4. Create another pull request to the `main` branch from the new branch to replace the pull request from the `release/` branch. +5. Enable the **Merge pull request** setting in the repository's **Settings** tab. +6. Make sure you are on `release/`. Push the new release version tags for a target module set by running `make push-tags MODSET=`. Wait for the new tag build to pass successfully. +7. **IMPORTANT**: The pull request to bring the changes from the release branch *MUST* be merged using the **Merge pull request** method, and *NOT* squashed using “**Squash and merge**”. This is important as it allows us to ensure the commit SHA from the release branch is also on the main branch. **Not following this step will cause much go dependency sadness.** +8. If the pull request was created from the `release/` branch, it will be auto-deleted. Restore the release branch via GitHub. +9. Once the patch is released, disable the **Merge pull request** setting. + +## 1.0 release + +Stable modules adhere to our [versioning document guarantees](../VERSIONING.md), so we need to be careful before releasing. Before adding a module to the stable module set and making a first 1.x release, please [open a new stabilization issue](https://github.com/open-telemetry/opentelemetry-collector/issues/new/choose) and follow the instructions in the issue template. + +Once a module is ready to be released under the `1.x` version scheme, file a PR to move the module to the `stable` module set and remove it from the `beta` module set. Note that we do not make `v1.x.y-rc.z` style releases for new stable modules; we instead treat the last two beta minor releases as release candidates and the module moves directly from the `0.x` to the `1.x` release series. ## Release schedule | Date | Version | Release manager | |------------|---------|-----------------| -| 2023-09-25 | v0.86.0 | @bogdandrutu | -| 2023-10-09 | v0.87.0 | @Aneurysm9 | -| 2023-10-23 | v0.88.0 | @mx-psi | -| 2023-11-06 | v0.89.0 | @jpkrohling | -| 2023-11-20 | v0.90.0 | @djaglowski | -| 2023-12-04 | v0.91.0 | @dmitryax | -| 2023-12-18 | v0.92.0 | @codeboten | \ No newline at end of file +| 2024-02-19 | v0.95.0 | @jpkrohling | +| 2024-03-04 | v0.96.0 | @mx-psi | +| 2024-03-18 | v0.97.0 | @djaglowski | +| 2024-04-01 | v0.98.0 | @dmitryax | +| 2024-04-15 | v0.99.0 | @codeboten | +| 2024-04-29 | v0.100.0 | @bogdandrutu | +| 2024-05-13 | v0.101.0 | @Aneurysm9 | diff --git a/docs/roadmap.md b/docs/roadmap.md deleted file mode 100644 index e76cb8b92ab..00000000000 --- a/docs/roadmap.md +++ /dev/null @@ -1,29 +0,0 @@ -# Long-term Roadmap - -This long-term roadmap (draft) is a vision document that reflects our -current desires. It is not a commitment to implement everything listed in this roadmap. -The primary purpose of this document is to ensure that all contributors work in alignment. -As our vision changes over time, maintainers reserve the right to add, modify, and _remove_ -items from this roadmap. - -Description|Status|Links| ------------|------|-----| -**Testing**| -Metrics correctness tests|Done|[#652](https://github.com/open-telemetry/opentelemetry-collector/issues/652) -| | -**New Formats**| -Complete OTLP/HTTP support|Done|[#882](https://github.com/open-telemetry/opentelemetry-collector/issues/882) -Add logs support for all primary core processors (attributes, batch, k8sattributes, etc)| Done | -| | -**5 Min to Value**| -Distribution packages for most common targets (e.g. Docker, RPM, Windows, etc)| Done | https://github.com/open-telemetry/opentelemetry-collector-releases/releases | -Detection and collection of environment metrics and tags on AWS| Beta| https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/resourcedetectionprocessor | -Detection and collection of k8s telemetry| Beta | https://pkg.go.dev/github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sattributesprocessor | -Host metric collection|Beta| https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/hostmetricsreceiver | -Support more application-specific metric collection (e.g. Kafka, Hadoop, etc) | In Progress | https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver| -| | -**Other Features**| -Graceful shutdown (pipeline draining)|Done|[#483](https://github.com/open-telemetry/opentelemetry-collector/issues/483) -Deprecate queue retry processor and enable queuing per exporter by default|Done|[#1721](https://github.com/open-telemetry/opentelemetry-collector/issues/1721) - -At this time, much of the effort from the OpenTelemetry Collector SIG is focused on achieving GA status across various packages. See additional details in the [GA roadmap](ga-roadmap.md) document. diff --git a/docs/scraping-receivers.md b/docs/scraping-receivers.md index e9fa31f44a2..91e0bd9f292 100644 --- a/docs/scraping-receivers.md +++ b/docs/scraping-receivers.md @@ -24,7 +24,7 @@ defines stability guarantees and provides guidelines for metric updates. Each built-in scraping metrics receiver has a `metadata.yaml` file that MUST define all the metrics emitted by the receiver. The file is being used to generate an API for metrics recording, user settings to customize the emitted metrics and user documentation. The file schema is defined in -https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/cmd/mdatagen/metric-metadata.yaml. +https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/cmd/mdatagen/metadata-schema.yaml Defining a metric in `metadata.yaml` DOES NOT guarantee that the metric will always be produced by the receiver. In some cases it may be impossible to fetch particular metrics from a system in a particular state. diff --git a/docs/security-best-practices.md b/docs/security-best-practices.md index 4101e561177..6ca44ba0b64 100644 --- a/docs/security-best-practices.md +++ b/docs/security-best-practices.md @@ -148,6 +148,8 @@ receivers: Generally, `localhost`-like addresses should be preferred over the 0.0.0.0 address. For more information, see [CWE-1327](https://cwe.mitre.org/data/definitions/1327.html). +To change the default endpoint to be `localhost`-bound in all components, enable the `component.UseLocalHostAsDefaultHost` feature gate. This feature gate will be enabled by default in the Collector in a future release. + ## Processors Processors sit between receivers and exporters. They are responsible for @@ -169,7 +171,7 @@ scrub sensitive data before exporting. In addition, processors offer safeguards around resource utilization. The `batch` and especially `memory_limiter` processor help ensure that the -Collector is resource efficient and does not out of memory when overloaded. At +Collector is resource efficient and does not run out of memory when overloaded. At least these two processors SHOULD be enabled on every defined pipeline. > For more information on recommended processors and order, see diff --git a/docs/service-extensions.md b/docs/service-extensions.md deleted file mode 100644 index 6d707a6d31e..00000000000 --- a/docs/service-extensions.md +++ /dev/null @@ -1,146 +0,0 @@ -# OpenTelemetry Collector: Extensions - -Besides the pipeline elements (receivers, processors, and exporters) the Collector -uses various service extensions (e.g.: healthcheck, z-pages, etc). -This document describes the “extensions” design and how they are implemented. - -## Configuration and Interface - -The configuration follows the same pattern used for pipelines: a base -configuration type and the creation of factories to instantiate the extension -objects. - -In order to support generic service extensions an interface is defined -so the service can interact uniformly with these. At minimum service extensions -need to implement the interface that covers Start and Shutdown. - -In addition to this base interface there is support to notify extensions when -pipelines are “ready” and when they are about to be stopped, i.e.: “not ready” -to receive data. These are a necessary addition to allow implementing extensions -that indicate to LBs and external systems if the service instance is ready or -not to receive data -(e.g.: a [k8s readiness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#define-readiness-probes)). -These state changes are under the control of the service server hosting -the extensions. - -There are more complex scenarios in which there can be notifications of state -changes from the extensions to their host. These more complex cases are not -supported at this moment, but this design doesn’t prevent such extensions in the -future[^1]. - - -## Collector State and Extensions - -The diagram below shows the basic state transitions of the OpenTelemetry Collector -and how it will interact with the service extensions. - -![ServiceLifeCycle](images/design-service-lifecycle.png) - - -## Configuration - -The config package will be extended to load the service extensions when the -configuration is loaded. The settings for service extensions will live in the -same configuration file as the pipeline elements. Below is an example of how -these sections would look like in the configuration file: - -```yaml - -# Example of the extensions available with the core Collector. The list below -# includes all configurable options and their respective default value. -extensions: - health_check: - port: 13133 - pprof: - endpoint: "localhost:1777" - block_profile_fraction: 0 - mutex_profile_fraction: 0 - zpages: - endpoint: "localhost:55679" - -# The service lists extensions not directly related to data pipelines, but used -# by the service. -service: - # extensions lists the extensions added to the service. They are started - # in the order presented below and stopped in the reverse order. - extensions: [health_check, pprof, zpages] -``` - -The configuration base type does not share any common fields. - -The configuration, analogous to pipelines, allows to have multiple extensions of -the same type. Implementers of extensions need to take care to return error -if it can only execute a single instance. (Note: the configuration uses composite -key names in the form of `type[/name]` -as defined in this [this document](https://docs.google.com/document/d/1NeheFG7DmcUYo_h2vLtNRlia9x5wOJMlV4QKEK05FhQ/edit#)). - -The factory follows the same pattern established for pipeline configuration: - -```go -// Factory is a factory interface for extensions to the service. -type Factory interface { - // Type gets the type of the extension created by this factory. - Type() string - - // CreateDefaultConfig creates the default configuration for the extension. - CreateDefaultConfig() config.Extension - - // CreateExtension creates a service extension based on the given config. - CreateExtension(logger *zap.Logger, cfg config.Extension) (component.Extension, error) -} -``` - - -## Extension Interface - -The interface defined below is the minimum required for -extensions in use on the service: - -```go -// ServiceExtension 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 ServiceExtension interface { - // Start the ServiceExtension object hosted by the given host. At this point in the - // process life-cycle the receivers are not started and the host did not - // receive any data yet. - Start(host Host) error - - // Shutdown the ServiceExtension instance. This happens after the pipelines were - // shutdown. - Shutdown() error -} - -// PipelineWatcher is an extra interface for ServiceExtension hosted by the OpenTelemetry -// Collector that is to be implemented by extensions interested in changes to pipeline -// states. Typically this will be used by extensions that change their behavior if data is -// being ingested or not, e.g.: a k8s readiness probe. -type PipelineWatcher interface { - // Ready notifies the ServiceExtension that all pipelines were built and the - // receivers were started, i.e.: the service is ready to receive data - // (notice that it may already have received data when this method is called). - Ready() error - - // NotReady notifies the ServiceExtension that all receivers are about to be stopped, - // i.e.: pipeline receivers will not accept new data. - // This is sent before receivers are stopped, so the ServiceExtension can take any - // appropriate action before that happens. - NotReady() error -} - -// Host represents the entity where the extension is being hosted. -// It is used to allow communication between the extension and its host. -type Host interface { - // ReportFatalError is used to report to the host that the extension - // encountered a fatal error (i.e.: an error that the instance can't recover - // from) after its start function had already returned. - ReportFatalError(err error) -} -``` - -## Notes - -[^1]: - This can be done by adding specific interfaces to extension types that support - those and having the service checking which of the extension instances support - each interface. diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index ff51b2afb7f..df9c995c507 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -11,8 +11,6 @@ Logs can be helpful in identifying issues. Always start by checking the log output and looking for potential issues. The verbosity level defaults to `INFO` and can be adjusted. -#### Version 0.36 and above: - Set the log level in the config `service::telemetry::logs` ```yaml @@ -22,22 +20,12 @@ service: level: "debug" ``` -#### Version 0.35 and below: - -Pass `--log-level` flag to the `otelcol` process. See `--help` for more details. - -```console -$ otelcol --log-level DEBUG -``` - ### Metrics Prometheus metrics are exposed locally on port `8888` and path `/metrics`. For containerized environments it may be desirable to expose this port on a public interface instead of just locally. -#### Version 0.43.0 and above: - Set the address in the config `service::telemetry::metrics` ```yaml @@ -47,17 +35,24 @@ service: address: ":8888" ``` -#### Version 0.42.0 and below: +A Grafana dashboard for these metrics can be found +[here](https://grafana.com/grafana/dashboards/15983-opentelemetry-collector/). -Pass `--metrics-addr ` flag to the `otelcol` process. See `--help` for -more details. +You can enhance metrics telemetry level using `level` field. The following is a list of all possible values and their explanations. -```console -$ otelcol --metrics-addr 0.0.0.0:8888 -``` +- "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. -A Grafana dashboard for these metrics can be found -[here](https://grafana.com/grafana/dashboards/15983-opentelemetry-collector/). +For example: +```yaml +service: + telemetry: + metrics: + level: detailed + address: ":8888" +``` Also note that a Collector can be configured to scrape its own metrics and send it through configured pipelines. For example: @@ -85,6 +80,22 @@ service: exporters: [debug] ``` +### Traces + +OpenTelemetry Collector has an ability to send it's own traces using OTLP exporter. You can send the traces to OTLP server running on the same OpenTelemetry Collector, so it goes through configured pipelines. For example: + +```yaml +service: + telemetry: + traces: + processors: + batch: + exporter: + otlp: + protocol: grpc/protobuf + endpoint: ${MY_POD_IP}:4317 +``` + ### zPages The @@ -247,8 +258,7 @@ The Collector may exit/restart because: - Memory pressure due to missing or misconfigured [memory_limiter](https://github.com/open-telemetry/opentelemetry-collector/blob/main/processor/memorylimiterprocessor/README.md) processor. -- [Improperly sized](https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/performance.md) - for load. +- Improperly sized for load. - Improperly configured (for example, a queue size configured higher than available memory). - Infrastructure resource limits (for example Kubernetes). @@ -257,7 +267,7 @@ The Collector may exit/restart because: Data may be dropped for a variety of reasons, but most commonly because of an: -- [Improperly sized Collector](https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/performance.md) resulting in Collector being unable to process and export the data as fast as it is received. +- Improperly sized Collector resulting in Collector being unable to process and export the data as fast as it is received. - Exporter destination unavailable or accepting the data too slowly. To mitigate drops, it is highly recommended to configure the @@ -305,7 +315,7 @@ configuration issue. This could be due to a firewall, DNS, or proxy issue. Note that the Collector does have [proxy support](https://github.com/open-telemetry/opentelemetry-collector/tree/main/exporter#proxy-support). -### Startup failing in Windows Docker containers +### Startup failing in Windows Docker containers (v0.90.1 and earlier) The process may fail to start in a Windows Docker container with the following error: `The service process could not connect to the service controller`. In diff --git a/docs/vision.md b/docs/vision.md index dfe9ab01934..5b315598d0d 100644 --- a/docs/vision.md +++ b/docs/vision.md @@ -21,5 +21,3 @@ Extensible and customizable without touching the core code. Can create custom ag ## Unified Codebase One codebase for daemon (Agent) and standalone service (Collector). - -For more details on how we plan to achieve this vision please see the [Roadmap](roadmap.md). \ No newline at end of file diff --git a/examples/k8s/otel-config.yaml b/examples/k8s/otel-config.yaml index 5a26806eb13..7c73578ac3c 100644 --- a/examples/k8s/otel-config.yaml +++ b/examples/k8s/otel-config.yaml @@ -35,11 +35,8 @@ data: check_interval: 5s extensions: zpages: {} - memory_ballast: - # Memory Ballast size should be max 1/3 to 1/2 of memory. - size_mib: 165 service: - extensions: [zpages, memory_ballast] + extensions: [zpages] pipelines: traces: receivers: [otlp] @@ -68,7 +65,7 @@ spec: - command: - "/otelcol" - "--config=/conf/otel-agent-config.yaml" - image: otel/opentelemetry-collector:0.85.0 + image: otel/opentelemetry-collector:0.94.0 name: otel-agent resources: limits: @@ -87,6 +84,8 @@ spec: fieldRef: apiVersion: v1 fieldPath: status.podIP + - name: GOMEMLIMIT + value: 400MiB volumeMounts: - name: otel-agent-config-vol mountPath: /conf @@ -124,16 +123,13 @@ data: check_interval: 5s extensions: zpages: {} - memory_ballast: - # Memory Ballast size should be max 1/3 to 1/2 of memory. - size_mib: 683 exporters: otlp: endpoint: "http://someotlp.target.com:4317" # Replace with a real endpoint. tls: insecure: true service: - extensions: [zpages, memory_ballast] + extensions: [zpages] pipelines: traces/1: receivers: [otlp] @@ -187,7 +183,7 @@ spec: - command: - "/otelcol" - "--config=/conf/otel-collector-config.yaml" - image: otel/opentelemetry-collector:0.85.0 + image: otel/opentelemetry-collector:0.94.0 name: otel-collector resources: limits: @@ -199,7 +195,7 @@ spec: ports: - containerPort: 55679 # Default endpoint for ZPages. - containerPort: 4317 # Default endpoint for OpenTelemetry receiver. - - containerPort: 14250 # Default endpoint for Jaeger gRPC receiver. + - containerPort: 1.3.0 # Default endpoint for Jaeger gRPC receiver. - containerPort: 14268 # Default endpoint for Jaeger HTTP receiver. - containerPort: 9411 # Default endpoint for Zipkin receiver. - containerPort: 8888 # Default endpoint for querying metrics. @@ -209,6 +205,8 @@ spec: fieldRef: apiVersion: v1 fieldPath: status.podIP + - name: GOMEMLIMIT + value: 1600MiB volumeMounts: - name: otel-collector-config-vol mountPath: /conf diff --git a/examples/local/otel-config.yaml b/examples/local/otel-config.yaml index 7ea61683d2a..20cbf6973f5 100644 --- a/examples/local/otel-config.yaml +++ b/examples/local/otel-config.yaml @@ -1,6 +1,4 @@ extensions: - memory_ballast: - size_mib: 512 zpages: endpoint: localhost:55679 @@ -15,7 +13,7 @@ receivers: processors: batch: memory_limiter: - # 75% of maximum memory up to 4G + # 75% of maximum memory up to 2G limit_mib: 1536 # 25% of limit up to 2G spike_limit_mib: 512 @@ -36,4 +34,4 @@ service: processors: [memory_limiter, batch] exporters: [debug] - extensions: [memory_ballast, zpages] + extensions: [zpages] diff --git a/exporter/README.md b/exporter/README.md index 109731a9573..f567fd7b9ac 100644 --- a/exporter/README.md +++ b/exporter/README.md @@ -1,27 +1,14 @@ # General Information -An exporter is how data gets sent to different systems/back-ends. Generally, an -exporter translates the internal format into another defined format. +An exporter defines how the pipeline data leaves the collector. -Available trace exporters (sorted alphabetically): +This repository hosts the following exporters available in +traces, metrics and logs pipelines (sorted alphabetically): +- [Debug](debugexporter/README.md) - [OTLP gRPC](otlpexporter/README.md) - [OTLP HTTP](otlphttpexporter/README.md) -Available metric exporters (sorted alphabetically): - -- [OTLP gRPC](otlpexporter/README.md) -- [OTLP HTTP](otlphttpexporter/README.md) - -Available log exporters (sorted alphabetically): - -- [OTLP gRPC](otlpexporter/README.md) -- [OTLP HTTP](otlphttpexporter/README.md) - -Available local exporters (sorted alphabetically): - -- [Logging](loggingexporter/README.md) - The [contrib repository](https://github.com/open-telemetry/opentelemetry-collector-contrib) has more exporters available in its builds. diff --git a/exporter/debugexporter/README.md b/exporter/debugexporter/README.md index dd246772af7..618e12b1d13 100644 --- a/exporter/debugexporter/README.md +++ b/exporter/debugexporter/README.md @@ -1,20 +1,29 @@ # Debug Exporter -| Status | | -| ------------------------ |-----------------------| -| Stability | [Development] | -| Supported pipeline types | traces, metrics, logs | -| Distributions | [core], [contrib] | + +| Status | | +| ------------- |-----------| +| Stability | [development]: traces, metrics, logs | +| Distributions | [core], [contrib] | +| Warnings | [Unstable Output Format](#warnings) | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aexporter%2Fdebug%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aexporter%2Fdebug) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aexporter%2Fdebug%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aexporter%2Fdebug) | -Exports data to the console via zap.Logger. +[development]: https://github.com/open-telemetry/opentelemetry-collector#development +[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + + +Exports data to the console (stderr) via `zap.Logger`. -Supported pipeline types: traces, metrics, logs +See also the [Troubleshooting][troubleshooting_docs] document for examples on using this exporter. + +[troubleshooting_docs]: ../../docs/troubleshooting.md ## Getting Started The following settings are optional: -- `verbosity` (default = `normal`): the verbosity of the logging export +- `verbosity` (default = `basic`): the verbosity of the logging export (detailed|normal|basic). When set to `detailed`, pipeline data is verbosely logged. - `sampling_initial` (default = `2`): number of messages initially logged each @@ -24,7 +33,7 @@ The following settings are optional: docs](https://godoc.org/go.uber.org/zap/zapcore#NewSampler) for more details. on how sampling parameters impact number of messages. -Example: +Example configuration: ```yaml exporters: @@ -34,6 +43,70 @@ exporters: sampling_thereafter: 200 ``` -[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib -[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol -[Development]: https://github.com/open-telemetry/opentelemetry-collector#in-development +## Verbosity levels + +The following subsections describe the output from the exporter depending on the configured verbosity level - `basic`, `normal` and `detailed`. +The default verbosity level is `basic`. + +### Basic verbosity + +With `verbosity: basic`, the exporter outputs a single-line summary of received data with a total count of telemetry records for every batch of received logs, metrics or traces. + +Here's an example output: + +```console +2023-11-10T22:49:03.510-0600 info TracesExporter {"kind": "exporter", "data_type": "traces", "name": "debug", "resource spans": 1, "spans": 2} +``` + +### Normal verbosity + +With `verbosity: normal`, the exporter's behavior is currently the same as with `verbosity: basic`. +See above for more details. + +### Detailed verbosity + +With `verbosity: detailed`, the exporter outputs all details of every telemetry record, typically writing multiple lines for every telemetry record. + +Here's an example output: + +```console +2023-11-10T22:49:03.510-0600 info TracesExporter {"kind": "exporter", "data_type": "traces", "name": "debug", "resource spans": 1, "spans": 2} +2023-11-10T22:49:03.510-0600 info ResourceSpans #0 +Resource SchemaURL: https://opentelemetry.io/schemas/1.4.0 +Resource attributes: + -> service.name: Str(telemetrygen) +ScopeSpans #0 +ScopeSpans SchemaURL: +InstrumentationScope telemetrygen +Span #0 + Trace ID : 3bde5d3ee82303571bba6e1136781fe4 + Parent ID : 5e9dcf9bac4acc1f + ID : 2cf3ef2899aba35c + Name : okey-dokey + Kind : Server + Start time : 2023-11-11 04:49:03.509369393 +0000 UTC + End time : 2023-11-11 04:49:03.50949377 +0000 UTC + Status code : Unset + Status message : +Attributes: + -> net.peer.ip: Str(1.2.3.4) + -> peer.service: Str(telemetrygen-client) +Span #1 + Trace ID : 3bde5d3ee82303571bba6e1136781fe4 + Parent ID : + ID : 5e9dcf9bac4acc1f + Name : lets-go + Kind : Client + Start time : 2023-11-11 04:49:03.50935117 +0000 UTC + End time : 2023-11-11 04:49:03.50949377 +0000 UTC + Status code : Unset + Status message : +Attributes: + -> net.peer.ip: Str(1.2.3.4) + -> peer.service: Str(telemetrygen-server) + {"kind": "exporter", "data_type": "traces", "name": "debug"} +``` + +## Warnings + +- Unstable Output Format: The output formats for all verbosity levels is not guaranteed and may be changed at any time without a breaking change. \ No newline at end of file diff --git a/exporter/debugexporter/doc.go b/exporter/debugexporter/doc.go index 9edb9ae096d..a079325f067 100644 --- a/exporter/debugexporter/doc.go +++ b/exporter/debugexporter/doc.go @@ -1,5 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +//go:generate mdatagen metadata.yaml + // Package debugexporter exports data to console as logs. package debugexporter // import "go.opentelemetry.io/collector/exporter/debugexporter" diff --git a/exporter/debugexporter/factory.go b/exporter/debugexporter/factory.go index 919ca32ade6..e9e75130dd6 100644 --- a/exporter/debugexporter/factory.go +++ b/exporter/debugexporter/factory.go @@ -9,12 +9,14 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configtelemetry" "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/debugexporter/internal/metadata" "go.opentelemetry.io/collector/exporter/internal/common" ) +// The value of "type" key in configuration. +var componentType = component.MustNewType("debug") + const ( - // The value of "type" key in configuration. - typeStr = "debug" defaultSamplingInitial = 2 defaultSamplingThereafter = 500 ) @@ -22,17 +24,17 @@ const ( // NewFactory creates a factory for Debug exporter func NewFactory() exporter.Factory { return exporter.NewFactory( - typeStr, + componentType, createDefaultConfig, - exporter.WithTraces(createTracesExporter, component.StabilityLevelDevelopment), - exporter.WithMetrics(createMetricsExporter, component.StabilityLevelDevelopment), - exporter.WithLogs(createLogsExporter, component.StabilityLevelDevelopment), + exporter.WithTraces(createTracesExporter, metadata.TracesStability), + exporter.WithMetrics(createMetricsExporter, metadata.MetricsStability), + exporter.WithLogs(createLogsExporter, metadata.LogsStability), ) } func createDefaultConfig() component.Config { return &Config{ - Verbosity: configtelemetry.LevelNormal, + Verbosity: configtelemetry.LevelBasic, SamplingInitial: defaultSamplingInitial, SamplingThereafter: defaultSamplingThereafter, } diff --git a/exporter/debugexporter/go.mod b/exporter/debugexporter/go.mod index 546b482fb54..6f838aa9ba2 100644 --- a/exporter/debugexporter/go.mod +++ b/exporter/debugexporter/go.mod @@ -1,51 +1,59 @@ module go.opentelemetry.io/collector/exporter/debugexporter -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 - go.opentelemetry.io/collector/confmap v0.85.0 - go.opentelemetry.io/collector/exporter v0.85.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 + go.opentelemetry.io/collector/confmap v0.96.0 + go.opentelemetry.io/collector/exporter v0.96.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 ) require ( + github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector v0.85.0 // indirect - go.opentelemetry.io/collector/consumer v0.85.0 // indirect - go.opentelemetry.io/collector/extension v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/sdk v1.18.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector v0.96.0 // indirect + go.opentelemetry.io/collector/config/configretry v0.96.0 // indirect + go.opentelemetry.io/collector/consumer v0.96.0 // indirect + go.opentelemetry.io/collector/extension v0.96.0 // indirect + go.opentelemetry.io/collector/pdata v1.3.0 // indirect + go.opentelemetry.io/collector/receiver v0.96.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -65,18 +73,8 @@ replace go.opentelemetry.io/collector/pdata => ../../pdata replace go.opentelemetry.io/collector/receiver => ../../receiver -replace go.opentelemetry.io/collector/semconv => ../../semconv - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension - replace go.opentelemetry.io/collector/extension => ../../extension -replace go.opentelemetry.io/collector/connector => ../../connector - -replace go.opentelemetry.io/collector/config/confignet => ../../config/confignet - -replace go.opentelemetry.io/collector/processor => ../../processor - replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry -replace go.opentelemetry.io/collector/service => ../../service +replace go.opentelemetry.io/collector/config/configretry => ../../config/configretry diff --git a/exporter/debugexporter/go.sum b/exporter/debugexporter/go.sum index 56e97816e75..dbdb92fd3bb 100644 --- a/exporter/debugexporter/go.sum +++ b/exporter/debugexporter/go.sum @@ -1,55 +1,28 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -58,15 +31,14 @@ github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NI github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -76,83 +48,64 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -160,38 +113,16 @@ 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/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/exporter/debugexporter/internal/metadata/generated_status.go b/exporter/debugexporter/internal/metadata/generated_status.go new file mode 100644 index 00000000000..18587820654 --- /dev/null +++ b/exporter/debugexporter/internal/metadata/generated_status.go @@ -0,0 +1,29 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("debug") + scopeName = "go.opentelemetry.io/collector/exporter/debugexporter" +) + +const ( + TracesStability = component.StabilityLevelDevelopment + MetricsStability = component.StabilityLevelDevelopment + LogsStability = component.StabilityLevelDevelopment +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} diff --git a/exporter/debugexporter/metadata.yaml b/exporter/debugexporter/metadata.yaml new file mode 100644 index 00000000000..4c60b9589e8 --- /dev/null +++ b/exporter/debugexporter/metadata.yaml @@ -0,0 +1,8 @@ +type: debug + +status: + class: exporter + stability: + development: [traces, metrics, logs] + distributions: [core, contrib] + warnings: [Unstable Output Format] diff --git a/exporter/debugexporter/package_test.go b/exporter/debugexporter/package_test.go new file mode 100644 index 00000000000..320777f1ab8 --- /dev/null +++ b/exporter/debugexporter/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package debugexporter + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/exporter/exporter_test.go b/exporter/exporter_test.go index eafa2c03f47..108e55fb582 100644 --- a/exporter/exporter_test.go +++ b/exporter/exporter_test.go @@ -16,12 +16,12 @@ import ( ) func TestNewFactory(t *testing.T) { - const typeStr = "test" + var testType = component.MustNewType("test") defaultCfg := struct{}{} factory := NewFactory( - typeStr, + testType, func() component.Config { return &defaultCfg }) - assert.EqualValues(t, typeStr, factory.Type()) + assert.EqualValues(t, testType, factory.Type()) assert.EqualValues(t, &defaultCfg, factory.CreateDefaultConfig()) _, err := factory.CreateTracesExporter(context.Background(), CreateSettings{}, &defaultCfg) assert.Error(t, err) @@ -32,15 +32,15 @@ func TestNewFactory(t *testing.T) { } func TestNewFactoryWithOptions(t *testing.T) { - const typeStr = "test" + var testType = component.MustNewType("test") defaultCfg := struct{}{} factory := NewFactory( - typeStr, + testType, func() component.Config { return &defaultCfg }, WithTraces(createTraces, component.StabilityLevelDevelopment), WithMetrics(createMetrics, component.StabilityLevelAlpha), WithLogs(createLogs, component.StabilityLevelDeprecated)) - assert.EqualValues(t, typeStr, factory.Type()) + assert.EqualValues(t, testType, factory.Type()) assert.EqualValues(t, &defaultCfg, factory.CreateDefaultConfig()) assert.Equal(t, component.StabilityLevelDevelopment, factory.TracesExporterStability()) @@ -63,8 +63,8 @@ func TestMakeFactoryMap(t *testing.T) { out map[component.Type]Factory } - p1 := NewFactory("p1", nil) - p2 := NewFactory("p2", nil) + p1 := NewFactory(component.MustNewType("p1"), nil) + p2 := NewFactory(component.MustNewType("p2"), nil) testCases := []testCase{ { name: "different names", @@ -76,7 +76,7 @@ func TestMakeFactoryMap(t *testing.T) { }, { name: "same name", - in: []Factory{p1, p2, NewFactory("p1", nil)}, + in: []Factory{p1, p2, NewFactory(component.MustNewType("p1"), nil)}, }, } @@ -97,9 +97,9 @@ func TestMakeFactoryMap(t *testing.T) { func TestBuilder(t *testing.T) { defaultCfg := struct{}{} factories, err := MakeFactoryMap([]Factory{ - NewFactory("err", nil), + NewFactory(component.MustNewType("err"), nil), NewFactory( - "all", + component.MustNewType("all"), func() component.Config { return &defaultCfg }, WithTraces(createTraces, component.StabilityLevelDevelopment), WithMetrics(createMetrics, component.StabilityLevelAlpha), @@ -115,21 +115,21 @@ func TestBuilder(t *testing.T) { }{ { name: "unknown", - id: component.NewID("unknown"), + id: component.MustNewID("unknown"), err: "exporter factory not available for: \"unknown\"", }, { name: "err", - id: component.NewID("err"), + id: component.MustNewID("err"), err: "telemetry type is not supported", }, { name: "all", - id: component.NewID("all"), + id: component.MustNewID("all"), }, { name: "all/named", - id: component.NewIDWithName("all", "named"), + id: component.MustNewIDWithName("all", "named"), }, } @@ -172,7 +172,7 @@ func TestBuilderMissingConfig(t *testing.T) { defaultCfg := struct{}{} factories, err := MakeFactoryMap([]Factory{ NewFactory( - "all", + component.MustNewType("all"), func() component.Config { return &defaultCfg }, WithTraces(createTraces, component.StabilityLevelDevelopment), WithMetrics(createMetrics, component.StabilityLevelAlpha), @@ -183,7 +183,7 @@ func TestBuilderMissingConfig(t *testing.T) { require.NoError(t, err) bErr := NewBuilder(map[component.ID]component.Config{}, factories) - missingID := component.NewIDWithName("all", "missing") + missingID := component.MustNewIDWithName("all", "missing") te, err := bErr.CreateTraces(context.Background(), createSettings(missingID)) assert.EqualError(t, err, "exporter \"all/missing\" is not configured") @@ -199,14 +199,14 @@ func TestBuilderMissingConfig(t *testing.T) { } func TestBuilderFactory(t *testing.T) { - factories, err := MakeFactoryMap([]Factory{NewFactory("foo", nil)}...) + factories, err := MakeFactoryMap([]Factory{NewFactory(component.MustNewType("foo"), nil)}...) require.NoError(t, err) - cfgs := map[component.ID]component.Config{component.NewID("foo"): struct{}{}} + cfgs := map[component.ID]component.Config{component.MustNewID("foo"): struct{}{}} b := NewBuilder(cfgs, factories) - assert.NotNil(t, b.Factory(component.NewID("foo").Type())) - assert.Nil(t, b.Factory(component.NewID("bar").Type())) + assert.NotNil(t, b.Factory(component.MustNewID("foo").Type())) + assert.Nil(t, b.Factory(component.MustNewID("bar").Type())) } var nopInstance = &nopExporter{ diff --git a/exporter/exporterhelper/README.md b/exporter/exporterhelper/README.md index ccbb7ac0096..06ce55ae626 100644 --- a/exporter/exporterhelper/README.md +++ b/exporter/exporterhelper/README.md @@ -12,7 +12,7 @@ The following configuration options can be modified: - `enabled` (default = true) - `initial_interval` (default = 5s): Time to wait after the first failure before retrying; ignored if `enabled` is `false` - `max_interval` (default = 30s): Is the upper bound on backoff; ignored if `enabled` is `false` - - `max_elapsed_time` (default = 300s): Is the maximum amount of time spent trying to send a batch; ignored if `enabled` is `false` + - `max_elapsed_time` (default = 300s): Is the maximum amount of time spent trying to send a batch; ignored if `enabled` is `false`. If set to 0, the retries are never stopped. - `sending_queue` - `enabled` (default = true) - `num_consumers` (default = 10): Number of consumers that dequeue batches; ignored if `enabled` is `false` @@ -22,7 +22,7 @@ The following configuration options can be modified: - `requests_per_second` is the average number of requests per seconds - `requests_per_batch` is the average number of requests per batch (if [the batch processor](https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor/batchprocessor) - is used, the metric `batch_send_size` can be used for estimation) + is used, the metric `send_batch_size` can be used for estimation) - `timeout` (default = 5s): Time to wait per individual attempt to send data to a backend The `initial_interval`, `max_interval`, `max_elapsed_time`, and `timeout` options accept @@ -38,7 +38,8 @@ valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". To use the persistent queue, the following setting needs to be set: - `sending_queue` - - `storage` (default = none): When set, enables persistence and uses the component specified as a storage extension for the persistent queue + - `storage` (default = none): When set, enables persistence and uses the component specified as a storage extension for the persistent queue. + There is no in-memory queue when set. The maximum number of batches stored to disk can be controlled using `sending_queue.queue_size` parameter (which, similarly as for in-memory buffering, defaults to 1000 batches). diff --git a/exporter/exporterhelper/common.go b/exporter/exporterhelper/common.go index 127bd66ec55..509570960e8 100644 --- a/exporter/exporterhelper/common.go +++ b/exporter/exporterhelper/common.go @@ -5,70 +5,41 @@ package exporterhelper // import "go.opentelemetry.io/collector/exporter/exporte import ( "context" - "time" + "go.uber.org/multierr" "go.uber.org/zap" - "go.uber.org/zap/zapcore" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/exporter" - "go.opentelemetry.io/collector/exporter/exporterhelper/internal" + "go.opentelemetry.io/collector/exporter/exporterqueue" ) // requestSender is an abstraction of a sender for a request independent of the type of the data (traces, metrics, logs). type requestSender interface { - start(ctx context.Context, host component.Host, set exporter.CreateSettings) error - shutdown() - send(req internal.Request) error + component.Component + send(context.Context, Request) error setNextSender(nextSender requestSender) } type baseRequestSender struct { + component.StartFunc + component.ShutdownFunc nextSender requestSender } var _ requestSender = (*baseRequestSender)(nil) -func (b *baseRequestSender) start(context.Context, component.Host, exporter.CreateSettings) error { - return nil -} - -func (b *baseRequestSender) shutdown() {} - -func (b *baseRequestSender) send(req internal.Request) error { - return b.nextSender.send(req) +func (b *baseRequestSender) send(ctx context.Context, req Request) error { + return b.nextSender.send(ctx, req) } func (b *baseRequestSender) setNextSender(nextSender requestSender) { b.nextSender = nextSender } -type obsrepSenderFactory func(obsrep *obsExporter) requestSender - -// baseRequest is a base implementation for the internal.Request. -type baseRequest struct { - ctx context.Context - processingFinishedCallback func() -} - -func (req *baseRequest) Context() context.Context { - return req.ctx -} - -func (req *baseRequest) SetContext(ctx context.Context) { - req.ctx = ctx -} - -func (req *baseRequest) SetOnProcessingFinished(callback func()) { - req.processingFinishedCallback = callback -} - -func (req *baseRequest) OnProcessingFinished() { - if req.processingFinishedCallback != nil { - req.processingFinishedCallback() - } -} +type obsrepSenderFactory func(obsrep *ObsReport) requestSender // Option apply changes to baseExporter. type Option func(*baseExporter) @@ -97,11 +68,15 @@ func WithTimeout(timeoutSettings TimeoutSettings) Option { } } -// WithRetry overrides the default RetrySettings for an exporter. -// The default RetrySettings is to disable retries. -func WithRetry(retrySettings RetrySettings) Option { +// WithRetry overrides the default configretry.BackOffConfig for an exporter. +// The default configretry.BackOffConfig is to disable retries. +func WithRetry(config configretry.BackOffConfig) Option { return func(o *baseExporter) { - o.retrySender = newRetrySender(o.set.ID, retrySettings, o.sampledLogger, o.onTemporaryFailure) + if !config.Enabled { + o.exportFailureMessage += " Try enabling retry_on_failure config option to retry on retryable errors." + return + } + o.retrySender = newRetrySender(config, o.set) } } @@ -110,20 +85,47 @@ func WithRetry(retrySettings RetrySettings) Option { // This option cannot be used with the new exporter helpers New[Traces|Metrics|Logs]RequestExporter. func WithQueue(config QueueSettings) Option { return func(o *baseExporter) { - if o.requestExporter { - panic("queueing is not available for the new request exporters yet") + if o.marshaler == nil || o.unmarshaler == nil { + panic("WithQueue option is not available for the new request exporters, use WithRequestQueue instead") + } + if !config.Enabled { + o.exportFailureMessage += " Try enabling sending_queue to survive temporary failures." + return + } + qf := exporterqueue.NewPersistentQueueFactory[Request](config.StorageID, exporterqueue.PersistentQueueSettings[Request]{ + Marshaler: o.marshaler, + Unmarshaler: o.unmarshaler, + }) + q := qf(context.Background(), exporterqueue.Settings{ + DataType: o.signal, + ExporterSettings: o.set, + }, exporterqueue.Config{ + Enabled: config.Enabled, + NumConsumers: config.NumConsumers, + QueueSize: config.QueueSize, + }) + o.queueSender = newQueueSender(q, o.set, config.NumConsumers, o.exportFailureMessage) + } +} + +// WithRequestQueue enables queueing for an exporter. +// This option should be used with the new exporter helpers New[Traces|Metrics|Logs]RequestExporter. +// 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 WithRequestQueue(cfg exporterqueue.Config, queueFactory exporterqueue.Factory[Request]) Option { + return func(o *baseExporter) { + if o.marshaler != nil || o.unmarshaler != nil { + panic("WithRequestQueue option must be used with the new request exporters only, use WithQueue instead") } - var queue internal.ProducerConsumerQueue - if config.Enabled { - if config.StorageID == nil { - queue = internal.NewBoundedMemoryQueue(config.QueueSize, config.NumConsumers) - } else { - queue = internal.NewPersistentQueue(config.QueueSize, config.NumConsumers, *config.StorageID, o.marshaler, o.unmarshaler) - } + if !cfg.Enabled { + o.exportFailureMessage += " Try enabling sending_queue to survive temporary failures." + return } - qs := newQueueSender(o.set.ID, o.signal, queue, o.sampledLogger) - o.queueSender = qs - o.setOnTemporaryFailure(qs.onTemporaryFailure) + set := exporterqueue.Settings{ + DataType: o.signal, + ExporterSettings: o.set, + } + o.queueSender = newQueueSender(queueFactory(context.Background(), set, cfg), o.set, cfg.NumConsumers, o.exportFailureMessage) } } @@ -136,19 +138,36 @@ func WithCapabilities(capabilities consumer.Capabilities) Option { } } +// withMarshaler is used to set the request marshaler for the new exporter helper. +// It must be provided as the first option when creating a new exporter helper. +func withMarshaler(marshaler exporterqueue.Marshaler[Request]) Option { + return func(o *baseExporter) { + o.marshaler = marshaler + } +} + +// withUnmarshaler is used to set the request unmarshaler for the new exporter helper. +// It must be provided as the first option when creating a new exporter helper. +func withUnmarshaler(unmarshaler exporterqueue.Unmarshaler[Request]) Option { + return func(o *baseExporter) { + o.unmarshaler = unmarshaler + } +} + // baseExporter contains common fields between different exporter types. type baseExporter struct { component.StartFunc component.ShutdownFunc - requestExporter bool - marshaler internal.RequestMarshaler - unmarshaler internal.RequestUnmarshaler - signal component.DataType + marshaler exporterqueue.Marshaler[Request] + unmarshaler exporterqueue.Unmarshaler[Request] + signal component.DataType - set exporter.CreateSettings - obsrep *obsExporter - sampledLogger *zap.Logger + set exporter.CreateSettings + obsrep *ObsReport + + // Message for the user to be added with an export failure message. + exportFailureMessage string // 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. @@ -158,35 +177,25 @@ type baseExporter struct { retrySender requestSender timeoutSender *timeoutSender // timeoutSender is always initialized. - // onTemporaryFailure is a function that is called when the retrySender is unable to send data to the next consumer. - onTemporaryFailure onRequestHandlingFinishedFunc - consumerOptions []consumer.Option } -// TODO: requestExporter, marshaler, and unmarshaler arguments can be removed when the old exporter helpers will be updated to call the new ones. -func newBaseExporter(set exporter.CreateSettings, signal component.DataType, requestExporter bool, marshaler internal.RequestMarshaler, - unmarshaler internal.RequestUnmarshaler, osf obsrepSenderFactory, options ...Option) (*baseExporter, error) { - - obsrep, err := newObsExporter(ObsReportSettings{ExporterID: set.ID, ExporterCreateSettings: set}, globalInstruments) +func newBaseExporter(set exporter.CreateSettings, signal component.DataType, osf obsrepSenderFactory, options ...Option) (*baseExporter, error) { + obsReport, err := NewObsReport(ObsReportSettings{ExporterID: set.ID, ExporterCreateSettings: set}) if err != nil { return nil, err } be := &baseExporter{ - requestExporter: requestExporter, - marshaler: marshaler, - unmarshaler: unmarshaler, - signal: signal, + signal: signal, queueSender: &baseRequestSender{}, - obsrepSender: osf(obsrep), + obsrepSender: osf(obsReport), retrySender: &baseRequestSender{}, timeoutSender: &timeoutSender{cfg: NewDefaultTimeoutSettings()}, - set: set, - obsrep: obsrep, - sampledLogger: createSampledLogger(set.Logger), + set: set, + obsrep: obsReport, } for _, op := range options { @@ -198,8 +207,13 @@ func newBaseExporter(set exporter.CreateSettings, signal component.DataType, req } // send sends the request using the first sender in the chain. -func (be *baseExporter) send(req internal.Request) error { - return be.queueSender.send(req) +func (be *baseExporter) send(ctx context.Context, req Request) error { + err := be.queueSender.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())) + } + return err } // connectSenders connects the senders in the predefined order. @@ -216,42 +230,15 @@ func (be *baseExporter) Start(ctx context.Context, host component.Host) error { } // If no error then start the queueSender. - return be.queueSender.start(ctx, host, be.set) + return be.queueSender.Start(ctx, host) } func (be *baseExporter) Shutdown(ctx context.Context) error { - // First shutdown the retry sender, so it can push any pending requests to back the queue. - be.retrySender.shutdown() - - // Then shutdown the queue sender. - be.queueSender.shutdown() - - // Last shutdown the wrapped exporter itself. - return be.ShutdownFunc.Shutdown(ctx) -} - -func (be *baseExporter) setOnTemporaryFailure(onTemporaryFailure onRequestHandlingFinishedFunc) { - be.onTemporaryFailure = onTemporaryFailure - if rs, ok := be.retrySender.(*retrySender); ok { - rs.onTemporaryFailure = onTemporaryFailure - } -} - -func createSampledLogger(logger *zap.Logger) *zap.Logger { - if logger.Core().Enabled(zapcore.DebugLevel) { - // Debugging is enabled. Don't do any sampling. - return logger - } - - // Create a logger that samples all messages to 1 per 10 seconds initially, - // and 1/100 of messages after that. - opts := zap.WrapCore(func(core zapcore.Core) zapcore.Core { - return zapcore.NewSamplerWithOptions( - core, - 10*time.Second, - 1, - 100, - ) - }) - return logger.WithOptions(opts) + 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 queue sender. + be.queueSender.Shutdown(ctx), + // Last shutdown the wrapped exporter itself. + be.ShutdownFunc.Shutdown(ctx)) } diff --git a/exporter/exporterhelper/common_test.go b/exporter/exporterhelper/common_test.go index 9889754e231..e3a584b17b1 100644 --- a/exporter/exporterhelper/common_test.go +++ b/exporter/exporterhelper/common_test.go @@ -9,39 +9,35 @@ import ( "testing" "github.com/stretchr/testify/require" - "go.opencensus.io/tag" "go.opentelemetry.io/otel/codes" sdktrace "go.opentelemetry.io/otel/sdk/trace" + "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/exporter" + "go.opentelemetry.io/collector/exporter/exporterqueue" "go.opentelemetry.io/collector/exporter/exportertest" ) var ( - defaultID = component.NewID("test") + defaultType = component.MustNewType("test") + defaultID = component.NewID(defaultType) defaultSettings = func() exporter.CreateSettings { set := exportertest.NewNopCreateSettings() set.ID = defaultID return set }() - exporterTag, _ = tag.NewKey("exporter") - defaultExporterTags = []tag.Tag{ - {Key: exporterTag, Value: "test"}, - } ) -func newNoopObsrepSender(_ *obsExporter) requestSender { +func newNoopObsrepSender(*ObsReport) requestSender { return &baseRequestSender{} } func TestBaseExporter(t *testing.T) { - be, err := newBaseExporter(defaultSettings, "", false, nil, nil, newNoopObsrepSender) - require.NoError(t, err) - require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - require.NoError(t, be.Shutdown(context.Background())) - be, err = newBaseExporter(defaultSettings, "", true, nil, nil, newNoopObsrepSender) + be, err := newBaseExporter(defaultSettings, defaultType, newNoopObsrepSender) require.NoError(t, err) require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) require.NoError(t, be.Shutdown(context.Background())) @@ -50,9 +46,9 @@ func TestBaseExporter(t *testing.T) { func TestBaseExporterWithOptions(t *testing.T) { want := errors.New("my error") be, err := newBaseExporter( - defaultSettings, "", false, nil, nil, newNoopObsrepSender, - WithStart(func(ctx context.Context, host component.Host) error { return want }), - WithShutdown(func(ctx context.Context) error { return want }), + defaultSettings, defaultType, newNoopObsrepSender, + WithStart(func(context.Context, component.Host) error { return want }), + WithShutdown(func(context.Context) error { return want }), WithTimeout(NewDefaultTimeoutSettings()), ) require.NoError(t, err) @@ -69,13 +65,34 @@ func checkStatus(t *testing.T, sd sdktrace.ReadOnlySpan, err error) { } } -func TestQueueRetryOptionsWithRequestExporter(t *testing.T) { - bs, err := newBaseExporter(exportertest.NewNopCreateSettings(), "", true, nil, nil, newNoopObsrepSender, - WithRetry(NewDefaultRetrySettings())) +func TestQueueOptionsWithRequestExporter(t *testing.T) { + bs, err := newBaseExporter(exportertest.NewNopCreateSettings(), defaultType, newNoopObsrepSender, + WithRetry(configretry.NewDefaultBackOffConfig())) require.Nil(t, err) - require.True(t, bs.requestExporter) + require.Nil(t, bs.marshaler) + require.Nil(t, bs.unmarshaler) + require.Panics(t, func() { + _, _ = newBaseExporter(exportertest.NewNopCreateSettings(), defaultType, newNoopObsrepSender, + WithRetry(configretry.NewDefaultBackOffConfig()), WithQueue(NewDefaultQueueSettings())) + }) require.Panics(t, func() { - _, _ = newBaseExporter(exportertest.NewNopCreateSettings(), "", true, nil, nil, newNoopObsrepSender, - WithRetry(NewDefaultRetrySettings()), WithQueue(NewDefaultQueueSettings())) + _, _ = newBaseExporter(exportertest.NewNopCreateSettings(), defaultType, newNoopObsrepSender, + withMarshaler(mockRequestMarshaler), withUnmarshaler(mockRequestUnmarshaler(&mockRequest{})), + WithRetry(configretry.NewDefaultBackOffConfig()), + WithRequestQueue(exporterqueue.NewDefaultConfig(), exporterqueue.NewMemoryQueueFactory[Request]())) }) } + +func TestBaseExporterLogging(t *testing.T) { + set := exportertest.NewNopCreateSettings() + logger, observed := observer.New(zap.DebugLevel) + set.Logger = zap.New(logger) + rCfg := configretry.NewDefaultBackOffConfig() + rCfg.Enabled = false + bs, err := newBaseExporter(set, defaultType, newNoopObsrepSender, WithRetry(rCfg)) + require.Nil(t, err) + sendErr := bs.send(context.Background(), newErrorRequest()) + require.Error(t, sendErr) + + require.Len(t, observed.FilterLevelExact(zap.ErrorLevel).All(), 1) +} diff --git a/exporter/exporterhelper/constants.go b/exporter/exporterhelper/constants.go index a7cfca32aca..57829f08c04 100644 --- a/exporter/exporterhelper/constants.go +++ b/exporter/exporterhelper/constants.go @@ -18,10 +18,10 @@ var ( errNilPushMetricsData = errors.New("nil PushMetrics") // errNilPushLogsData is returned when a nil PushLogs is given. errNilPushLogsData = errors.New("nil PushLogs") - // errNilTracesConverter is returned when a nil TracesConverter is given. - errNilTracesConverter = errors.New("nil TracesConverter") - // errNilMetricsConverter is returned when a nil MetricsConverter is given. - errNilMetricsConverter = errors.New("nil MetricsConverter") - // errNilLogsConverter is returned when a nil LogsConverter is given. - errNilLogsConverter = errors.New("nil LogsConverter") + // errNilTracesConverter is returned when a nil RequestFromTracesFunc is given. + errNilTracesConverter = errors.New("nil RequestFromTracesFunc") + // errNilMetricsConverter is returned when a nil RequestFromMetricsFunc is given. + errNilMetricsConverter = errors.New("nil RequestFromMetricsFunc") + // errNilLogsConverter is returned when a nil RequestFromLogsFunc is given. + errNilLogsConverter = errors.New("nil RequestFromLogsFunc") ) diff --git a/exporter/exporterhelper/internal/bounded_memory_queue.go b/exporter/exporterhelper/internal/bounded_memory_queue.go deleted file mode 100644 index c7f8655338a..00000000000 --- a/exporter/exporterhelper/internal/bounded_memory_queue.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright The OpenTelemetry Authors -// Copyright (c) 2019 The Jaeger Authors. -// Copyright (c) 2017 Uber Technologies, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package internal // import "go.opentelemetry.io/collector/exporter/exporterhelper/internal" - -import ( - "context" - "sync" - "sync/atomic" - - "go.opentelemetry.io/collector/component" -) - -// boundedMemoryQueue implements a producer-consumer exchange similar to a ring buffer queue, -// where the queue is bounded and if it fills up due to slow consumers, the new items written by -// the producer are dropped. -type boundedMemoryQueue struct { - stopWG sync.WaitGroup - size *atomic.Uint32 - stopped *atomic.Bool - items chan Request - capacity uint32 - numConsumers int -} - -// NewBoundedMemoryQueue constructs the new queue of specified capacity, and with an optional -// callback for dropped items (e.g. useful to emit metrics). -func NewBoundedMemoryQueue(capacity int, numConsumers int) ProducerConsumerQueue { - return &boundedMemoryQueue{ - items: make(chan Request, capacity), - stopped: &atomic.Bool{}, - size: &atomic.Uint32{}, - capacity: uint32(capacity), - numConsumers: numConsumers, - } -} - -// StartConsumers starts a given number of goroutines consuming items from the queue -// and passing them into the consumer callback. -func (q *boundedMemoryQueue) Start(_ context.Context, _ component.Host, set QueueSettings) error { - var startWG sync.WaitGroup - for i := 0; i < q.numConsumers; i++ { - q.stopWG.Add(1) - startWG.Add(1) - go func() { - startWG.Done() - defer q.stopWG.Done() - for item := range q.items { - q.size.Add(^uint32(0)) - set.Callback(item) - } - }() - } - startWG.Wait() - return nil -} - -// Produce is used by the producer to submit new item to the queue. Returns false in case of queue overflow. -func (q *boundedMemoryQueue) Produce(item Request) bool { - if q.stopped.Load() { - return false - } - - // we might have two concurrent backing queues at the moment - // their combined size is stored in q.size, and their combined capacity - // should match the capacity of the new queue - if q.size.Load() >= q.capacity { - return false - } - - q.size.Add(1) - select { - case q.items <- item: - return true - default: - // should not happen, as overflows should have been captured earlier - q.size.Add(^uint32(0)) - return false - } -} - -// Stop stops all consumers, as well as the length reporter if started, -// and releases the items channel. It blocks until all consumers have stopped. -func (q *boundedMemoryQueue) Stop() { - q.stopped.Store(true) // disable producer - close(q.items) - q.stopWG.Wait() -} - -// Size returns the current size of the queue -func (q *boundedMemoryQueue) Size() int { - return int(q.size.Load()) -} - -func (q *boundedMemoryQueue) Capacity() int { - return int(q.capacity) -} - -func (q *boundedMemoryQueue) IsPersistent() bool { - return false -} diff --git a/exporter/exporterhelper/internal/bounded_memory_queue_test.go b/exporter/exporterhelper/internal/bounded_memory_queue_test.go deleted file mode 100644 index 9fe809cf2a2..00000000000 --- a/exporter/exporterhelper/internal/bounded_memory_queue_test.go +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright The OpenTelemetry Authors -// Copyright (c) 2019 The Jaeger Authors. -// Copyright (c) 2017 Uber Technologies, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package internal - -import ( - "context" - "reflect" - "sync" - "sync/atomic" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/component/componenttest" - "go.opentelemetry.io/collector/exporter/exportertest" -) - -func newNopQueueSettings(callback func(item Request)) QueueSettings { - return QueueSettings{ - CreateSettings: exportertest.NewNopCreateSettings(), - DataType: component.DataTypeMetrics, - Callback: callback, - } -} - -type stringRequest struct { - Request - str string -} - -func newStringRequest(str string) Request { - return stringRequest{str: str} -} - -// In this test we run a queue with capacity 1 and a single consumer. -// We want to test the overflow behavior, so we block the consumer -// by holding a startLock before submitting items to the queue. -func helper(t *testing.T, startConsumers func(q ProducerConsumerQueue, consumerFn func(item Request))) { - q := NewBoundedMemoryQueue(1, 1) - - var startLock sync.Mutex - - startLock.Lock() // block consumers - consumerState := newConsumerState(t) - - startConsumers(q, func(item Request) { - consumerState.record(item.(stringRequest).str) - - // block further processing until startLock is released - startLock.Lock() - //nolint:staticcheck // SA2001 ignore this! - startLock.Unlock() - }) - - assert.True(t, q.Produce(newStringRequest("a"))) - - // at this point "a" may or may not have been received by the consumer go-routine - // so let's make sure it has been - consumerState.waitToConsumeOnce() - - // at this point the item must have been read off the queue, but the consumer is blocked - assert.Equal(t, 0, q.Size()) - consumerState.assertConsumed(map[string]bool{ - "a": true, - }) - - // produce two more items. The first one should be accepted, but not consumed. - assert.True(t, q.Produce(newStringRequest("b"))) - assert.Equal(t, 1, q.Size()) - // the second should be rejected since the queue is full - assert.False(t, q.Produce(newStringRequest("c"))) - assert.Equal(t, 1, q.Size()) - - startLock.Unlock() // unblock consumer - - consumerState.assertConsumed(map[string]bool{ - "a": true, - "b": true, - }) - - // now that consumers are unblocked, we can add more items - expected := map[string]bool{ - "a": true, - "b": true, - } - for _, item := range []string{"d", "e", "f"} { - assert.True(t, q.Produce(newStringRequest(item))) - expected[item] = true - consumerState.assertConsumed(expected) - } - - q.Stop() - assert.False(t, q.Produce(newStringRequest("x")), "cannot push to closed queue") -} - -func TestBoundedQueue(t *testing.T) { - helper(t, func(q ProducerConsumerQueue, consumerFn func(item Request)) { - assert.NoError(t, q.Start(context.Background(), componenttest.NewNopHost(), newNopQueueSettings(consumerFn))) - }) -} - -// In this test we run a queue with many items and a slow consumer. -// When the queue is stopped, the remaining items should be processed. -// Due to the way q.Stop() waits for all consumers to finish, the -// same lock strategy use above will not work, as calling Unlock -// only after Stop will mean the consumers are still locked while -// trying to perform the final consumptions. -func TestShutdownWhileNotEmpty(t *testing.T) { - q := NewBoundedMemoryQueue(10, 1) - - consumerState := newConsumerState(t) - - assert.NoError(t, q.Start(context.Background(), componenttest.NewNopHost(), newNopQueueSettings(func(item Request) { - consumerState.record(item.(stringRequest).str) - time.Sleep(1 * time.Second) - }))) - - q.Produce(newStringRequest("a")) - q.Produce(newStringRequest("b")) - q.Produce(newStringRequest("c")) - q.Produce(newStringRequest("d")) - q.Produce(newStringRequest("e")) - q.Produce(newStringRequest("f")) - q.Produce(newStringRequest("g")) - q.Produce(newStringRequest("h")) - q.Produce(newStringRequest("i")) - q.Produce(newStringRequest("j")) - - q.Stop() - - assert.False(t, q.Produce(newStringRequest("x")), "cannot push to closed queue") - consumerState.assertConsumed(map[string]bool{ - "a": true, - "b": true, - "c": true, - "d": true, - "e": true, - "f": true, - "g": true, - "h": true, - "i": true, - "j": true, - }) - assert.Equal(t, 0, q.Size()) -} - -type consumerState struct { - sync.Mutex - t *testing.T - consumed map[string]bool - consumedOnce *atomic.Bool -} - -func newConsumerState(t *testing.T) *consumerState { - return &consumerState{ - t: t, - consumed: make(map[string]bool), - consumedOnce: &atomic.Bool{}, - } -} - -func (s *consumerState) record(val string) { - s.Lock() - defer s.Unlock() - s.consumed[val] = true - s.consumedOnce.Store(true) -} - -func (s *consumerState) snapshot() map[string]bool { - s.Lock() - defer s.Unlock() - out := make(map[string]bool) - for k, v := range s.consumed { - out[k] = v - } - return out -} - -func (s *consumerState) waitToConsumeOnce() { - require.Eventually(s.t, s.consumedOnce.Load, 2*time.Second, 10*time.Millisecond, "expected to consumer once") -} - -func (s *consumerState) assertConsumed(expected map[string]bool) { - for i := 0; i < 1000; i++ { - if snapshot := s.snapshot(); !reflect.DeepEqual(snapshot, expected) { - time.Sleep(time.Millisecond) - } - } - assert.Equal(s.t, expected, s.snapshot()) -} - -func TestZeroSize(t *testing.T) { - q := NewBoundedMemoryQueue(0, 1) - - err := q.Start(context.Background(), componenttest.NewNopHost(), newNopQueueSettings(func(item Request) {})) - assert.NoError(t, err) - - assert.False(t, q.Produce(newStringRequest("a"))) // in process -} diff --git a/exporter/exporterhelper/internal/mock_storage.go b/exporter/exporterhelper/internal/mock_storage.go deleted file mode 100644 index 0c544f57238..00000000000 --- a/exporter/exporterhelper/internal/mock_storage.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package internal // import "go.opentelemetry.io/collector/exporter/exporterhelper/internal" - -import ( - "context" - "errors" - "sync" - - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/extension/experimental/storage" -) - -type mockStorageExtension struct { - component.StartFunc - component.ShutdownFunc - getClientError error -} - -func (m mockStorageExtension) GetClient(_ context.Context, _ component.Kind, _ component.ID, _ string) (storage.Client, error) { - if m.getClientError != nil { - return nil, m.getClientError - } - return &mockStorageClient{st: map[string][]byte{}}, nil -} - -func NewMockStorageExtension(getClientError error) storage.Extension { - return &mockStorageExtension{getClientError: getClientError} -} - -type mockStorageClient struct { - st map[string][]byte - mux sync.Mutex - closeCounter uint64 -} - -func (m *mockStorageClient) Get(_ context.Context, s string) ([]byte, error) { - m.mux.Lock() - defer m.mux.Unlock() - - val, found := m.st[s] - if !found { - return nil, nil - } - - return val, nil -} - -func (m *mockStorageClient) Set(_ context.Context, s string, bytes []byte) error { - m.mux.Lock() - defer m.mux.Unlock() - - m.st[s] = bytes - return nil -} - -func (m *mockStorageClient) Delete(_ context.Context, s string) error { - m.mux.Lock() - defer m.mux.Unlock() - - delete(m.st, s) - return nil -} - -func (m *mockStorageClient) Close(_ context.Context) error { - m.closeCounter++ - return nil -} - -func (m *mockStorageClient) Batch(_ context.Context, ops ...storage.Operation) error { - m.mux.Lock() - defer m.mux.Unlock() - - for _, op := range ops { - switch op.Type { - case storage.Get: - op.Value = m.st[op.Key] - case storage.Set: - m.st[op.Key] = op.Value - case storage.Delete: - delete(m.st, op.Key) - default: - return errors.New("wrong operation type") - } - } - - return nil -} - -func (m *mockStorageClient) getCloseCount() uint64 { - return m.closeCounter -} diff --git a/exporter/exporterhelper/internal/persistent_queue.go b/exporter/exporterhelper/internal/persistent_queue.go deleted file mode 100644 index ba1dcc67230..00000000000 --- a/exporter/exporterhelper/internal/persistent_queue.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package internal // import "go.opentelemetry.io/collector/exporter/exporterhelper/internal" - -import ( - "context" - "errors" - "fmt" - "sync" - - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/extension/experimental/storage" -) - -var ( - // Monkey patching for unit test - stopStorage = func(queue *persistentQueue) { - queue.storage.stop() - } - errNoStorageClient = errors.New("no storage client extension found") - errWrongExtensionType = errors.New("requested extension is not a storage extension") -) - -// persistentQueue holds the queue backed by file storage -type persistentQueue struct { - stopWG sync.WaitGroup - stopOnce sync.Once - stopChan chan struct{} - storageID component.ID - storage *persistentContiguousStorage - capacity uint64 - numConsumers int - marshaler RequestMarshaler - unmarshaler RequestUnmarshaler -} - -// buildPersistentStorageName returns a name that is constructed out of queue name and signal type. This is done -// to avoid conflicts between different signals, which require unique persistent storage name -func buildPersistentStorageName(name string, signal component.DataType) string { - return fmt.Sprintf("%s-%s", name, signal) -} - -// NewPersistentQueue creates a new queue backed by file storage; name and signal must be a unique combination that identifies the queue storage -func NewPersistentQueue(capacity int, numConsumers int, storageID component.ID, marshaler RequestMarshaler, - unmarshaler RequestUnmarshaler) ProducerConsumerQueue { - return &persistentQueue{ - capacity: uint64(capacity), - numConsumers: numConsumers, - storageID: storageID, - marshaler: marshaler, - unmarshaler: unmarshaler, - stopChan: make(chan struct{}), - } -} - -// Start starts the persistentQueue with the given number of consumers. -func (pq *persistentQueue) Start(ctx context.Context, host component.Host, set QueueSettings) error { - storageClient, err := toStorageClient(ctx, pq.storageID, host, set.ID, set.DataType) - if err != nil { - return err - } - storageName := buildPersistentStorageName(set.ID.Name(), set.DataType) - pq.storage = newPersistentContiguousStorage(ctx, storageName, storageClient, set.Logger, pq.capacity, pq.marshaler, pq.unmarshaler) - for i := 0; i < pq.numConsumers; i++ { - pq.stopWG.Add(1) - go func() { - defer pq.stopWG.Done() - for { - select { - case req := <-pq.storage.get(): - set.Callback(req) - case <-pq.stopChan: - return - } - } - }() - } - return nil -} - -// Produce adds an item to the queue and returns true if it was accepted -func (pq *persistentQueue) Produce(item Request) bool { - err := pq.storage.put(item) - return err == nil -} - -// Stop stops accepting items, shuts down the queue and closes the persistent queue -func (pq *persistentQueue) Stop() { - pq.stopOnce.Do(func() { - // stop the consumers before the storage or the successful processing result will fail to write to persistent storage - close(pq.stopChan) - pq.stopWG.Wait() - stopStorage(pq) - }) -} - -// Size returns the current depth of the queue, excluding the item already in the storage channel (if any) -func (pq *persistentQueue) Size() int { - return int(pq.storage.size()) -} - -func (pq *persistentQueue) Capacity() int { - return int(pq.capacity) -} - -func (pq *persistentQueue) IsPersistent() bool { - return true -} - -func toStorageClient(ctx context.Context, storageID component.ID, host component.Host, ownerID component.ID, signal component.DataType) (storage.Client, error) { - extension, err := getStorageExtension(host.GetExtensions(), storageID) - if err != nil { - return nil, err - } - - client, err := extension.GetClient(ctx, component.KindExporter, ownerID, string(signal)) - if err != nil { - return nil, err - } - - return client, err -} - -func getStorageExtension(extensions map[component.ID]component.Component, storageID component.ID) (storage.Extension, error) { - if ext, found := extensions[storageID]; found { - if storageExt, ok := ext.(storage.Extension); ok { - return storageExt, nil - } - return nil, errWrongExtensionType - } - return nil, errNoStorageClient -} diff --git a/exporter/exporterhelper/internal/persistent_queue_test.go b/exporter/exporterhelper/internal/persistent_queue_test.go deleted file mode 100644 index 08570e92342..00000000000 --- a/exporter/exporterhelper/internal/persistent_queue_test.go +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package internal - -import ( - "context" - "errors" - "fmt" - "strconv" - "sync/atomic" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/extension/experimental/storage" - "go.opentelemetry.io/collector/extension/extensiontest" - "go.opentelemetry.io/collector/pdata/pcommon" - "go.opentelemetry.io/collector/pdata/ptrace" -) - -type mockHost struct { - component.Host - ext map[component.ID]component.Component -} - -func (nh *mockHost) GetExtensions() map[component.ID]component.Component { - return nh.ext -} - -// createTestQueue creates and starts a fake queue with the given capacity and number of consumers. -func createTestQueue(t *testing.T, capacity, numConsumers int, callback func(item Request)) ProducerConsumerQueue { - pq := NewPersistentQueue(capacity, numConsumers, component.ID{}, newFakeTracesRequestMarshalerFunc(), - newFakeTracesRequestUnmarshalerFunc()) - host := &mockHost{ext: map[component.ID]component.Component{ - {}: NewMockStorageExtension(nil), - }} - err := pq.Start(context.Background(), host, newNopQueueSettings(callback)) - require.NoError(t, err) - t.Cleanup(pq.Stop) - return pq -} - -func TestPersistentQueue_Capacity(t *testing.T) { - for i := 0; i < 100; i++ { - pq := NewPersistentQueue(5, 1, component.ID{}, newFakeTracesRequestMarshalerFunc(), - newFakeTracesRequestUnmarshalerFunc()) - host := &mockHost{ext: map[component.ID]component.Component{ - {}: NewMockStorageExtension(nil), - }} - err := pq.Start(context.Background(), host, newNopQueueSettings(func(req Request) {})) - require.NoError(t, err) - - // Stop consumer to imitate queue overflow - close(pq.(*persistentQueue).stopChan) - pq.(*persistentQueue).stopWG.Wait() - - assert.Equal(t, 0, pq.Size()) - - traces := newTraces(1, 10) - req := newFakeTracesRequest(traces) - - for i := 0; i < 10; i++ { - result := pq.Produce(req) - if i < 6 { - assert.True(t, result) - } else { - assert.False(t, result) - } - - // Let's make sure the loop picks the first element into the channel, - // so the capacity could be used in full - if i == 0 { - assert.Eventually(t, func() bool { - return pq.Size() == 0 - }, 5*time.Second, 10*time.Millisecond) - } - } - assert.Equal(t, 5, pq.Size()) - stopStorage(pq.(*persistentQueue)) - } -} - -func TestPersistentQueue_Close(t *testing.T) { - wq := createTestQueue(t, 1001, 100, func(item Request) {}) - traces := newTraces(1, 10) - req := newFakeTracesRequest(traces) - - for i := 0; i < 1000; i++ { - wq.Produce(req) - } - // This will close the queue very quickly, consumers might not be able to consume anything and should finish gracefully - assert.NotPanics(t, func() { - wq.Stop() - }) - // The additional stop should not panic - assert.NotPanics(t, func() { - wq.Stop() - }) -} - -// Verify storage closes after queue consumers. If not in this order, successfully consumed items won't be updated in storage -func TestPersistentQueue_Close_StorageCloseAfterConsumers(t *testing.T) { - wq := createTestQueue(t, 1001, 1, func(item Request) {}) - traces := newTraces(1, 10) - - lastRequestProcessedTime := time.Now() - req := newFakeTracesRequest(traces) - req.processingFinishedCallback = func() { - lastRequestProcessedTime = time.Now() - } - - fnBefore := stopStorage - stopStorageTime := time.Now() - stopStorage = func(queue *persistentQueue) { - stopStorageTime = time.Now() - queue.storage.stop() - } - - for i := 0; i < 1000; i++ { - wq.Produce(req) - } - assert.NotPanics(t, func() { - wq.Stop() - }) - assert.True(t, stopStorageTime.After(lastRequestProcessedTime), "storage stop time should be after last request processed time") - stopStorage = fnBefore -} - -func TestPersistentQueue_ConsumersProducers(t *testing.T) { - cases := []struct { - numMessagesProduced int - numConsumers int - }{ - { - numMessagesProduced: 1, - numConsumers: 1, - }, - { - numMessagesProduced: 100, - numConsumers: 1, - }, - { - numMessagesProduced: 100, - numConsumers: 3, - }, - { - numMessagesProduced: 1, - numConsumers: 100, - }, - { - numMessagesProduced: 100, - numConsumers: 100, - }, - } - - for _, c := range cases { - t.Run(fmt.Sprintf("#messages: %d #consumers: %d", c.numMessagesProduced, c.numConsumers), func(t *testing.T) { - traces := newTraces(1, 10) - req := newFakeTracesRequest(traces) - - numMessagesConsumed := &atomic.Int32{} - tq := createTestQueue(t, 1000, c.numConsumers, func(item Request) { - if item != nil { - numMessagesConsumed.Add(int32(1)) - } - }) - - for i := 0; i < c.numMessagesProduced; i++ { - tq.Produce(req) - } - - assert.Eventually(t, func() bool { - return c.numMessagesProduced == int(numMessagesConsumed.Load()) - }, 5*time.Second, 10*time.Millisecond) - }) - } -} - -func newTraces(numTraces int, numSpans int) ptrace.Traces { - traces := ptrace.NewTraces() - batch := traces.ResourceSpans().AppendEmpty() - batch.Resource().Attributes().PutStr("resource-attr", "some-resource") - batch.Resource().Attributes().PutInt("num-traces", int64(numTraces)) - batch.Resource().Attributes().PutInt("num-spans", int64(numSpans)) - - for i := 0; i < numTraces; i++ { - traceID := pcommon.TraceID([16]byte{1, 2, 3, byte(i)}) - ils := batch.ScopeSpans().AppendEmpty() - for j := 0; j < numSpans; j++ { - span := ils.Spans().AppendEmpty() - span.SetTraceID(traceID) - span.SetSpanID([8]byte{1, 2, 3, byte(j)}) - span.SetName("should-not-be-changed") - span.Attributes().PutInt("int-attribute", int64(j)) - span.Attributes().PutStr("str-attribute-1", "foobar") - span.Attributes().PutStr("str-attribute-2", "fdslafjasdk12312312jkl") - span.Attributes().PutStr("str-attribute-3", "AbcDefGeKKjkfdsafasdfsdasdf") - span.Attributes().PutStr("str-attribute-4", "xxxxxx") - span.Attributes().PutStr("str-attribute-5", "abcdef") - } - } - - return traces -} - -func TestToStorageClient(t *testing.T) { - getStorageClientError := errors.New("unable to create storage client") - testCases := []struct { - desc string - storage storage.Extension - numStorages int - storageIndex int - expectedError error - getClientError error - }{ - { - desc: "obtain storage extension by name", - numStorages: 2, - storageIndex: 0, - expectedError: nil, - }, - { - desc: "fail on not existing storage extension", - numStorages: 2, - storageIndex: 100, - expectedError: errNoStorageClient, - }, - { - desc: "invalid extension type", - numStorages: 2, - storageIndex: 100, - expectedError: errNoStorageClient, - }, - { - desc: "fail on error getting storage client from extension", - numStorages: 1, - storageIndex: 0, - expectedError: getStorageClientError, - getClientError: getStorageClientError, - }, - } - - for _, tC := range testCases { - t.Run(tC.desc, func(t *testing.T) { - storageID := component.NewIDWithName("file_storage", strconv.Itoa(tC.storageIndex)) - - var extensions = map[component.ID]component.Component{} - for i := 0; i < tC.numStorages; i++ { - extensions[component.NewIDWithName("file_storage", strconv.Itoa(i))] = NewMockStorageExtension(tC.getClientError) - } - host := &mockHost{ext: extensions} - ownerID := component.NewID("foo_exporter") - - // execute - client, err := toStorageClient(context.Background(), storageID, host, ownerID, component.DataTypeTraces) - - // verify - if tC.expectedError != nil { - assert.ErrorIs(t, err, tC.expectedError) - assert.Nil(t, client) - } else { - assert.NoError(t, err) - assert.NotNil(t, client) - } - }) - } -} - -func TestInvalidStorageExtensionType(t *testing.T) { - storageID := component.NewIDWithName("extension", "extension") - - // make a test extension - factory := extensiontest.NewNopFactory() - extConfig := factory.CreateDefaultConfig() - settings := extensiontest.NewNopCreateSettings() - extension, err := factory.CreateExtension(context.Background(), settings, extConfig) - assert.NoError(t, err) - var extensions = map[component.ID]component.Component{ - storageID: extension, - } - host := &mockHost{ext: extensions} - ownerID := component.NewID("foo_exporter") - - // execute - client, err := toStorageClient(context.Background(), storageID, host, ownerID, component.DataTypeTraces) - - // we should get an error about the extension type - assert.ErrorIs(t, err, errWrongExtensionType) - assert.Nil(t, client) -} diff --git a/exporter/exporterhelper/internal/persistent_storage.go b/exporter/exporterhelper/internal/persistent_storage.go deleted file mode 100644 index 49f204bbb0d..00000000000 --- a/exporter/exporterhelper/internal/persistent_storage.go +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package internal // import "go.opentelemetry.io/collector/exporter/exporterhelper/internal" - -import ( - "context" - "errors" - "fmt" - "strconv" - "sync" - "sync/atomic" - - "go.uber.org/zap" - - "go.opentelemetry.io/collector/extension/experimental/storage" -) - -// persistentContiguousStorage provides a persistent queue implementation backed by file storage extension -// -// Write index describes the position at which next item is going to be stored. -// Read index describes which item needs to be read next. -// When Write index = Read index, no elements are in the queue. -// -// The items currently dispatched by consumers are not deleted until the processing is finished. -// Their list is stored under a separate key. -// -// ┌───────file extension-backed queue───────┐ -// │ │ -// │ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ │ -// │ n+1 │ n │ ... │ 4 │ │ 3 │ │ 2 │ │ 1 │ │ -// │ └───┘ └───┘ └─x─┘ └─|─┘ └─x─┘ │ -// │ x | x │ -// └───────────────────────x─────|─────x─────┘ -// ▲ ▲ x | x -// │ │ x | xxxx deleted -// │ │ x | -// write read x └── currently dispatched item -// index index x -// xxxx deleted -type persistentContiguousStorage struct { - logger *zap.Logger - queueName string - client storage.Client - unmarshaler RequestUnmarshaler - marshaler RequestMarshaler - - putChan chan struct{} - stopChan chan struct{} - stopOnce sync.Once - capacity uint64 - - reqChan chan Request - - mu sync.Mutex - readIndex itemIndex - writeIndex itemIndex - currentlyDispatchedItems []itemIndex - - itemsCount *atomic.Uint64 -} - -type itemIndex uint64 - -const ( - zapKey = "key" - zapQueueNameKey = "queueName" - zapErrorCount = "errorCount" - zapNumberOfItems = "numberOfItems" - - readIndexKey = "ri" - writeIndexKey = "wi" - currentlyDispatchedItemsKey = "di" -) - -var ( - errMaxCapacityReached = errors.New("max capacity reached") - errValueNotSet = errors.New("value not set") - errKeyNotPresentInBatch = errors.New("key was not present in get batchStruct") -) - -// newPersistentContiguousStorage creates a new file-storage extension backed queue; -// queueName parameter must be a unique value that identifies the queue. -func newPersistentContiguousStorage(ctx context.Context, queueName string, client storage.Client, - logger *zap.Logger, capacity uint64, marshaler RequestMarshaler, unmarshaler RequestUnmarshaler) *persistentContiguousStorage { - pcs := &persistentContiguousStorage{ - logger: logger, - client: client, - queueName: queueName, - unmarshaler: unmarshaler, - marshaler: marshaler, - capacity: capacity, - putChan: make(chan struct{}, capacity), - reqChan: make(chan Request), - stopChan: make(chan struct{}), - itemsCount: &atomic.Uint64{}, - } - - initPersistentContiguousStorage(ctx, pcs) - notDispatchedReqs := pcs.retrieveNotDispatchedReqs(context.Background()) - - // Make sure the leftover requests are handled - pcs.enqueueNotDispatchedReqs(notDispatchedReqs) - - // Ensure the communication channel has the same size as the queue - // We might already have items here from requeueing non-dispatched requests - for len(pcs.putChan) < int(pcs.size()) { - pcs.putChan <- struct{}{} - } - - // start the loop which moves items from storage to the outbound channel - go pcs.loop() - - return pcs -} - -func initPersistentContiguousStorage(ctx context.Context, pcs *persistentContiguousStorage) { - var writeIndex itemIndex - var readIndex itemIndex - batch, err := newBatch(pcs).get(readIndexKey, writeIndexKey).execute(ctx) - - if err == nil { - readIndex, err = batch.getItemIndexResult(readIndexKey) - } - - if err == nil { - writeIndex, err = batch.getItemIndexResult(writeIndexKey) - } - - if err != nil { - if errors.Is(err, errValueNotSet) { - pcs.logger.Info("Initializing new persistent queue", zap.String(zapQueueNameKey, pcs.queueName)) - } else { - pcs.logger.Error("Failed getting read/write index, starting with new ones", - zap.String(zapQueueNameKey, pcs.queueName), - zap.Error(err)) - } - pcs.readIndex = 0 - pcs.writeIndex = 0 - } else { - pcs.readIndex = readIndex - pcs.writeIndex = writeIndex - } - - pcs.itemsCount.Store(uint64(pcs.writeIndex - pcs.readIndex)) -} - -func (pcs *persistentContiguousStorage) enqueueNotDispatchedReqs(reqs []Request) { - if len(reqs) > 0 { - errCount := 0 - for _, req := range reqs { - if req == nil || pcs.put(req) != nil { - errCount++ - } - } - if errCount > 0 { - pcs.logger.Error("Errors occurred while moving items for dispatching back to queue", - zap.String(zapQueueNameKey, pcs.queueName), - zap.Int(zapNumberOfItems, len(reqs)), zap.Int(zapErrorCount, errCount)) - - } else { - pcs.logger.Info("Moved items for dispatching back to queue", - zap.String(zapQueueNameKey, pcs.queueName), - zap.Int(zapNumberOfItems, len(reqs))) - - } - } -} - -// loop is the main loop that handles fetching items from the persistent buffer -func (pcs *persistentContiguousStorage) loop() { - for { - select { - case <-pcs.stopChan: - return - case <-pcs.putChan: - req, found := pcs.getNextItem(context.Background()) - if found { - pcs.reqChan <- req - } - } - } -} - -// get returns the request channel that all the requests will be send on -func (pcs *persistentContiguousStorage) get() <-chan Request { - return pcs.reqChan -} - -// size returns the number of currently available items, which were not picked by consumers yet -func (pcs *persistentContiguousStorage) size() uint64 { - return pcs.itemsCount.Load() -} - -func (pcs *persistentContiguousStorage) stop() { - pcs.logger.Debug("Stopping persistentContiguousStorage", zap.String(zapQueueNameKey, pcs.queueName)) - pcs.stopOnce.Do(func() { - close(pcs.stopChan) - if err := pcs.client.Close(context.Background()); err != nil { - pcs.logger.Warn("failed to close client", zap.Error(err)) - } - }) -} - -// put marshals the request and puts it into the persistent queue -func (pcs *persistentContiguousStorage) put(req Request) error { - // Nil requests are ignored - if req == nil { - return nil - } - - pcs.mu.Lock() - defer pcs.mu.Unlock() - - if pcs.size() >= pcs.capacity { - pcs.logger.Warn("Maximum queue capacity reached", zap.String(zapQueueNameKey, pcs.queueName)) - return errMaxCapacityReached - } - - itemKey := pcs.itemKey(pcs.writeIndex) - pcs.writeIndex++ - pcs.itemsCount.Store(uint64(pcs.writeIndex - pcs.readIndex)) - - ctx := context.Background() - _, err := newBatch(pcs).setItemIndex(writeIndexKey, pcs.writeIndex).setRequest(itemKey, req).execute(ctx) - - // Inform the loop that there's some data to process - pcs.putChan <- struct{}{} - - return err -} - -// getNextItem pulls the next available item from the persistent storage; if none is found, returns (nil, false) -func (pcs *persistentContiguousStorage) getNextItem(ctx context.Context) (Request, bool) { - pcs.mu.Lock() - defer pcs.mu.Unlock() - - if pcs.readIndex != pcs.writeIndex { - index := pcs.readIndex - // Increase here, so even if errors happen below, it always iterates - pcs.readIndex++ - pcs.itemsCount.Store(uint64(pcs.writeIndex - pcs.readIndex)) - - pcs.updateReadIndex(ctx) - pcs.itemDispatchingStart(ctx, index) - - var req Request - batch, err := newBatch(pcs).get(pcs.itemKey(index)).execute(ctx) - if err == nil { - req, err = batch.getRequestResult(pcs.itemKey(index)) - } - - if err != nil || req == nil { - // We need to make sure that currently dispatched items list is cleaned - if err := pcs.itemDispatchingFinish(ctx, index); err != nil { - pcs.logger.Error("Error deleting item from queue", - zap.String(zapQueueNameKey, pcs.queueName), zap.Error(err)) - } - - return nil, false - } - - // If all went well so far, cleanup will be handled by callback - req.SetOnProcessingFinished(func() { - pcs.mu.Lock() - defer pcs.mu.Unlock() - if err := pcs.itemDispatchingFinish(ctx, index); err != nil { - pcs.logger.Error("Error deleting item from queue", - zap.String(zapQueueNameKey, pcs.queueName), zap.Error(err)) - } - }) - return req, true - } - - return nil, false -} - -// retrieveNotDispatchedReqs gets the items for which sending was not finished, cleans the storage -// and moves the items back to the queue. The function returns an array which might contain nils -// if unmarshalling of the value at a given index was not possible. -func (pcs *persistentContiguousStorage) retrieveNotDispatchedReqs(ctx context.Context) []Request { - var reqs []Request - var dispatchedItems []itemIndex - - pcs.mu.Lock() - defer pcs.mu.Unlock() - - pcs.logger.Debug("Checking if there are items left for dispatch by consumers", zap.String(zapQueueNameKey, pcs.queueName)) - batch, err := newBatch(pcs).get(currentlyDispatchedItemsKey).execute(ctx) - if err == nil { - dispatchedItems, err = batch.getItemIndexArrayResult(currentlyDispatchedItemsKey) - } - if err != nil { - pcs.logger.Error("Could not fetch items left for dispatch by consumers", zap.String(zapQueueNameKey, pcs.queueName), zap.Error(err)) - return reqs - } - - if len(dispatchedItems) > 0 { - pcs.logger.Info("Fetching items left for dispatch by consumers", - zap.String(zapQueueNameKey, pcs.queueName), zap.Int(zapNumberOfItems, len(dispatchedItems))) - } else { - pcs.logger.Debug("No items left for dispatch by consumers") - } - - reqs = make([]Request, len(dispatchedItems)) - keys := make([]string, len(dispatchedItems)) - retrieveBatch := newBatch(pcs) - cleanupBatch := newBatch(pcs) - for i, it := range dispatchedItems { - keys[i] = pcs.itemKey(it) - retrieveBatch.get(keys[i]) - cleanupBatch.delete(keys[i]) - } - - _, retrieveErr := retrieveBatch.execute(ctx) - _, cleanupErr := cleanupBatch.execute(ctx) - - if retrieveErr != nil { - pcs.logger.Warn("Failed retrieving items left by consumers", zap.String(zapQueueNameKey, pcs.queueName), zap.Error(retrieveErr)) - } - - if cleanupErr != nil { - pcs.logger.Debug("Failed cleaning items left by consumers", zap.String(zapQueueNameKey, pcs.queueName), zap.Error(cleanupErr)) - } - - if retrieveErr != nil { - return reqs - } - - for i, key := range keys { - req, err := retrieveBatch.getRequestResult(key) - // If error happened or item is nil, it will be efficiently ignored - if err != nil { - pcs.logger.Warn("Failed unmarshalling item", - zap.String(zapQueueNameKey, pcs.queueName), zap.String(zapKey, key), zap.Error(err)) - } else { - if req == nil { - pcs.logger.Debug("Item value could not be retrieved", - zap.String(zapQueueNameKey, pcs.queueName), zap.String(zapKey, key), zap.Error(err)) - } else { - reqs[i] = req - } - } - } - - return reqs -} - -// itemDispatchingStart appends the item to the list of currently dispatched items -func (pcs *persistentContiguousStorage) itemDispatchingStart(ctx context.Context, index itemIndex) { - pcs.currentlyDispatchedItems = append(pcs.currentlyDispatchedItems, index) - _, err := newBatch(pcs). - setItemIndexArray(currentlyDispatchedItemsKey, pcs.currentlyDispatchedItems). - execute(ctx) - if err != nil { - pcs.logger.Debug("Failed updating currently dispatched items", - zap.String(zapQueueNameKey, pcs.queueName), zap.Error(err)) - } -} - -// itemDispatchingFinish removes the item from the list of currently dispatched items and deletes it from the persistent queue -func (pcs *persistentContiguousStorage) itemDispatchingFinish(ctx context.Context, index itemIndex) error { - var batch *batchStruct - var updatedDispatchedItems []itemIndex - for _, it := range pcs.currentlyDispatchedItems { - if it != index { - updatedDispatchedItems = append(updatedDispatchedItems, it) - } - } - pcs.currentlyDispatchedItems = updatedDispatchedItems - - batch = newBatch(pcs). - setItemIndexArray(currentlyDispatchedItemsKey, pcs.currentlyDispatchedItems). - delete(pcs.itemKey(index)) - if _, err := batch.execute(ctx); err != nil { - // got an error, try to gracefully handle it - pcs.logger.Warn("Failed updating currently dispatched items, trying to delete the item first", - zap.String(zapQueueNameKey, pcs.queueName), zap.Error(err)) - } else { - // Everything ok, exit - return nil - } - - if _, err := newBatch(pcs).delete(pcs.itemKey(index)).execute(ctx); err != nil { - // Return an error here, as this indicates an issue with the underlying storage medium - return fmt.Errorf("failed deleting item from queue, got error from storage: %w", err) - } - - batch = newBatch(pcs). - setItemIndexArray(currentlyDispatchedItemsKey, pcs.currentlyDispatchedItems) - if _, err := batch.execute(ctx); err != nil { - // even if this fails, we still have the right dispatched items in memory - // at worst, we'll have the wrong list in storage, and we'll discard the nonexistent items during startup - return fmt.Errorf("failed updating currently dispatched items, but deleted item successfully: %w", err) - } - - return nil -} - -func (pcs *persistentContiguousStorage) updateReadIndex(ctx context.Context) { - _, err := newBatch(pcs). - setItemIndex(readIndexKey, pcs.readIndex). - execute(ctx) - - if err != nil { - pcs.logger.Debug("Failed updating read index", - zap.String(zapQueueNameKey, pcs.queueName), zap.Error(err)) - } -} - -func (pcs *persistentContiguousStorage) itemKey(index itemIndex) string { - return strconv.FormatUint(uint64(index), 10) -} diff --git a/exporter/exporterhelper/internal/persistent_storage_batch.go b/exporter/exporterhelper/internal/persistent_storage_batch.go deleted file mode 100644 index a80ba93c5c3..00000000000 --- a/exporter/exporterhelper/internal/persistent_storage_batch.go +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package internal // import "go.opentelemetry.io/collector/exporter/exporterhelper/internal" - -import ( - "bytes" - "context" - "encoding/binary" - "errors" - - "go.uber.org/zap" - - "go.opentelemetry.io/collector/extension/experimental/storage" -) - -var errItemIndexArrInvalidDataType = errors.New("invalid data type, expected []itemIndex") - -// batchStruct provides convenience capabilities for creating and processing storage extension batches -type batchStruct struct { - logger *zap.Logger - pcs *persistentContiguousStorage - - operations []storage.Operation - getOperations map[string]storage.Operation -} - -func newBatch(pcs *persistentContiguousStorage) *batchStruct { - return &batchStruct{ - logger: pcs.logger, - pcs: pcs, - operations: []storage.Operation{}, - getOperations: map[string]storage.Operation{}, - } -} - -// execute runs the provided operations in order -func (bof *batchStruct) execute(ctx context.Context) (*batchStruct, error) { - err := bof.pcs.client.Batch(ctx, bof.operations...) - if err != nil { - return nil, err - } - - return bof, nil -} - -// set adds a Set operation to the batch -func (bof *batchStruct) set(key string, value any, marshal func(any) ([]byte, error)) *batchStruct { - valueBytes, err := marshal(value) - if err != nil { - bof.logger.Debug("Failed marshaling item, skipping it", zap.String(zapKey, key), zap.Error(err)) - } else { - bof.operations = append(bof.operations, storage.SetOperation(key, valueBytes)) - } - - return bof -} - -// get adds a Get operation to the batch. After executing, its result will be available through getResult -func (bof *batchStruct) get(keys ...string) *batchStruct { - for _, key := range keys { - op := storage.GetOperation(key) - bof.getOperations[key] = op - bof.operations = append(bof.operations, op) - } - - return bof -} - -// delete adds a Delete operation to the batch -func (bof *batchStruct) delete(keys ...string) *batchStruct { - for _, key := range keys { - bof.operations = append(bof.operations, storage.DeleteOperation(key)) - } - - return bof -} - -// getResult returns the result of a Get operation for a given key using the provided unmarshal function. -// It should be called after execute. It may return nil value -func (bof *batchStruct) getResult(key string, unmarshal func([]byte) (any, error)) (any, error) { - op := bof.getOperations[key] - if op == nil { - return nil, errKeyNotPresentInBatch - } - - if op.Value == nil { - return nil, nil - } - - return unmarshal(op.Value) -} - -// getRequestResult returns the result of a Get operation as a request -// If the value cannot be retrieved, it returns an error -func (bof *batchStruct) getRequestResult(key string) (Request, error) { - reqIf, err := bof.getResult(key, bof.bytesToRequest) - if err != nil { - return nil, err - } - if reqIf == nil { - return nil, errValueNotSet - } - - return reqIf.(Request), nil -} - -// getItemIndexResult returns the result of a Get operation as an itemIndex -// If the value cannot be retrieved, it returns an error -func (bof *batchStruct) getItemIndexResult(key string) (itemIndex, error) { - itemIndexIf, err := bof.getResult(key, bytesToItemIndex) - if err != nil { - return itemIndex(0), err - } - - if itemIndexIf == nil { - return itemIndex(0), errValueNotSet - } - - return itemIndexIf.(itemIndex), nil -} - -// getItemIndexArrayResult returns the result of a Get operation as a itemIndexArray -// It may return nil value -func (bof *batchStruct) getItemIndexArrayResult(key string) ([]itemIndex, error) { - itemIndexArrIf, err := bof.getResult(key, bytesToItemIndexArray) - if err != nil { - return nil, err - } - - if itemIndexArrIf == nil { - return nil, nil - } - - return itemIndexArrIf.([]itemIndex), nil -} - -// setRequest adds Set operation over a given request to the batch -func (bof *batchStruct) setRequest(key string, value Request) *batchStruct { - return bof.set(key, value, bof.requestToBytes) -} - -// setItemIndex adds Set operation over a given itemIndex to the batch -func (bof *batchStruct) setItemIndex(key string, value itemIndex) *batchStruct { - return bof.set(key, value, itemIndexToBytes) -} - -// setItemIndexArray adds Set operation over a given itemIndex array to the batch -func (bof *batchStruct) setItemIndexArray(key string, value []itemIndex) *batchStruct { - return bof.set(key, value, itemIndexArrayToBytes) -} - -func itemIndexToBytes(val any) ([]byte, error) { - var buf bytes.Buffer - err := binary.Write(&buf, binary.LittleEndian, val) - if err != nil { - return nil, err - } - return buf.Bytes(), err -} - -func bytesToItemIndex(b []byte) (any, error) { - var val itemIndex - err := binary.Read(bytes.NewReader(b), binary.LittleEndian, &val) - if err != nil { - return val, err - } - return val, nil -} - -func itemIndexArrayToBytes(arr any) ([]byte, error) { - var buf bytes.Buffer - size := 0 - - if arr != nil { - arrItemIndex, ok := arr.([]itemIndex) - if ok { - size = len(arrItemIndex) - } else { - return nil, errItemIndexArrInvalidDataType - } - } - - err := binary.Write(&buf, binary.LittleEndian, uint32(size)) - if err != nil { - return nil, err - } - - err = binary.Write(&buf, binary.LittleEndian, arr) - if err != nil { - return nil, err - } - return buf.Bytes(), err -} - -func bytesToItemIndexArray(b []byte) (any, error) { - var size uint32 - reader := bytes.NewReader(b) - err := binary.Read(reader, binary.LittleEndian, &size) - if err != nil { - return nil, err - } - - val := make([]itemIndex, size) - err = binary.Read(reader, binary.LittleEndian, &val) - return val, err -} - -func (bof *batchStruct) requestToBytes(req any) ([]byte, error) { - return bof.pcs.marshaler(req.(Request)) -} - -func (bof *batchStruct) bytesToRequest(b []byte) (any, error) { - return bof.pcs.unmarshaler(b) -} diff --git a/exporter/exporterhelper/internal/persistent_storage_batch_test.go b/exporter/exporterhelper/internal/persistent_storage_batch_test.go deleted file mode 100644 index 2784ca92759..00000000000 --- a/exporter/exporterhelper/internal/persistent_storage_batch_test.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package internal - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestPersistentStorageBatch_Operations(t *testing.T) { - ext := NewMockStorageExtension(nil) - client := createTestClient(ext) - ps := createTestPersistentStorage(client) - - itemIndexValue := itemIndex(123) - itemIndexArrayValue := []itemIndex{itemIndex(1), itemIndex(2)} - - _, err := newBatch(ps). - setItemIndex("index", itemIndexValue). - setItemIndexArray("arr", itemIndexArrayValue). - execute(context.Background()) - require.NoError(t, err) - - batch, err := newBatch(ps). - get("index", "arr"). - execute(context.Background()) - require.NoError(t, err) - - retrievedItemIndexValue, err := batch.getItemIndexResult("index") - require.NoError(t, err) - assert.Equal(t, itemIndexValue, retrievedItemIndexValue) - - retrievedItemIndexArrayValue, err := batch.getItemIndexArrayResult("arr") - require.NoError(t, err) - assert.Equal(t, itemIndexArrayValue, retrievedItemIndexArrayValue) - - _, err = newBatch(ps).delete("index", "arr").execute(context.Background()) - require.NoError(t, err) - - batch, err = newBatch(ps). - get("index", "arr"). - execute(context.Background()) - require.NoError(t, err) - - _, err = batch.getItemIndexResult("index") - assert.Error(t, err, errValueNotSet) - - retrievedItemIndexArrayValue, err = batch.getItemIndexArrayResult("arr") - require.NoError(t, err) - assert.Nil(t, retrievedItemIndexArrayValue) -} diff --git a/exporter/exporterhelper/internal/persistent_storage_test.go b/exporter/exporterhelper/internal/persistent_storage_test.go deleted file mode 100644 index d48bbd75285..00000000000 --- a/exporter/exporterhelper/internal/persistent_storage_test.go +++ /dev/null @@ -1,714 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package internal - -import ( - "context" - "errors" - "fmt" - "reflect" - "sync" - "syscall" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap" - - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/extension/experimental/storage" - "go.opentelemetry.io/collector/pdata/ptrace" -) - -func createTestClient(extension storage.Extension) storage.Client { - client, err := extension.GetClient(context.Background(), component.KindReceiver, component.ID{}, "") - if err != nil { - panic(err) - } - return client -} - -func createTestPersistentStorageWithLoggingAndCapacity(client storage.Client, logger *zap.Logger, capacity uint64) *persistentContiguousStorage { - return newPersistentContiguousStorage(context.Background(), "foo", client, logger, capacity, - newFakeTracesRequestMarshalerFunc(), newFakeTracesRequestUnmarshalerFunc()) -} - -func createTestPersistentStorage(client storage.Client) *persistentContiguousStorage { - logger := zap.NewNop() - return createTestPersistentStorageWithLoggingAndCapacity(client, logger, 1000) -} - -type fakeTracesRequest struct { - td ptrace.Traces - processingFinishedCallback func() - Request -} - -func newFakeTracesRequest(td ptrace.Traces) *fakeTracesRequest { - return &fakeTracesRequest{ - td: td, - } -} - -func (fd *fakeTracesRequest) OnProcessingFinished() { - if fd.processingFinishedCallback != nil { - fd.processingFinishedCallback() - } -} - -func (fd *fakeTracesRequest) SetOnProcessingFinished(callback func()) { - fd.processingFinishedCallback = callback -} - -func newFakeTracesRequestUnmarshalerFunc() RequestUnmarshaler { - return func(bytes []byte) (Request, error) { - unmarshaler := ptrace.ProtoUnmarshaler{} - traces, err := unmarshaler.UnmarshalTraces(bytes) - if err != nil { - return nil, err - } - return newFakeTracesRequest(traces), nil - } -} - -func newFakeTracesRequestMarshalerFunc() RequestMarshaler { - return func(req Request) ([]byte, error) { - marshaler := ptrace.ProtoMarshaler{} - return marshaler.MarshalTraces(req.(*fakeTracesRequest).td) - } -} - -func TestPersistentStorage_CorruptedData(t *testing.T) { - traces := newTraces(5, 10) - req := newFakeTracesRequest(traces) - - cases := []struct { - name string - corruptAllData bool - corruptSomeData bool - corruptCurrentlyDispatchedItemsKey bool - corruptReadIndex bool - corruptWriteIndex bool - desiredQueueSize uint64 - desiredNumberOfDispatchedItems int - }{ - { - name: "corrupted no items", - corruptAllData: false, - desiredQueueSize: 2, - desiredNumberOfDispatchedItems: 1, - }, - { - name: "corrupted all items", - corruptAllData: true, - desiredQueueSize: 0, - desiredNumberOfDispatchedItems: 0, - }, - { - name: "corrupted some items", - corruptSomeData: true, - desiredQueueSize: 1, - desiredNumberOfDispatchedItems: 1, - }, - { - name: "corrupted dispatched items key", - corruptCurrentlyDispatchedItemsKey: true, - desiredQueueSize: 1, - desiredNumberOfDispatchedItems: 1, - }, - { - name: "corrupted read index", - corruptReadIndex: true, - desiredQueueSize: 0, - desiredNumberOfDispatchedItems: 1, - }, - { - name: "corrupted write index", - corruptWriteIndex: true, - desiredQueueSize: 0, - desiredNumberOfDispatchedItems: 1, - }, - { - name: "corrupted everything", - corruptAllData: true, - corruptCurrentlyDispatchedItemsKey: true, - corruptReadIndex: true, - corruptWriteIndex: true, - desiredQueueSize: 0, - desiredNumberOfDispatchedItems: 0, - }, - } - - badBytes := []byte{0, 1, 2} - - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - ext := NewMockStorageExtension(nil) - client := createTestClient(ext) - ps := createTestPersistentStorage(client) - - ctx := context.Background() - - // Put some items, make sure they are loaded and shutdown the storage... - for i := 0; i < 3; i++ { - err := ps.put(req) - require.NoError(t, err) - } - require.Eventually(t, func() bool { - return ps.size() == 2 - }, 5*time.Second, 10*time.Millisecond) - ps.stop() - - // ... so now we can corrupt data (in several ways) - if c.corruptAllData || c.corruptSomeData { - _ = client.Set(ctx, "0", badBytes) - } - if c.corruptAllData { - _ = client.Set(ctx, "1", badBytes) - _ = client.Set(ctx, "2", badBytes) - } - - if c.corruptCurrentlyDispatchedItemsKey { - _ = client.Set(ctx, currentlyDispatchedItemsKey, badBytes) - } - - if c.corruptReadIndex { - _ = client.Set(ctx, readIndexKey, badBytes) - } - - if c.corruptWriteIndex { - _ = client.Set(ctx, writeIndexKey, badBytes) - } - - // Reload - newPs := createTestPersistentStorage(client) - - require.Eventually(t, func() bool { - newPs.mu.Lock() - defer newPs.mu.Unlock() - return newPs.size() == c.desiredQueueSize && len(newPs.currentlyDispatchedItems) == c.desiredNumberOfDispatchedItems - }, 5*time.Second, 10*time.Millisecond) - }) - } -} - -func TestPersistentStorage_CurrentlyProcessedItems(t *testing.T) { - traces := newTraces(5, 10) - req := newFakeTracesRequest(traces) - - ext := NewMockStorageExtension(nil) - client := createTestClient(ext) - ps := createTestPersistentStorage(client) - - for i := 0; i < 5; i++ { - err := ps.put(req) - require.NoError(t, err) - } - - // Item index 0 is currently in unbuffered channel - requireCurrentlyDispatchedItemsEqual(t, ps, []itemIndex{0}) - - // Now, this will take item 0 and pull item 1 into the unbuffered channel - readReq := <-ps.get() - assert.Equal(t, req.td, readReq.(*fakeTracesRequest).td) - requireCurrentlyDispatchedItemsEqual(t, ps, []itemIndex{0, 1}) - - // This takes item 1 from channel and pulls another one (item 2) into the unbuffered channel - secondReadReq := <-ps.get() - requireCurrentlyDispatchedItemsEqual(t, ps, []itemIndex{0, 1, 2}) - - // Lets mark item 1 as finished, it will remove it from the currently dispatched items list - secondReadReq.OnProcessingFinished() - requireCurrentlyDispatchedItemsEqual(t, ps, []itemIndex{0, 2}) - - // Reload the storage. Since items 0 and 2 were not finished, those should be requeued at the end. - // The queue should be essentially {3,4,0,2} out of which item "3" should be pulled right away into - // the unbuffered channel. Check how many items are there, which, after the current one is fetched should go to 3. - newPs := createTestPersistentStorage(client) - assert.Eventually(t, func() bool { - return newPs.size() == 3 - }, 5*time.Second, 10*time.Millisecond) - - requireCurrentlyDispatchedItemsEqual(t, newPs, []itemIndex{3}) - - // We should be able to pull all remaining items now - for i := 0; i < 4; i++ { - req := <-newPs.get() - req.OnProcessingFinished() - } - - // The queue should be now empty - requireCurrentlyDispatchedItemsEqual(t, newPs, nil) - assert.Eventually(t, func() bool { - return newPs.size() == 0 - }, 5*time.Second, 10*time.Millisecond) - - // The writeIndex should be now set accordingly - require.Equal(t, 7, int(newPs.writeIndex)) - - // There should be no items left in the storage - for i := 0; i < int(newPs.writeIndex); i++ { - bb, err := client.Get(context.Background(), newPs.itemKey(itemIndex(i))) - require.NoError(t, err) - require.Nil(t, bb) - } -} - -// this test attempts to check if all the invariants are kept if the queue is recreated while -// close to full and with some items dispatched -func TestPersistentStorage_StartWithNonDispatched(t *testing.T) { - var capacity uint64 = 5 // arbitrary small number - logger := zap.NewNop() - - traces := newTraces(5, 10) - req := newFakeTracesRequest(traces) - - ext := NewMockStorageExtension(nil) - client := createTestClient(ext) - ps := createTestPersistentStorageWithLoggingAndCapacity(client, logger, capacity) - - // Put in items up to capacity - for i := 0; i < int(capacity); i++ { - err := ps.put(req) - require.NoError(t, err) - } - - // get one item out, but don't mark it as processed - <-ps.get() - // put one more item in - err := ps.put(req) - require.NoError(t, err) - - require.Eventually(t, func() bool { - return ps.size() == capacity-1 - }, 5*time.Second, 10*time.Millisecond) - ps.stop() - - // Reload - newPs := createTestPersistentStorageWithLoggingAndCapacity(client, logger, capacity) - - require.Eventually(t, func() bool { - newPs.mu.Lock() - defer newPs.mu.Unlock() - return newPs.size() == capacity-1 && len(newPs.currentlyDispatchedItems) == 1 - }, 5*time.Second, 10*time.Millisecond) -} - -func TestPersistentStorage_RepeatPutCloseReadClose(t *testing.T) { - traces := newTraces(5, 10) - req := newFakeTracesRequest(traces) - - for i := 0; i < 10; i++ { - ext := NewMockStorageExtension(nil) - client := createTestClient(ext) - ps := createTestPersistentStorage(client) - require.Equal(t, uint64(0), ps.size()) - - // Put two elements - err := ps.put(req) - require.NoError(t, err) - err = ps.put(req) - require.NoError(t, err) - - err = ext.Shutdown(context.Background()) - require.NoError(t, err) - - // TODO: when replacing mock with real storage, this could actually be uncommented - // ext = NewMockStorageExtension(nil) - // ps = createTestPersistentStorage(ext) - - // The first element should be already picked by loop - require.Eventually(t, func() bool { - return ps.size() == 1 - }, 5*time.Second, 10*time.Millisecond) - - // Lets read both of the elements we put - readReq := <-ps.get() - require.Equal(t, req.td, readReq.(*fakeTracesRequest).td) - - readReq = <-ps.get() - require.Equal(t, req.td, readReq.(*fakeTracesRequest).td) - require.Equal(t, uint64(0), ps.size()) - - err = ext.Shutdown(context.Background()) - require.NoError(t, err) - } - - // No more items - ext := NewMockStorageExtension(nil) - wq := createTestQueue(t, 1000, 1, func(Request) {}) - require.Equal(t, 0, wq.Size()) - require.NoError(t, ext.Shutdown(context.Background())) -} - -func TestPersistentStorage_EmptyRequest(t *testing.T) { - ext := NewMockStorageExtension(nil) - client := createTestClient(ext) - ps := createTestPersistentStorage(client) - - require.Equal(t, uint64(0), ps.size()) - - err := ps.put(nil) - require.NoError(t, err) - - require.Equal(t, uint64(0), ps.size()) - - err = ext.Shutdown(context.Background()) - require.NoError(t, err) -} - -func BenchmarkPersistentStorage_TraceSpans(b *testing.B) { - cases := []struct { - numTraces int - numSpansPerTrace int - }{ - { - numTraces: 1, - numSpansPerTrace: 1, - }, - { - numTraces: 1, - numSpansPerTrace: 10, - }, - { - numTraces: 10, - numSpansPerTrace: 10, - }, - } - - for _, c := range cases { - b.Run(fmt.Sprintf("#traces: %d #spansPerTrace: %d", c.numTraces, c.numSpansPerTrace), func(bb *testing.B) { - ext := NewMockStorageExtension(nil) - client := createTestClient(ext) - ps := createTestPersistentStorageWithLoggingAndCapacity(client, zap.NewNop(), 10000000) - - traces := newTraces(c.numTraces, c.numSpansPerTrace) - req := newFakeTracesRequest(traces) - - bb.ResetTimer() - - for i := 0; i < bb.N; i++ { - err := ps.put(req) - require.NoError(bb, err) - } - - for i := 0; i < bb.N; i++ { - req := ps.get() - require.NotNil(bb, req) - } - require.NoError(b, ext.Shutdown(context.Background())) - }) - } -} - -func TestPersistentStorage_ItemIndexMarshaling(t *testing.T) { - cases := []struct { - arr1 []itemIndex - arr2 []itemIndex - }{ - { - arr1: []itemIndex{0, 1, 2}, - arr2: []itemIndex{0, 1, 2}, - }, - { - arr1: []itemIndex{}, - arr2: []itemIndex{}, - }, - { - arr1: nil, - arr2: []itemIndex{}, - }, - } - - for _, c := range cases { - count := 0 - if c.arr1 != nil { - count = len(c.arr1) - } - t.Run(fmt.Sprintf("#elements:%d", count), func(tt *testing.T) { - barr, err := itemIndexArrayToBytes(c.arr1) - require.NoError(t, err) - arr2, err := bytesToItemIndexArray(barr) - require.NoError(t, err) - require.Equal(t, c.arr2, arr2) - }) - } -} - -func TestPersistentStorage_StopShouldCloseClient(t *testing.T) { - ext := NewMockStorageExtension(nil) - client := createTestClient(ext) - ps := createTestPersistentStorage(client) - - ps.stop() - - castedClient, ok := client.(*mockStorageClient) - require.True(t, ok, "expected client to be mockStorageClient") - require.Equal(t, uint64(1), castedClient.getCloseCount()) -} - -func TestPersistentStorage_StorageFull(t *testing.T) { - var err error - traces := newTraces(5, 10) - req := newFakeTracesRequest(traces) - marshaled, err := newFakeTracesRequestMarshalerFunc()(req) - require.NoError(t, err) - maxSizeInBytes := len(marshaled) * 5 // arbitrary small number - freeSpaceInBytes := 1 - - client := newFakeBoundedStorageClient(maxSizeInBytes) - ps := createTestPersistentStorage(client) - - // Put enough items in to fill the underlying storage - reqCount := 0 - for { - err = ps.put(req) - if errors.Is(err, syscall.ENOSPC) { - break - } - require.NoError(t, err) - reqCount++ - } - - // Manually set the storage to only have a small amount of free space left - newMaxSize := client.GetSizeInBytes() + freeSpaceInBytes - client.SetMaxSizeInBytes(newMaxSize) - - // Try to put an item in, should fail - err = ps.put(req) - require.Error(t, err) - - // Take out all the items - for i := reqCount; i > 0; i-- { - request := <-ps.get() - request.OnProcessingFinished() - } - - // We should be able to put a new item in - // However, this will fail if deleting items fails with full storage - err = ps.put(req) - require.NoError(t, err) -} - -func TestPersistentStorage_ItemDispatchingFinish_ErrorHandling(t *testing.T) { - errDeletingItem := fmt.Errorf("error deleting item") - errUpdatingDispatched := fmt.Errorf("error updating dispatched items") - testCases := []struct { - storageErrors []error - expectedError error - description string - }{ - { - description: "no errors", - storageErrors: []error{}, - expectedError: nil, - }, - { - description: "error on first transaction, success afterwards", - storageErrors: []error{ - errUpdatingDispatched, - }, - expectedError: nil, - }, - { - description: "error on first and second transaction", - storageErrors: []error{ - errUpdatingDispatched, - errDeletingItem, - }, - expectedError: errDeletingItem, - }, - { - description: "error on first and third transaction", - storageErrors: []error{ - errUpdatingDispatched, - nil, - errUpdatingDispatched, - }, - expectedError: errUpdatingDispatched, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.description, func(t *testing.T) { - testCase := testCase - client := newFakeStorageClientWithErrors(testCase.storageErrors) - ps := createTestPersistentStorage(client) - client.Reset() - - err := ps.itemDispatchingFinish(context.Background(), 0) - - require.ErrorIs(t, err, testCase.expectedError) - }) - } -} - -func requireCurrentlyDispatchedItemsEqual(t *testing.T, pcs *persistentContiguousStorage, compare []itemIndex) { - require.Eventually(t, func() bool { - pcs.mu.Lock() - defer pcs.mu.Unlock() - return reflect.DeepEqual(pcs.currentlyDispatchedItems, compare) - }, 5*time.Second, 10*time.Millisecond) -} - -func newFakeBoundedStorageClient(maxSizeInBytes int) *fakeBoundedStorageClient { - return &fakeBoundedStorageClient{ - st: map[string][]byte{}, - MaxSizeInBytes: maxSizeInBytes, - } -} - -// this storage client mimics the behavior of actual storage engines with limited storage space available -// in general, real storage engines often have a per-write-transaction storage overhead, needing to keep -// both the old and the new value stored until the transaction is committed -// this is useful for testing the persistent queue queue behavior with a full disk -type fakeBoundedStorageClient struct { - MaxSizeInBytes int - st map[string][]byte - sizeInBytes int - mux sync.Mutex -} - -func (m *fakeBoundedStorageClient) Get(ctx context.Context, key string) ([]byte, error) { - op := storage.GetOperation(key) - err := m.Batch(ctx, op) - if err != nil { - return nil, err - } - - return op.Value, nil -} - -func (m *fakeBoundedStorageClient) Set(ctx context.Context, key string, value []byte) error { - return m.Batch(ctx, storage.SetOperation(key, value)) -} - -func (m *fakeBoundedStorageClient) Delete(ctx context.Context, key string) error { - return m.Batch(ctx, storage.DeleteOperation(key)) -} - -func (m *fakeBoundedStorageClient) Close(_ context.Context) error { - return nil -} - -func (m *fakeBoundedStorageClient) Batch(_ context.Context, ops ...storage.Operation) error { - m.mux.Lock() - defer m.mux.Unlock() - - totalAdded, totalRemoved := m.getTotalSizeChange(ops) - - // the assumption here is that the new data needs to coexist with the old data on disk - // for the transaction to succeed - // this seems to be true for the file storage extension at least - if m.sizeInBytes+totalAdded > m.MaxSizeInBytes { - return fmt.Errorf("insufficient space available: %w", syscall.ENOSPC) - } - - for _, op := range ops { - switch op.Type { - case storage.Get: - op.Value = m.st[op.Key] - case storage.Set: - m.st[op.Key] = op.Value - case storage.Delete: - delete(m.st, op.Key) - default: - return errors.New("wrong operation type") - } - } - - m.sizeInBytes += (totalAdded - totalRemoved) - - return nil -} - -func (m *fakeBoundedStorageClient) SetMaxSizeInBytes(newMaxSize int) { - m.mux.Lock() - defer m.mux.Unlock() - m.MaxSizeInBytes = newMaxSize -} - -func (m *fakeBoundedStorageClient) GetSizeInBytes() int { - m.mux.Lock() - defer m.mux.Unlock() - return m.sizeInBytes -} - -func (m *fakeBoundedStorageClient) getTotalSizeChange(ops []storage.Operation) (totalAdded int, totalRemoved int) { - totalAdded, totalRemoved = 0, 0 - for _, op := range ops { - switch op.Type { - case storage.Set: - if oldValue, ok := m.st[op.Key]; ok { - totalRemoved += len(oldValue) - } else { - totalAdded += len(op.Key) - } - totalAdded += len(op.Value) - case storage.Delete: - if value, ok := m.st[op.Key]; ok { - totalRemoved += len(op.Key) - totalRemoved += len(value) - } - default: - } - } - return totalAdded, totalRemoved -} - -func newFakeStorageClientWithErrors(errors []error) *fakeStorageClientWithErrors { - return &fakeStorageClientWithErrors{ - errors: errors, - } -} - -// this storage client just returns errors from a list in order -// used for testing error handling -type fakeStorageClientWithErrors struct { - errors []error - nextErrorIndex int - mux sync.Mutex -} - -func (m *fakeStorageClientWithErrors) Get(ctx context.Context, key string) ([]byte, error) { - op := storage.GetOperation(key) - err := m.Batch(ctx, op) - if err != nil { - return nil, err - } - - return op.Value, nil -} - -func (m *fakeStorageClientWithErrors) Set(ctx context.Context, key string, value []byte) error { - return m.Batch(ctx, storage.SetOperation(key, value)) -} - -func (m *fakeStorageClientWithErrors) Delete(ctx context.Context, key string) error { - return m.Batch(ctx, storage.DeleteOperation(key)) -} - -func (m *fakeStorageClientWithErrors) Close(_ context.Context) error { - return nil -} - -func (m *fakeStorageClientWithErrors) Batch(_ context.Context, _ ...storage.Operation) error { - m.mux.Lock() - defer m.mux.Unlock() - - if m.nextErrorIndex >= len(m.errors) { - return nil - } - - err := m.errors[m.nextErrorIndex] - m.nextErrorIndex++ - return err -} - -func (m *fakeStorageClientWithErrors) Reset() { - m.mux.Lock() - defer m.mux.Unlock() - m.nextErrorIndex = 0 -} diff --git a/exporter/exporterhelper/internal/producer_consumer_queue.go b/exporter/exporterhelper/internal/producer_consumer_queue.go deleted file mode 100644 index 7b17106a564..00000000000 --- a/exporter/exporterhelper/internal/producer_consumer_queue.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright The OpenTelemetry Authors -// Copyright (c) 2019 The Jaeger Authors. -// Copyright (c) 2017 Uber Technologies, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package internal // import "go.opentelemetry.io/collector/exporter/exporterhelper/internal" - -import ( - "context" - - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/exporter" -) - -type QueueSettings struct { - exporter.CreateSettings - DataType component.DataType - Callback func(item Request) -} - -// ProducerConsumerQueue defines a producer-consumer exchange which can be backed by e.g. the memory-based ring buffer queue -// (boundedMemoryQueue) or via a disk-based queue (persistentQueue) -type ProducerConsumerQueue interface { - // Start starts the queue with a given number of goroutines consuming items from the queue - // and passing them into the consumer callback. - Start(ctx context.Context, host component.Host, set QueueSettings) error - // Produce is used by the producer to submit new item to the queue. Returns false if the item wasn't added - // to the queue due to queue overflow. - Produce(item Request) bool - // Size returns the current Size of the queue - Size() int - // Stop stops all consumers, as well as the length reporter if started, - // and releases the items channel. It blocks until all consumers have stopped. - Stop() - // Capacity returns the capacity of the queue. - Capacity() int - // IsPersistent returns true if the queue is persistent. - // TODO: Do not expose this method if the interface moves to a public package. - IsPersistent() bool -} diff --git a/exporter/exporterhelper/internal/request.go b/exporter/exporterhelper/internal/request.go deleted file mode 100644 index 454a42782ce..00000000000 --- a/exporter/exporterhelper/internal/request.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package internal // import "go.opentelemetry.io/collector/exporter/exporterhelper/internal" - -import "context" - -// Request defines capabilities required for persistent storage of a request -type Request interface { - // Context returns the context.Context of the requests. - Context() context.Context - - // SetContext updates the context.Context of the requests. - SetContext(context.Context) - - Export(ctx context.Context) error - - // OnError returns a new Request may contain the items left to be sent if some items failed to process and can be retried. - // Otherwise, it should return the original Request. - OnError(error) Request - - // Count returns the count of spans/metric points or log records. - Count() int - - // OnProcessingFinished calls the optional callback function to handle cleanup after all processing is finished - OnProcessingFinished() - - // SetOnProcessingFinished allows to set an optional callback function to do the cleanup (e.g. remove the item from persistent queue) - SetOnProcessingFinished(callback func()) -} - -// RequestUnmarshaler defines a function which takes a byte slice and unmarshals it into a relevant request -type RequestUnmarshaler func([]byte) (Request, error) - -// RequestMarshaler defines a function which takes a request and marshals it into a byte slice -type RequestMarshaler func(Request) ([]byte, error) diff --git a/exporter/exporterhelper/logs.go b/exporter/exporterhelper/logs.go index b098e722921..ce70230e321 100644 --- a/exporter/exporterhelper/logs.go +++ b/exporter/exporterhelper/logs.go @@ -13,7 +13,8 @@ import ( "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/exporter" - "go.opentelemetry.io/collector/exporter/exporterhelper/internal" + "go.opentelemetry.io/collector/exporter/exporterqueue" + "go.opentelemetry.io/collector/exporter/internal/queue" "go.opentelemetry.io/collector/pdata/plog" ) @@ -21,37 +22,35 @@ var logsMarshaler = &plog.ProtoMarshaler{} var logsUnmarshaler = &plog.ProtoUnmarshaler{} type logsRequest struct { - baseRequest ld plog.Logs pusher consumer.ConsumeLogsFunc } -func newLogsRequest(ctx context.Context, ld plog.Logs, pusher consumer.ConsumeLogsFunc) internal.Request { +func newLogsRequest(ld plog.Logs, pusher consumer.ConsumeLogsFunc) Request { return &logsRequest{ - baseRequest: baseRequest{ctx: ctx}, - ld: ld, - pusher: pusher, + ld: ld, + pusher: pusher, } } -func newLogsRequestUnmarshalerFunc(pusher consumer.ConsumeLogsFunc) internal.RequestUnmarshaler { - return func(bytes []byte) (internal.Request, error) { +func newLogsRequestUnmarshalerFunc(pusher consumer.ConsumeLogsFunc) exporterqueue.Unmarshaler[Request] { + return func(bytes []byte) (Request, error) { logs, err := logsUnmarshaler.UnmarshalLogs(bytes) if err != nil { return nil, err } - return newLogsRequest(context.Background(), logs, pusher), nil + return newLogsRequest(logs, pusher), nil } } -func logsRequestMarshaler(req internal.Request) ([]byte, error) { +func logsRequestMarshaler(req Request) ([]byte, error) { return logsMarshaler.MarshalLogs(req.(*logsRequest).ld) } -func (req *logsRequest) OnError(err error) internal.Request { +func (req *logsRequest) OnError(err error) Request { var logError consumererror.Logs if errors.As(err, &logError) { - return newLogsRequest(req.ctx, logError.Data(), req.pusher) + return newLogsRequest(logError.Data(), req.pusher) } return req } @@ -60,7 +59,7 @@ func (req *logsRequest) Export(ctx context.Context) error { return req.pusher(ctx, req.ld) } -func (req *logsRequest) Count() int { +func (req *logsRequest) ItemsCount() int { return req.ld.LogRecordCount() } @@ -71,7 +70,7 @@ type logsExporter struct { // NewLogsExporter creates an exporter.Logs that records observability metrics and wraps every request with a Span. func NewLogsExporter( - _ context.Context, + ctx context.Context, set exporter.CreateSettings, cfg component.Config, pusher consumer.ConsumeLogsFunc, @@ -80,42 +79,23 @@ func NewLogsExporter( if cfg == nil { return nil, errNilConfig } - - if set.Logger == nil { - return nil, errNilLogger - } - if pusher == nil { return nil, errNilPushLogsData } - - be, err := newBaseExporter(set, component.DataTypeLogs, false, logsRequestMarshaler, - newLogsRequestUnmarshalerFunc(pusher), newLogsExporterWithObservability, options...) - if err != nil { - return nil, err - } - - lc, err := consumer.NewLogs(func(ctx context.Context, ld plog.Logs) error { - req := newLogsRequest(ctx, ld, pusher) - serr := be.send(req) - if errors.Is(serr, errSendingQueueIsFull) { - be.obsrep.recordLogsEnqueueFailure(req.Context(), int64(req.Count())) - } - return serr - }, be.consumerOptions...) - - return &logsExporter{ - baseExporter: be, - Logs: lc, - }, err + logsOpts := []Option{withMarshaler(logsRequestMarshaler), withUnmarshaler(newLogsRequestUnmarshalerFunc(pusher))} + return NewLogsRequestExporter(ctx, set, requestFromLogs(pusher), append(logsOpts, options...)...) } -// LogsConverter provides an interface for converting plog.Logs into a request. +// RequestFromLogsFunc converts plog.Logs data into a user-defined request. // This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. -type LogsConverter interface { - // RequestFromLogs converts plog.Logs data into a request. - RequestFromLogs(context.Context, plog.Logs) (Request, error) +type RequestFromLogsFunc func(context.Context, plog.Logs) (Request, error) + +// requestFromLogs returns a RequestFromLogsFunc that converts plog.Logs into a Request. +func requestFromLogs(pusher consumer.ConsumeLogsFunc) RequestFromLogsFunc { + return func(_ context.Context, ld plog.Logs) (Request, error) { + return newLogsRequest(ld, pusher), nil + } } // NewLogsRequestExporter creates new logs exporter based on custom LogsConverter and RequestSender. @@ -124,7 +104,7 @@ type LogsConverter interface { func NewLogsRequestExporter( _ context.Context, set exporter.CreateSettings, - converter LogsConverter, + converter RequestFromLogsFunc, options ...Option, ) (exporter.Logs, error) { if set.Logger == nil { @@ -135,23 +115,22 @@ func NewLogsRequestExporter( return nil, errNilLogsConverter } - be, err := newBaseExporter(set, component.DataTypeLogs, true, nil, nil, newLogsExporterWithObservability, options...) + be, err := newBaseExporter(set, component.DataTypeLogs, newLogsExporterWithObservability, options...) if err != nil { return nil, err } lc, err := consumer.NewLogs(func(ctx context.Context, ld plog.Logs) error { - req, cErr := converter.RequestFromLogs(ctx, ld) + req, cErr := converter(ctx, ld) if cErr != nil { set.Logger.Error("Failed to convert logs. Dropping data.", zap.Int("dropped_log_records", ld.LogRecordCount()), zap.Error(err)) return consumererror.NewPermanent(cErr) } - r := newRequest(ctx, req) - sErr := be.send(r) - if errors.Is(sErr, errSendingQueueIsFull) { - be.obsrep.recordLogsEnqueueFailure(r.Context(), int64(r.Count())) + sErr := be.send(ctx, req) + if errors.Is(sErr, queue.ErrQueueIsFull) { + be.obsrep.recordEnqueueFailure(ctx, component.DataTypeLogs, int64(req.ItemsCount())) } return sErr }, be.consumerOptions...) @@ -164,16 +143,16 @@ func NewLogsRequestExporter( type logsExporterWithObservability struct { baseRequestSender - obsrep *obsExporter + obsrep *ObsReport } -func newLogsExporterWithObservability(obsrep *obsExporter) requestSender { +func newLogsExporterWithObservability(obsrep *ObsReport) requestSender { return &logsExporterWithObservability{obsrep: obsrep} } -func (lewo *logsExporterWithObservability) send(req internal.Request) error { - req.SetContext(lewo.obsrep.StartLogsOp(req.Context())) - err := lewo.nextSender.send(req) - lewo.obsrep.EndLogsOp(req.Context(), req.Count(), err) +func (lewo *logsExporterWithObservability) send(ctx context.Context, req Request) error { + c := lewo.obsrep.StartLogsOp(ctx) + err := lewo.nextSender.send(c, req) + lewo.obsrep.EndLogsOp(c, req.ItemsCount(), err) return err } diff --git a/exporter/exporterhelper/logs_test.go b/exporter/exporterhelper/logs_test.go index 699913f85a9..e42af577b2c 100644 --- a/exporter/exporterhelper/logs_test.go +++ b/exporter/exporterhelper/logs_test.go @@ -16,18 +16,19 @@ import ( sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/sdk/trace/tracetest" "go.opentelemetry.io/otel/trace" + nooptrace "go.opentelemetry.io/otel/trace/noop" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/exporter" - "go.opentelemetry.io/collector/exporter/exporterhelper/internal" "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/exporter/internal/queue" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" "go.opentelemetry.io/collector/internal/testdata" - "go.opentelemetry.io/collector/obsreport/obsreporttest" "go.opentelemetry.io/collector/pdata/plog" ) @@ -36,18 +37,18 @@ const ( ) var ( - fakeLogsExporterName = component.NewIDWithName("fake_logs_exporter", "with_name") + fakeLogsExporterName = component.MustNewIDWithName("fake_logs_exporter", "with_name") fakeLogsExporterConfig = struct{}{} ) func TestLogsRequest(t *testing.T) { - lr := newLogsRequest(context.Background(), testdata.GenerateLogs(1), nil) + lr := newLogsRequest(testdata.GenerateLogs(1), nil) logErr := consumererror.NewLogs(errors.New("some error"), plog.NewLogs()) assert.EqualValues( t, - newLogsRequest(context.Background(), plog.NewLogs(), nil), - lr.OnError(logErr), + newLogsRequest(plog.NewLogs(), nil), + lr.(RequestErrorHandler).OnError(logErr), ) } @@ -64,7 +65,7 @@ func TestLogsExporter_NilLogger(t *testing.T) { } func TestLogsRequestExporter_NilLogger(t *testing.T) { - le, err := NewLogsRequestExporter(context.Background(), exporter.CreateSettings{}, &fakeRequestConverter{}) + le, err := NewLogsRequestExporter(context.Background(), exporter.CreateSettings{}, (&fakeRequestConverter{}).requestFromLogsFunc) require.Nil(t, le) require.Equal(t, errNilLogger, err) } @@ -95,7 +96,8 @@ func TestLogsExporter_Default(t *testing.T) { func TestLogsRequestExporter_Default(t *testing.T) { ld := plog.NewLogs() - le, err := NewLogsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), &fakeRequestConverter{}) + le, err := NewLogsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), + (&fakeRequestConverter{}).requestFromLogsFunc) assert.NotNil(t, le) assert.NoError(t, err) @@ -116,7 +118,8 @@ func TestLogsExporter_WithCapabilities(t *testing.T) { func TestLogsRequestExporter_WithCapabilities(t *testing.T) { capabilities := consumer.Capabilities{MutatesData: true} - le, err := NewLogsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), &fakeRequestConverter{}, WithCapabilities(capabilities)) + le, err := NewLogsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), + (&fakeRequestConverter{}).requestFromLogsFunc, WithCapabilities(capabilities)) require.NoError(t, err) require.NotNil(t, le) @@ -135,7 +138,8 @@ func TestLogsExporter_Default_ReturnError(t *testing.T) { func TestLogsRequestExporter_Default_ConvertError(t *testing.T) { ld := plog.NewLogs() want := errors.New("convert_error") - le, err := NewLogsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), &fakeRequestConverter{logsError: want}) + le, err := NewLogsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), + (&fakeRequestConverter{logsError: want}).requestFromLogsFunc) require.NoError(t, err) require.NotNil(t, le) require.Equal(t, consumererror.NewPermanent(want), le.ConsumeLogs(context.Background(), ld)) @@ -145,7 +149,7 @@ func TestLogsRequestExporter_Default_ExportError(t *testing.T) { ld := plog.NewLogs() want := errors.New("export_error") le, err := NewLogsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), - &fakeRequestConverter{requestError: want}) + (&fakeRequestConverter{requestError: want}).requestFromLogsFunc) require.NoError(t, err) require.NotNil(t, le) require.Equal(t, want, le.ConsumeLogs(context.Background(), ld)) @@ -153,17 +157,17 @@ func TestLogsRequestExporter_Default_ExportError(t *testing.T) { func TestLogsExporter_WithPersistentQueue(t *testing.T) { qCfg := NewDefaultQueueSettings() - storageID := component.NewIDWithName("file_storage", "storage") + storageID := component.MustNewIDWithName("file_storage", "storage") qCfg.StorageID = &storageID - rCfg := NewDefaultRetrySettings() + rCfg := configretry.NewDefaultBackOffConfig() ts := consumertest.LogsSink{} set := exportertest.NewNopCreateSettings() - set.ID = component.NewIDWithName("test_logs", "with_persistent_queue") + set.ID = component.MustNewIDWithName("test_logs", "with_persistent_queue") te, err := NewLogsExporter(context.Background(), set, &fakeLogsExporterConfig, ts.ConsumeLogs, WithRetry(rCfg), WithQueue(qCfg)) require.NoError(t, err) host := &mockHost{ext: map[component.ID]component.Component{ - storageID: internal.NewMockStorageExtension(nil), + storageID: queue.NewMockStorageExtension(nil), }} require.NoError(t, te.Start(context.Background(), host)) t.Cleanup(func() { require.NoError(t, te.Shutdown(context.Background())) }) @@ -176,11 +180,11 @@ func TestLogsExporter_WithPersistentQueue(t *testing.T) { } func TestLogsExporter_WithRecordMetrics(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(fakeLogsExporterName) + tt, err := componenttest.SetupTelemetry(fakeLogsExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - le, err := NewLogsExporter(context.Background(), exportertest.NewCreateSettings(fakeLogsExporterName, tt.TelemetrySettings), &fakeLogsExporterConfig, newPushLogsData(nil)) + le, err := NewLogsExporter(context.Background(), exporter.CreateSettings{ID: fakeLogsExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, &fakeLogsExporterConfig, newPushLogsData(nil)) require.NoError(t, err) require.NotNil(t, le) @@ -188,11 +192,13 @@ func TestLogsExporter_WithRecordMetrics(t *testing.T) { } func TestLogsRequestExporter_WithRecordMetrics(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(fakeLogsExporterName) + tt, err := componenttest.SetupTelemetry(fakeLogsExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - le, err := NewLogsRequestExporter(context.Background(), exportertest.NewCreateSettings(fakeLogsExporterName, tt.TelemetrySettings), &fakeRequestConverter{}) + le, err := NewLogsRequestExporter(context.Background(), + exporter.CreateSettings{ID: fakeLogsExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + (&fakeRequestConverter{}).requestFromLogsFunc) require.NoError(t, err) require.NotNil(t, le) @@ -201,11 +207,11 @@ func TestLogsRequestExporter_WithRecordMetrics(t *testing.T) { func TestLogsExporter_WithRecordMetrics_ReturnError(t *testing.T) { want := errors.New("my_error") - tt, err := obsreporttest.SetupTelemetry(fakeLogsExporterName) + tt, err := componenttest.SetupTelemetry(fakeLogsExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - le, err := NewLogsExporter(context.Background(), exportertest.NewCreateSettings(fakeLogsExporterName, tt.TelemetrySettings), &fakeLogsExporterConfig, newPushLogsData(want)) + le, err := NewLogsExporter(context.Background(), exporter.CreateSettings{ID: fakeLogsExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, &fakeLogsExporterConfig, newPushLogsData(want)) require.Nil(t, err) require.NotNil(t, le) @@ -214,12 +220,12 @@ func TestLogsExporter_WithRecordMetrics_ReturnError(t *testing.T) { func TestLogsRequestExporter_WithRecordMetrics_ExportError(t *testing.T) { want := errors.New("export_error") - tt, err := obsreporttest.SetupTelemetry(fakeLogsExporterName) + tt, err := componenttest.SetupTelemetry(fakeLogsExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - le, err := NewLogsRequestExporter(context.Background(), exportertest.NewCreateSettings(fakeLogsExporterName, tt.TelemetrySettings), - &fakeRequestConverter{requestError: want}) + le, err := NewLogsRequestExporter(context.Background(), exporter.CreateSettings{ID: fakeLogsExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + (&fakeRequestConverter{requestError: want}).requestFromLogsFunc) require.Nil(t, err) require.NotNil(t, le) @@ -227,16 +233,16 @@ func TestLogsRequestExporter_WithRecordMetrics_ExportError(t *testing.T) { } func TestLogsExporter_WithRecordEnqueueFailedMetrics(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(fakeLogsExporterName) + tt, err := componenttest.SetupTelemetry(fakeLogsExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - rCfg := NewDefaultRetrySettings() + rCfg := configretry.NewDefaultBackOffConfig() qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 1 qCfg.QueueSize = 2 wantErr := errors.New("some-error") - te, err := NewLogsExporter(context.Background(), exportertest.NewCreateSettings(fakeLogsExporterName, tt.TelemetrySettings), &fakeLogsExporterConfig, newPushLogsData(wantErr), WithRetry(rCfg), WithQueue(qCfg)) + te, err := NewLogsExporter(context.Background(), exporter.CreateSettings{ID: fakeLogsExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, &fakeLogsExporterConfig, newPushLogsData(wantErr), WithRetry(rCfg), WithQueue(qCfg)) require.NoError(t, err) require.NotNil(t, te) @@ -248,7 +254,7 @@ func TestLogsExporter_WithRecordEnqueueFailedMetrics(t *testing.T) { } // 2 batched must be in queue, and 5 batches (15 log records) rejected due to queue overflow - checkExporterEnqueueFailedLogsStats(t, globalInstruments, fakeLogsExporterName, int64(15)) + require.NoError(t, tt.CheckExporterEnqueueFailedLogs(int64(15))) } func TestLogsExporter_WithSpan(t *testing.T) { @@ -256,7 +262,7 @@ func TestLogsExporter_WithSpan(t *testing.T) { sr := new(tracetest.SpanRecorder) set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) otel.SetTracerProvider(set.TracerProvider) - defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) le, err := NewLogsExporter(context.Background(), set, &fakeLogsExporterConfig, newPushLogsData(nil)) require.Nil(t, err) @@ -269,9 +275,9 @@ func TestLogsRequestExporter_WithSpan(t *testing.T) { sr := new(tracetest.SpanRecorder) set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) otel.SetTracerProvider(set.TracerProvider) - defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) - le, err := NewLogsRequestExporter(context.Background(), set, &fakeRequestConverter{}) + le, err := NewLogsRequestExporter(context.Background(), set, (&fakeRequestConverter{}).requestFromLogsFunc) require.Nil(t, err) require.NotNil(t, le) checkWrapSpanForLogsExporter(t, sr, set.TracerProvider.Tracer("test"), le, nil, 1) @@ -282,7 +288,7 @@ func TestLogsExporter_WithSpan_ReturnError(t *testing.T) { sr := new(tracetest.SpanRecorder) set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) otel.SetTracerProvider(set.TracerProvider) - defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) want := errors.New("my_error") le, err := NewLogsExporter(context.Background(), set, &fakeLogsExporterConfig, newPushLogsData(want)) @@ -296,10 +302,10 @@ func TestLogsRequestExporter_WithSpan_ReturnError(t *testing.T) { sr := new(tracetest.SpanRecorder) set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) otel.SetTracerProvider(set.TracerProvider) - defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) want := errors.New("my_error") - le, err := NewLogsRequestExporter(context.Background(), set, &fakeRequestConverter{requestError: want}) + le, err := NewLogsRequestExporter(context.Background(), set, (&fakeRequestConverter{requestError: want}).requestFromLogsFunc) require.Nil(t, err) require.NotNil(t, le) checkWrapSpanForLogsExporter(t, sr, set.TracerProvider.Tracer("test"), le, want, 1) @@ -321,7 +327,8 @@ func TestLogsRequestExporter_WithShutdown(t *testing.T) { shutdownCalled := false shutdown := func(context.Context) error { shutdownCalled = true; return nil } - le, err := NewLogsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), &fakeRequestConverter{}, WithShutdown(shutdown)) + le, err := NewLogsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), + (&fakeRequestConverter{}).requestFromLogsFunc, WithShutdown(shutdown)) assert.NotNil(t, le) assert.NoError(t, err) @@ -344,7 +351,8 @@ func TestLogsRequestExporter_WithShutdown_ReturnError(t *testing.T) { want := errors.New("my_error") shutdownErr := func(context.Context) error { return want } - le, err := NewLogsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), &fakeRequestConverter{}, WithShutdown(shutdownErr)) + le, err := NewLogsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), + (&fakeRequestConverter{}).requestFromLogsFunc, WithShutdown(shutdownErr)) assert.NotNil(t, le) assert.NoError(t, err) @@ -352,12 +360,12 @@ func TestLogsRequestExporter_WithShutdown_ReturnError(t *testing.T) { } func newPushLogsData(retError error) consumer.ConsumeLogsFunc { - return func(ctx context.Context, td plog.Logs) error { + return func(_ context.Context, _ plog.Logs) error { return retError } } -func checkRecordedMetricsForLogsExporter(t *testing.T, tt obsreporttest.TestTelemetry, le exporter.Logs, wantError error) { +func checkRecordedMetricsForLogsExporter(t *testing.T, tt componenttest.TestTelemetry, le exporter.Logs, wantError error) { ld := testdata.GenerateLogs(2) const numBatches = 7 for i := 0; i < numBatches; i++ { diff --git a/exporter/exporterhelper/metrics.go b/exporter/exporterhelper/metrics.go index e3f09f361c7..ab7d65dae65 100644 --- a/exporter/exporterhelper/metrics.go +++ b/exporter/exporterhelper/metrics.go @@ -13,7 +13,8 @@ import ( "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/exporter" - "go.opentelemetry.io/collector/exporter/exporterhelper/internal" + "go.opentelemetry.io/collector/exporter/exporterqueue" + "go.opentelemetry.io/collector/exporter/internal/queue" "go.opentelemetry.io/collector/pdata/pmetric" ) @@ -21,37 +22,35 @@ var metricsMarshaler = &pmetric.ProtoMarshaler{} var metricsUnmarshaler = &pmetric.ProtoUnmarshaler{} type metricsRequest struct { - baseRequest md pmetric.Metrics pusher consumer.ConsumeMetricsFunc } -func newMetricsRequest(ctx context.Context, md pmetric.Metrics, pusher consumer.ConsumeMetricsFunc) internal.Request { +func newMetricsRequest(md pmetric.Metrics, pusher consumer.ConsumeMetricsFunc) Request { return &metricsRequest{ - baseRequest: baseRequest{ctx: ctx}, - md: md, - pusher: pusher, + md: md, + pusher: pusher, } } -func newMetricsRequestUnmarshalerFunc(pusher consumer.ConsumeMetricsFunc) internal.RequestUnmarshaler { - return func(bytes []byte) (internal.Request, error) { +func newMetricsRequestUnmarshalerFunc(pusher consumer.ConsumeMetricsFunc) exporterqueue.Unmarshaler[Request] { + return func(bytes []byte) (Request, error) { metrics, err := metricsUnmarshaler.UnmarshalMetrics(bytes) if err != nil { return nil, err } - return newMetricsRequest(context.Background(), metrics, pusher), nil + return newMetricsRequest(metrics, pusher), nil } } -func metricsRequestMarshaler(req internal.Request) ([]byte, error) { +func metricsRequestMarshaler(req Request) ([]byte, error) { return metricsMarshaler.MarshalMetrics(req.(*metricsRequest).md) } -func (req *metricsRequest) OnError(err error) internal.Request { +func (req *metricsRequest) OnError(err error) Request { var metricsError consumererror.Metrics if errors.As(err, &metricsError) { - return newMetricsRequest(req.ctx, metricsError.Data(), req.pusher) + return newMetricsRequest(metricsError.Data(), req.pusher) } return req } @@ -60,7 +59,7 @@ func (req *metricsRequest) Export(ctx context.Context) error { return req.pusher(ctx, req.md) } -func (req *metricsRequest) Count() int { +func (req *metricsRequest) ItemsCount() int { return req.md.DataPointCount() } @@ -71,7 +70,7 @@ type metricsExporter struct { // NewMetricsExporter creates an exporter.Metrics that records observability metrics and wraps every request with a Span. func NewMetricsExporter( - _ context.Context, + ctx context.Context, set exporter.CreateSettings, cfg component.Config, pusher consumer.ConsumeMetricsFunc, @@ -80,42 +79,23 @@ func NewMetricsExporter( if cfg == nil { return nil, errNilConfig } - - if set.Logger == nil { - return nil, errNilLogger - } - if pusher == nil { return nil, errNilPushMetricsData } - - be, err := newBaseExporter(set, component.DataTypeMetrics, false, metricsRequestMarshaler, - newMetricsRequestUnmarshalerFunc(pusher), newMetricsSenderWithObservability, options...) - if err != nil { - return nil, err - } - - mc, err := consumer.NewMetrics(func(ctx context.Context, md pmetric.Metrics) error { - req := newMetricsRequest(ctx, md, pusher) - serr := be.send(req) - if errors.Is(serr, errSendingQueueIsFull) { - be.obsrep.recordMetricsEnqueueFailure(req.Context(), int64(req.Count())) - } - return serr - }, be.consumerOptions...) - - return &metricsExporter{ - baseExporter: be, - Metrics: mc, - }, err + metricsOpts := []Option{withMarshaler(metricsRequestMarshaler), withUnmarshaler(newMetricsRequestUnmarshalerFunc(pusher))} + return NewMetricsRequestExporter(ctx, set, requestFromMetrics(pusher), append(metricsOpts, options...)...) } -// MetricsConverter provides an interface for converting pmetric.Metrics into a request. +// RequestFromMetricsFunc converts pdata.Metrics into a user-defined request. // This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. -type MetricsConverter interface { - // RequestFromMetrics converts pdata.Metrics into a request. - RequestFromMetrics(context.Context, pmetric.Metrics) (Request, error) +type RequestFromMetricsFunc func(context.Context, pmetric.Metrics) (Request, error) + +// requestFromMetrics returns a RequestFromMetricsFunc that converts pdata.Metrics into a Request. +func requestFromMetrics(pusher consumer.ConsumeMetricsFunc) RequestFromMetricsFunc { + return func(_ context.Context, md pmetric.Metrics) (Request, error) { + return newMetricsRequest(md, pusher), nil + } } // NewMetricsRequestExporter creates a new metrics exporter based on a custom MetricsConverter and RequestSender. @@ -124,7 +104,7 @@ type MetricsConverter interface { func NewMetricsRequestExporter( _ context.Context, set exporter.CreateSettings, - converter MetricsConverter, + converter RequestFromMetricsFunc, options ...Option, ) (exporter.Metrics, error) { if set.Logger == nil { @@ -135,23 +115,22 @@ func NewMetricsRequestExporter( return nil, errNilMetricsConverter } - be, err := newBaseExporter(set, component.DataTypeMetrics, true, nil, nil, newMetricsSenderWithObservability, options...) + be, err := newBaseExporter(set, component.DataTypeMetrics, newMetricsSenderWithObservability, options...) if err != nil { return nil, err } mc, err := consumer.NewMetrics(func(ctx context.Context, md pmetric.Metrics) error { - req, cErr := converter.RequestFromMetrics(ctx, md) + req, cErr := converter(ctx, md) if cErr != nil { set.Logger.Error("Failed to convert metrics. Dropping data.", zap.Int("dropped_data_points", md.DataPointCount()), zap.Error(err)) return consumererror.NewPermanent(cErr) } - r := newRequest(ctx, req) - sErr := be.send(r) - if errors.Is(sErr, errSendingQueueIsFull) { - be.obsrep.recordMetricsEnqueueFailure(r.Context(), int64(r.Count())) + sErr := be.send(ctx, req) + if errors.Is(sErr, queue.ErrQueueIsFull) { + be.obsrep.recordEnqueueFailure(ctx, component.DataTypeMetrics, int64(req.ItemsCount())) } return sErr }, be.consumerOptions...) @@ -164,16 +143,16 @@ func NewMetricsRequestExporter( type metricsSenderWithObservability struct { baseRequestSender - obsrep *obsExporter + obsrep *ObsReport } -func newMetricsSenderWithObservability(obsrep *obsExporter) requestSender { +func newMetricsSenderWithObservability(obsrep *ObsReport) requestSender { return &metricsSenderWithObservability{obsrep: obsrep} } -func (mewo *metricsSenderWithObservability) send(req internal.Request) error { - req.SetContext(mewo.obsrep.StartMetricsOp(req.Context())) - err := mewo.nextSender.send(req) - mewo.obsrep.EndMetricsOp(req.Context(), req.Count(), err) +func (mewo *metricsSenderWithObservability) send(ctx context.Context, req Request) error { + c := mewo.obsrep.StartMetricsOp(ctx) + err := mewo.nextSender.send(c, req) + mewo.obsrep.EndMetricsOp(c, req.ItemsCount(), err) return err } diff --git a/exporter/exporterhelper/metrics_test.go b/exporter/exporterhelper/metrics_test.go index 81fab6f04ca..ddbefeb71f2 100644 --- a/exporter/exporterhelper/metrics_test.go +++ b/exporter/exporterhelper/metrics_test.go @@ -16,18 +16,19 @@ import ( sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/sdk/trace/tracetest" "go.opentelemetry.io/otel/trace" + nooptrace "go.opentelemetry.io/otel/trace/noop" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/exporter" - "go.opentelemetry.io/collector/exporter/exporterhelper/internal" "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/exporter/internal/queue" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" "go.opentelemetry.io/collector/internal/testdata" - "go.opentelemetry.io/collector/obsreport/obsreporttest" "go.opentelemetry.io/collector/pdata/pmetric" ) @@ -36,18 +37,18 @@ const ( ) var ( - fakeMetricsExporterName = component.NewIDWithName("fake_metrics_exporter", "with_name") + fakeMetricsExporterName = component.MustNewIDWithName("fake_metrics_exporter", "with_name") fakeMetricsExporterConfig = struct{}{} ) func TestMetricsRequest(t *testing.T) { - mr := newMetricsRequest(context.Background(), testdata.GenerateMetrics(1), nil) + mr := newMetricsRequest(testdata.GenerateMetrics(1), nil) metricsErr := consumererror.NewMetrics(errors.New("some error"), pmetric.NewMetrics()) assert.EqualValues( t, - newMetricsRequest(context.Background(), pmetric.NewMetrics(), nil), - mr.OnError(metricsErr), + newMetricsRequest(pmetric.NewMetrics(), nil), + mr.(RequestErrorHandler).OnError(metricsErr), ) } @@ -64,7 +65,8 @@ func TestMetricsExporter_NilLogger(t *testing.T) { } func TestMetricsRequestExporter_NilLogger(t *testing.T) { - me, err := NewMetricsRequestExporter(context.Background(), exporter.CreateSettings{}, fakeRequestConverter{}) + me, err := NewMetricsRequestExporter(context.Background(), exporter.CreateSettings{}, + (&fakeRequestConverter{}).requestFromMetricsFunc) require.Nil(t, me) require.Equal(t, errNilLogger, err) } @@ -95,7 +97,8 @@ func TestMetricsExporter_Default(t *testing.T) { func TestMetricsRequestExporter_Default(t *testing.T) { md := pmetric.NewMetrics() - me, err := NewMetricsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), fakeRequestConverter{}) + me, err := NewMetricsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), + (&fakeRequestConverter{}).requestFromMetricsFunc) assert.NoError(t, err) assert.NotNil(t, me) @@ -116,8 +119,8 @@ func TestMetricsExporter_WithCapabilities(t *testing.T) { func TestMetricsRequestExporter_WithCapabilities(t *testing.T) { capabilities := consumer.Capabilities{MutatesData: true} - me, err := NewMetricsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), fakeRequestConverter{}, - WithCapabilities(capabilities)) + me, err := NewMetricsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), + (&fakeRequestConverter{}).requestFromMetricsFunc, WithCapabilities(capabilities)) assert.NoError(t, err) assert.NotNil(t, me) @@ -136,7 +139,8 @@ func TestMetricsExporter_Default_ReturnError(t *testing.T) { func TestMetricsRequestExporter_Default_ConvertError(t *testing.T) { md := pmetric.NewMetrics() want := errors.New("convert_error") - me, err := NewMetricsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), fakeRequestConverter{metricsError: want}) + me, err := NewMetricsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), + (&fakeRequestConverter{metricsError: want}).requestFromMetricsFunc) require.NoError(t, err) require.NotNil(t, me) require.Equal(t, consumererror.NewPermanent(want), me.ConsumeMetrics(context.Background(), md)) @@ -146,7 +150,7 @@ func TestMetricsRequestExporter_Default_ExportError(t *testing.T) { md := pmetric.NewMetrics() want := errors.New("export_error") me, err := NewMetricsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), - fakeRequestConverter{requestError: want}) + (&fakeRequestConverter{requestError: want}).requestFromMetricsFunc) require.NoError(t, err) require.NotNil(t, me) require.Equal(t, want, me.ConsumeMetrics(context.Background(), md)) @@ -154,17 +158,17 @@ func TestMetricsRequestExporter_Default_ExportError(t *testing.T) { func TestMetricsExporter_WithPersistentQueue(t *testing.T) { qCfg := NewDefaultQueueSettings() - storageID := component.NewIDWithName("file_storage", "storage") + storageID := component.MustNewIDWithName("file_storage", "storage") qCfg.StorageID = &storageID - rCfg := NewDefaultRetrySettings() + rCfg := configretry.NewDefaultBackOffConfig() ms := consumertest.MetricsSink{} set := exportertest.NewNopCreateSettings() - set.ID = component.NewIDWithName("test_metrics", "with_persistent_queue") + set.ID = component.MustNewIDWithName("test_metrics", "with_persistent_queue") te, err := NewMetricsExporter(context.Background(), set, &fakeTracesExporterConfig, ms.ConsumeMetrics, WithRetry(rCfg), WithQueue(qCfg)) require.NoError(t, err) host := &mockHost{ext: map[component.ID]component.Component{ - storageID: internal.NewMockStorageExtension(nil), + storageID: queue.NewMockStorageExtension(nil), }} require.NoError(t, te.Start(context.Background(), host)) t.Cleanup(func() { require.NoError(t, te.Shutdown(context.Background())) }) @@ -177,11 +181,11 @@ func TestMetricsExporter_WithPersistentQueue(t *testing.T) { } func TestMetricsExporter_WithRecordMetrics(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(fakeMetricsExporterName) + tt, err := componenttest.SetupTelemetry(fakeMetricsExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - me, err := NewMetricsExporter(context.Background(), exportertest.NewCreateSettings(fakeMetricsExporterName, tt.TelemetrySettings), &fakeMetricsExporterConfig, newPushMetricsData(nil)) + me, err := NewMetricsExporter(context.Background(), exporter.CreateSettings{ID: fakeMetricsExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, &fakeMetricsExporterConfig, newPushMetricsData(nil)) require.NoError(t, err) require.NotNil(t, me) @@ -189,11 +193,13 @@ func TestMetricsExporter_WithRecordMetrics(t *testing.T) { } func TestMetricsRequestExporter_WithRecordMetrics(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(fakeMetricsExporterName) + tt, err := componenttest.SetupTelemetry(fakeMetricsExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - me, err := NewMetricsRequestExporter(context.Background(), exportertest.NewCreateSettings(fakeMetricsExporterName, tt.TelemetrySettings), fakeRequestConverter{}) + me, err := NewMetricsRequestExporter(context.Background(), + exporter.CreateSettings{ID: fakeMetricsExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + (&fakeRequestConverter{}).requestFromMetricsFunc) require.NoError(t, err) require.NotNil(t, me) @@ -202,11 +208,11 @@ func TestMetricsRequestExporter_WithRecordMetrics(t *testing.T) { func TestMetricsExporter_WithRecordMetrics_ReturnError(t *testing.T) { want := errors.New("my_error") - tt, err := obsreporttest.SetupTelemetry(fakeMetricsExporterName) + tt, err := componenttest.SetupTelemetry(fakeMetricsExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - me, err := NewMetricsExporter(context.Background(), exportertest.NewCreateSettings(fakeMetricsExporterName, tt.TelemetrySettings), &fakeMetricsExporterConfig, newPushMetricsData(want)) + me, err := NewMetricsExporter(context.Background(), exporter.CreateSettings{ID: fakeMetricsExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, &fakeMetricsExporterConfig, newPushMetricsData(want)) require.NoError(t, err) require.NotNil(t, me) @@ -215,11 +221,13 @@ func TestMetricsExporter_WithRecordMetrics_ReturnError(t *testing.T) { func TestMetricsRequestExporter_WithRecordMetrics_ExportError(t *testing.T) { want := errors.New("my_error") - tt, err := obsreporttest.SetupTelemetry(fakeMetricsExporterName) + tt, err := componenttest.SetupTelemetry(fakeMetricsExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - me, err := NewMetricsRequestExporter(context.Background(), exportertest.NewCreateSettings(fakeMetricsExporterName, tt.TelemetrySettings), fakeRequestConverter{requestError: want}) + me, err := NewMetricsRequestExporter(context.Background(), + exporter.CreateSettings{ID: fakeMetricsExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + (&fakeRequestConverter{requestError: want}).requestFromMetricsFunc) require.NoError(t, err) require.NotNil(t, me) @@ -227,16 +235,16 @@ func TestMetricsRequestExporter_WithRecordMetrics_ExportError(t *testing.T) { } func TestMetricsExporter_WithRecordEnqueueFailedMetrics(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(fakeMetricsExporterName) + tt, err := componenttest.SetupTelemetry(fakeMetricsExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - rCfg := NewDefaultRetrySettings() + rCfg := configretry.NewDefaultBackOffConfig() qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 1 qCfg.QueueSize = 2 wantErr := errors.New("some-error") - te, err := NewMetricsExporter(context.Background(), exportertest.NewCreateSettings(fakeMetricsExporterName, tt.TelemetrySettings), &fakeMetricsExporterConfig, newPushMetricsData(wantErr), WithRetry(rCfg), WithQueue(qCfg)) + te, err := NewMetricsExporter(context.Background(), exporter.CreateSettings{ID: fakeMetricsExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, &fakeMetricsExporterConfig, newPushMetricsData(wantErr), WithRetry(rCfg), WithQueue(qCfg)) require.NoError(t, err) require.NotNil(t, te) @@ -248,7 +256,7 @@ func TestMetricsExporter_WithRecordEnqueueFailedMetrics(t *testing.T) { } // 2 batched must be in queue, and 10 metric points rejected due to queue overflow - checkExporterEnqueueFailedMetricsStats(t, globalInstruments, fakeMetricsExporterName, int64(10)) + require.NoError(t, tt.CheckExporterEnqueueFailedMetrics(int64(10))) } func TestMetricsExporter_WithSpan(t *testing.T) { @@ -256,7 +264,7 @@ func TestMetricsExporter_WithSpan(t *testing.T) { sr := new(tracetest.SpanRecorder) set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) otel.SetTracerProvider(set.TracerProvider) - defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) me, err := NewMetricsExporter(context.Background(), set, &fakeMetricsExporterConfig, newPushMetricsData(nil)) require.NoError(t, err) @@ -269,9 +277,9 @@ func TestMetricsRequestExporter_WithSpan(t *testing.T) { sr := new(tracetest.SpanRecorder) set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) otel.SetTracerProvider(set.TracerProvider) - defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) - me, err := NewMetricsRequestExporter(context.Background(), set, fakeRequestConverter{}) + me, err := NewMetricsRequestExporter(context.Background(), set, (&fakeRequestConverter{}).requestFromMetricsFunc) require.NoError(t, err) require.NotNil(t, me) checkWrapSpanForMetricsExporter(t, sr, set.TracerProvider.Tracer("test"), me, nil, 2) @@ -282,7 +290,7 @@ func TestMetricsExporter_WithSpan_ReturnError(t *testing.T) { sr := new(tracetest.SpanRecorder) set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) otel.SetTracerProvider(set.TracerProvider) - defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) want := errors.New("my_error") me, err := NewMetricsExporter(context.Background(), set, &fakeMetricsExporterConfig, newPushMetricsData(want)) @@ -296,10 +304,10 @@ func TestMetricsRequestExporter_WithSpan_ExportError(t *testing.T) { sr := new(tracetest.SpanRecorder) set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) otel.SetTracerProvider(set.TracerProvider) - defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) want := errors.New("my_error") - me, err := NewMetricsRequestExporter(context.Background(), set, fakeRequestConverter{requestError: want}) + me, err := NewMetricsRequestExporter(context.Background(), set, (&fakeRequestConverter{requestError: want}).requestFromMetricsFunc) require.NoError(t, err) require.NotNil(t, me) checkWrapSpanForMetricsExporter(t, sr, set.TracerProvider.Tracer("test"), me, want, 2) @@ -323,7 +331,7 @@ func TestMetricsRequestExporter_WithShutdown(t *testing.T) { shutdown := func(context.Context) error { shutdownCalled = true; return nil } me, err := NewMetricsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), - &fakeRequestConverter{}, WithShutdown(shutdown)) + (&fakeRequestConverter{}).requestFromMetricsFunc, WithShutdown(shutdown)) assert.NotNil(t, me) assert.NoError(t, err) @@ -349,7 +357,7 @@ func TestMetricsRequestExporter_WithShutdown_ReturnError(t *testing.T) { shutdownErr := func(context.Context) error { return want } me, err := NewMetricsRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), - &fakeRequestConverter{}, WithShutdown(shutdownErr)) + (&fakeRequestConverter{}).requestFromMetricsFunc, WithShutdown(shutdownErr)) assert.NotNil(t, me) assert.NoError(t, err) @@ -358,12 +366,12 @@ func TestMetricsRequestExporter_WithShutdown_ReturnError(t *testing.T) { } func newPushMetricsData(retError error) consumer.ConsumeMetricsFunc { - return func(ctx context.Context, td pmetric.Metrics) error { + return func(_ context.Context, _ pmetric.Metrics) error { return retError } } -func checkRecordedMetricsForMetricsExporter(t *testing.T, tt obsreporttest.TestTelemetry, me exporter.Metrics, wantError error) { +func checkRecordedMetricsForMetricsExporter(t *testing.T, tt componenttest.TestTelemetry, me exporter.Metrics, wantError error) { md := testdata.GenerateMetrics(2) const numBatches = 7 for i := 0; i < numBatches; i++ { diff --git a/exporter/exporterhelper/obsexporter.go b/exporter/exporterhelper/obsexporter.go index e6bc950f708..f42c0195f49 100644 --- a/exporter/exporterhelper/obsexporter.go +++ b/exporter/exporterhelper/obsexporter.go @@ -5,14 +5,10 @@ package exporterhelper // import "go.opentelemetry.io/collector/exporter/exporte import ( "context" - "errors" - "go.opencensus.io/stats" - "go.opencensus.io/tag" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/metric" - sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/trace" "go.uber.org/multierr" "go.uber.org/zap" @@ -20,7 +16,6 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configtelemetry" "go.opentelemetry.io/collector/exporter" - "go.opentelemetry.io/collector/internal/obsreportconfig" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" ) @@ -32,18 +27,19 @@ const ( type ObsReport struct { level configtelemetry.Level spanNamePrefix string - mutators []tag.Mutator tracer trace.Tracer logger *zap.Logger - useOtelForMetrics bool - otelAttrs []attribute.KeyValue - sentSpans metric.Int64Counter - failedToSendSpans metric.Int64Counter - sentMetricPoints metric.Int64Counter - failedToSendMetricPoints metric.Int64Counter - sentLogRecords metric.Int64Counter - failedToSendLogRecords metric.Int64Counter + otelAttrs []attribute.KeyValue + sentSpans metric.Int64Counter + failedToSendSpans metric.Int64Counter + failedToEnqueueSpans metric.Int64Counter + sentMetricPoints metric.Int64Counter + failedToSendMetricPoints metric.Int64Counter + failedToEnqueueMetricPoints metric.Int64Counter + sentLogRecords metric.Int64Counter + failedToSendLogRecords metric.Int64Counter + failedToEnqueueLogRecords metric.Int64Counter } // ObsReportSettings are settings for creating an ObsReport. @@ -54,28 +50,22 @@ type ObsReportSettings struct { // NewObsReport creates a new Exporter. func NewObsReport(cfg ObsReportSettings) (*ObsReport, error) { - return newExporter(cfg, obsreportconfig.UseOtelForInternalMetricsfeatureGate.IsEnabled()) + return newExporter(cfg) } -func newExporter(cfg ObsReportSettings, useOtel bool) (*ObsReport, error) { +func newExporter(cfg ObsReportSettings) (*ObsReport, error) { exp := &ObsReport{ level: cfg.ExporterCreateSettings.TelemetrySettings.MetricsLevel, spanNamePrefix: obsmetrics.ExporterPrefix + cfg.ExporterID.String(), - mutators: []tag.Mutator{tag.Upsert(obsmetrics.TagKeyExporter, cfg.ExporterID.String(), tag.WithTTL(tag.TTLNoPropagation))}, tracer: cfg.ExporterCreateSettings.TracerProvider.Tracer(cfg.ExporterID.String()), logger: cfg.ExporterCreateSettings.Logger, - useOtelForMetrics: useOtel, otelAttrs: []attribute.KeyValue{ attribute.String(obsmetrics.ExporterKey, cfg.ExporterID.String()), }, } - // ignore instrument name error as per workaround in https://github.com/open-telemetry/opentelemetry-collector/issues/8346 - // if err := exp.createOtelMetrics(cfg); err != nil { - // return nil, err - // } - if err := exp.createOtelMetrics(cfg); err != nil && !errors.Is(err, sdkmetric.ErrInstrumentName) { + if err := exp.createOtelMetrics(cfg); err != nil { return nil, err } @@ -83,9 +73,6 @@ func newExporter(cfg ObsReportSettings, useOtel bool) (*ObsReport, error) { } func (or *ObsReport) createOtelMetrics(cfg ObsReportSettings) error { - if !or.useOtelForMetrics { - return nil - } meter := cfg.ExporterCreateSettings.MeterProvider.Meter(exporterScope) var errors, err error @@ -102,6 +89,12 @@ func (or *ObsReport) createOtelMetrics(cfg ObsReportSettings) error { metric.WithUnit("1")) errors = multierr.Append(errors, err) + or.failedToEnqueueSpans, err = meter.Int64Counter( + obsmetrics.ExporterPrefix+obsmetrics.FailedToEnqueueSpansKey, + metric.WithDescription("Number of spans failed to be added to the sending queue."), + metric.WithUnit("1")) + errors = multierr.Append(errors, err) + or.sentMetricPoints, err = meter.Int64Counter( obsmetrics.ExporterPrefix+obsmetrics.SentMetricPointsKey, metric.WithDescription("Number of metric points successfully sent to destination."), @@ -114,6 +107,12 @@ func (or *ObsReport) createOtelMetrics(cfg ObsReportSettings) error { metric.WithUnit("1")) errors = multierr.Append(errors, err) + or.failedToEnqueueMetricPoints, err = meter.Int64Counter( + obsmetrics.ExporterPrefix+obsmetrics.FailedToEnqueueMetricPointsKey, + metric.WithDescription("Number of metric points failed to be added to the sending queue."), + metric.WithUnit("1")) + errors = multierr.Append(errors, err) + or.sentLogRecords, err = meter.Int64Counter( obsmetrics.ExporterPrefix+obsmetrics.SentLogRecordsKey, metric.WithDescription("Number of log record successfully sent to destination."), @@ -126,6 +125,12 @@ func (or *ObsReport) createOtelMetrics(cfg ObsReportSettings) error { metric.WithUnit("1")) errors = multierr.Append(errors, err) + or.failedToEnqueueLogRecords, err = meter.Int64Counter( + obsmetrics.ExporterPrefix+obsmetrics.FailedToEnqueueLogRecordsKey, + metric.WithDescription("Number of log records failed to be added to the sending queue."), + metric.WithUnit("1")) + errors = multierr.Append(errors, err) + return errors } @@ -139,7 +144,7 @@ func (or *ObsReport) StartTracesOp(ctx context.Context) context.Context { // EndTracesOp completes the export operation that was started with StartTracesOp. func (or *ObsReport) EndTracesOp(ctx context.Context, numSpans int, err error) { numSent, numFailedToSend := toNumItems(numSpans, err) - or.recordMetrics(ctx, component.DataTypeTraces, numSent, numFailedToSend) + or.recordMetrics(noCancellationContext{Context: ctx}, component.DataTypeTraces, numSent, numFailedToSend) endSpan(ctx, err, numSent, numFailedToSend, obsmetrics.SentSpansKey, obsmetrics.FailedToSendSpansKey) } @@ -154,7 +159,7 @@ func (or *ObsReport) StartMetricsOp(ctx context.Context) context.Context { // StartMetricsOp. func (or *ObsReport) EndMetricsOp(ctx context.Context, numMetricPoints int, err error) { numSent, numFailedToSend := toNumItems(numMetricPoints, err) - or.recordMetrics(ctx, component.DataTypeMetrics, numSent, numFailedToSend) + or.recordMetrics(noCancellationContext{Context: ctx}, component.DataTypeMetrics, numSent, numFailedToSend) endSpan(ctx, err, numSent, numFailedToSend, obsmetrics.SentMetricPointsKey, obsmetrics.FailedToSendMetricPointsKey) } @@ -168,7 +173,7 @@ func (or *ObsReport) StartLogsOp(ctx context.Context) context.Context { // EndLogsOp completes the export operation that was started with StartLogsOp. func (or *ObsReport) EndLogsOp(ctx context.Context, numLogRecords int, err error) { numSent, numFailedToSend := toNumItems(numLogRecords, err) - or.recordMetrics(ctx, component.DataTypeLogs, numSent, numFailedToSend) + or.recordMetrics(noCancellationContext{Context: ctx}, component.DataTypeLogs, numSent, numFailedToSend) endSpan(ctx, err, numSent, numFailedToSend, obsmetrics.SentLogRecordsKey, obsmetrics.FailedToSendLogRecordsKey) } @@ -180,18 +185,10 @@ func (or *ObsReport) startOp(ctx context.Context, operationSuffix string) contex return ctx } -func (or *ObsReport) recordMetrics(ctx context.Context, dataType component.DataType, numSent, numFailed int64) { +func (or *ObsReport) recordMetrics(ctx context.Context, dataType component.DataType, sent, failed int64) { if or.level == configtelemetry.LevelNone { return } - if or.useOtelForMetrics { - or.recordWithOtel(ctx, dataType, numSent, numFailed) - } else { - or.recordWithOC(ctx, dataType, numSent, numFailed) - } -} - -func (or *ObsReport) recordWithOtel(ctx context.Context, dataType component.DataType, sent int64, failed int64) { var sentMeasure, failedMeasure metric.Int64Counter switch dataType { case component.DataTypeTraces: @@ -209,34 +206,6 @@ func (or *ObsReport) recordWithOtel(ctx context.Context, dataType component.Data failedMeasure.Add(ctx, failed, metric.WithAttributes(or.otelAttrs...)) } -func (or *ObsReport) recordWithOC(ctx context.Context, dataType component.DataType, sent int64, failed int64) { - var sentMeasure, failedMeasure *stats.Int64Measure - switch dataType { - case component.DataTypeTraces: - sentMeasure = obsmetrics.ExporterSentSpans - failedMeasure = obsmetrics.ExporterFailedToSendSpans - case component.DataTypeMetrics: - sentMeasure = obsmetrics.ExporterSentMetricPoints - failedMeasure = obsmetrics.ExporterFailedToSendMetricPoints - case component.DataTypeLogs: - sentMeasure = obsmetrics.ExporterSentLogRecords - failedMeasure = obsmetrics.ExporterFailedToSendLogRecords - } - - if failed > 0 { - _ = stats.RecordWithTags( - ctx, - or.mutators, - sentMeasure.M(sent), - failedMeasure.M(failed)) - } else { - _ = stats.RecordWithTags( - ctx, - or.mutators, - sentMeasure.M(sent)) - } -} - func endSpan(ctx context.Context, err error, numSent, numFailedToSend int64, sentItemsKey, failedToSendItemsKey string) { span := trace.SpanFromContext(ctx) // End the span according to errors. @@ -258,3 +227,17 @@ func toNumItems(numExportedItems int, err error) (int64, int64) { } return int64(numExportedItems), 0 } + +func (or *ObsReport) recordEnqueueFailure(ctx context.Context, dataType component.DataType, failed int64) { + var enqueueFailedMeasure metric.Int64Counter + switch dataType { + case component.DataTypeTraces: + enqueueFailedMeasure = or.failedToEnqueueSpans + case component.DataTypeMetrics: + enqueueFailedMeasure = or.failedToEnqueueMetricPoints + case component.DataTypeLogs: + enqueueFailedMeasure = or.failedToEnqueueLogRecords + } + + enqueueFailedMeasure.Add(ctx, failed, metric.WithAttributes(or.otelAttrs...)) +} diff --git a/exporter/exporterhelper/obsexporter_test.go b/exporter/exporterhelper/obsexporter_test.go index b1942e98306..f6f46ccbad2 100644 --- a/exporter/exporterhelper/obsexporter_test.go +++ b/exporter/exporterhelper/obsexporter_test.go @@ -14,26 +14,26 @@ import ( "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" - "go.opentelemetry.io/collector/obsreport/obsreporttest" ) var ( - exporterID = component.NewID("fakeExporter") + exporterID = component.MustNewID("fakeExporter") errFake = errors.New("errFake") ) func TestExportTraceDataOp(t *testing.T) { - testTelemetry(t, exporterID, func(t *testing.T, tt obsreporttest.TestTelemetry, useOtel bool) { - parentCtx, parentSpan := tt.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) + testTelemetry(t, exporterID, func(t *testing.T, tt componenttest.TestTelemetry) { + parentCtx, parentSpan := tt.TelemetrySettings().TracerProvider.Tracer("test").Start(context.Background(), t.Name()) defer parentSpan.End() obsrep, err := newExporter(ObsReportSettings{ ExporterID: exporterID, - ExporterCreateSettings: exportertest.NewCreateSettings(exporterID, tt.TelemetrySettings), - }, useOtel) + ExporterCreateSettings: exporter.CreateSettings{ID: exporterID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) require.NoError(t, err) params := []testParams{ @@ -74,14 +74,14 @@ func TestExportTraceDataOp(t *testing.T) { } func TestExportMetricsOp(t *testing.T) { - testTelemetry(t, exporterID, func(t *testing.T, tt obsreporttest.TestTelemetry, useOtel bool) { - parentCtx, parentSpan := tt.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) + testTelemetry(t, exporterID, func(t *testing.T, tt componenttest.TestTelemetry) { + parentCtx, parentSpan := tt.TelemetrySettings().TracerProvider.Tracer("test").Start(context.Background(), t.Name()) defer parentSpan.End() obsrep, err := newExporter(ObsReportSettings{ ExporterID: exporterID, - ExporterCreateSettings: exportertest.NewCreateSettings(exporterID, tt.TelemetrySettings), - }, useOtel) + ExporterCreateSettings: exporter.CreateSettings{ID: exporterID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) require.NoError(t, err) params := []testParams{ @@ -123,14 +123,14 @@ func TestExportMetricsOp(t *testing.T) { } func TestExportLogsOp(t *testing.T) { - testTelemetry(t, exporterID, func(t *testing.T, tt obsreporttest.TestTelemetry, useOtel bool) { - parentCtx, parentSpan := tt.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) + testTelemetry(t, exporterID, func(t *testing.T, tt componenttest.TestTelemetry) { + parentCtx, parentSpan := tt.TelemetrySettings().TracerProvider.Tracer("test").Start(context.Background(), t.Name()) defer parentSpan.End() obsrep, err := newExporter(ObsReportSettings{ ExporterID: exporterID, - ExporterCreateSettings: exportertest.NewCreateSettings(exporterID, tt.TelemetrySettings), - }, useOtel) + ExporterCreateSettings: exporter.CreateSettings{ID: exporterID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) require.NoError(t, err) params := []testParams{ @@ -171,25 +171,77 @@ func TestExportLogsOp(t *testing.T) { }) } -type testParams struct { - items int - err error +func TestCheckExporterTracesViews(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{ + ExporterID: exporterID, + ExporterCreateSettings: exporter.CreateSettings{ID: exporterID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) + require.NoError(t, err) + ctx := obsrep.StartTracesOp(context.Background()) + require.NotNil(t, ctx) + obsrep.EndTracesOp(ctx, 7, nil) + + assert.NoError(t, tt.CheckExporterTraces(7, 0)) + assert.Error(t, tt.CheckExporterTraces(7, 7)) + assert.Error(t, tt.CheckExporterTraces(0, 0)) + assert.Error(t, tt.CheckExporterTraces(0, 7)) } -func testTelemetry(t *testing.T, id component.ID, testFunc func(t *testing.T, tt obsreporttest.TestTelemetry, useOtel bool)) { - t.Run("WithOC", func(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(id) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) +func TestCheckExporterMetricsViews(t *testing.T) { + tt, err := componenttest.SetupTelemetry(exporterID) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - testFunc(t, tt, false) + obsrep, err := NewObsReport(ObsReportSettings{ + ExporterID: exporterID, + ExporterCreateSettings: exporter.CreateSettings{ID: exporterID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, }) + require.NoError(t, err) + ctx := obsrep.StartMetricsOp(context.Background()) + require.NotNil(t, ctx) + obsrep.EndMetricsOp(ctx, 7, nil) + + assert.NoError(t, tt.CheckExporterMetrics(7, 0)) + assert.Error(t, tt.CheckExporterMetrics(7, 7)) + assert.Error(t, tt.CheckExporterMetrics(0, 0)) + assert.Error(t, tt.CheckExporterMetrics(0, 7)) +} + +func TestCheckExporterLogsViews(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{ + ExporterID: exporterID, + ExporterCreateSettings: exporter.CreateSettings{ID: exporterID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) + require.NoError(t, err) + ctx := obsrep.StartLogsOp(context.Background()) + require.NotNil(t, ctx) + obsrep.EndLogsOp(ctx, 7, nil) + + assert.NoError(t, tt.CheckExporterLogs(7, 0)) + assert.Error(t, tt.CheckExporterLogs(7, 7)) + assert.Error(t, tt.CheckExporterLogs(0, 0)) + assert.Error(t, tt.CheckExporterLogs(0, 7)) +} + +type testParams struct { + items int + err error +} +func testTelemetry(t *testing.T, id component.ID, testFunc func(t *testing.T, tt componenttest.TestTelemetry)) { t.Run("WithOTel", func(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(id) + tt, err := componenttest.SetupTelemetry(id) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - testFunc(t, tt, true) + testFunc(t, tt) }) } diff --git a/exporter/exporterhelper/obsreport.go b/exporter/exporterhelper/obsreport.go deleted file mode 100644 index d0e0ae11bf3..00000000000 --- a/exporter/exporterhelper/obsreport.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package exporterhelper // import "go.opentelemetry.io/collector/exporter/exporterhelper" - -import ( - "context" - - "go.opencensus.io/metric" - "go.opencensus.io/metric/metricdata" - "go.opencensus.io/metric/metricproducer" - - "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" -) - -// TODO: Incorporate this functionality along with tests from obsreport_test.go -// into existing `obsreport` package once its functionally is not exposed -// as public API. For now this part is kept private. - -var ( - globalInstruments = newInstruments(metric.NewRegistry()) -) - -func init() { - metricproducer.GlobalManager().AddProducer(globalInstruments.registry) -} - -type instruments struct { - registry *metric.Registry - queueSize *metric.Int64DerivedGauge - queueCapacity *metric.Int64DerivedGauge - failedToEnqueueTraceSpans *metric.Int64Cumulative - failedToEnqueueMetricPoints *metric.Int64Cumulative - failedToEnqueueLogRecords *metric.Int64Cumulative -} - -func newInstruments(registry *metric.Registry) *instruments { - insts := &instruments{ - registry: registry, - } - insts.queueSize, _ = registry.AddInt64DerivedGauge( - obsmetrics.ExporterKey+"/queue_size", - metric.WithDescription("Current size of the retry queue (in batches)"), - metric.WithLabelKeys(obsmetrics.ExporterKey), - metric.WithUnit(metricdata.UnitDimensionless)) - - insts.queueCapacity, _ = registry.AddInt64DerivedGauge( - obsmetrics.ExporterKey+"/queue_capacity", - metric.WithDescription("Fixed capacity of the retry queue (in batches)"), - metric.WithLabelKeys(obsmetrics.ExporterKey), - metric.WithUnit(metricdata.UnitDimensionless)) - - insts.failedToEnqueueTraceSpans, _ = registry.AddInt64Cumulative( - obsmetrics.ExporterKey+"/enqueue_failed_spans", - metric.WithDescription("Number of spans failed to be added to the sending queue."), - metric.WithLabelKeys(obsmetrics.ExporterKey), - metric.WithUnit(metricdata.UnitDimensionless)) - - insts.failedToEnqueueMetricPoints, _ = registry.AddInt64Cumulative( - obsmetrics.ExporterKey+"/enqueue_failed_metric_points", - metric.WithDescription("Number of metric points failed to be added to the sending queue."), - metric.WithLabelKeys(obsmetrics.ExporterKey), - metric.WithUnit(metricdata.UnitDimensionless)) - - insts.failedToEnqueueLogRecords, _ = registry.AddInt64Cumulative( - obsmetrics.ExporterKey+"/enqueue_failed_log_records", - metric.WithDescription("Number of log records failed to be added to the sending queue."), - metric.WithLabelKeys(obsmetrics.ExporterKey), - metric.WithUnit(metricdata.UnitDimensionless)) - - return insts -} - -// obsExporter is a helper to add observability to an exporter. -type obsExporter struct { - *ObsReport - failedToEnqueueTraceSpansEntry *metric.Int64CumulativeEntry - failedToEnqueueMetricPointsEntry *metric.Int64CumulativeEntry - failedToEnqueueLogRecordsEntry *metric.Int64CumulativeEntry -} - -// newObsExporter creates a new observability exporter. -func newObsExporter(cfg ObsReportSettings, insts *instruments) (*obsExporter, error) { - labelValue := metricdata.NewLabelValue(cfg.ExporterID.String()) - failedToEnqueueTraceSpansEntry, _ := insts.failedToEnqueueTraceSpans.GetEntry(labelValue) - failedToEnqueueMetricPointsEntry, _ := insts.failedToEnqueueMetricPoints.GetEntry(labelValue) - failedToEnqueueLogRecordsEntry, _ := insts.failedToEnqueueLogRecords.GetEntry(labelValue) - - exp, err := NewObsReport(cfg) - if err != nil { - return nil, err - } - - return &obsExporter{ - ObsReport: exp, - failedToEnqueueTraceSpansEntry: failedToEnqueueTraceSpansEntry, - failedToEnqueueMetricPointsEntry: failedToEnqueueMetricPointsEntry, - failedToEnqueueLogRecordsEntry: failedToEnqueueLogRecordsEntry, - }, nil -} - -// recordTracesEnqueueFailure records number of spans that failed to be added to the sending queue. -func (eor *obsExporter) recordTracesEnqueueFailure(_ context.Context, numSpans int64) { - eor.failedToEnqueueTraceSpansEntry.Inc(numSpans) -} - -// recordMetricsEnqueueFailure records number of metric points that failed to be added to the sending queue. -func (eor *obsExporter) recordMetricsEnqueueFailure(_ context.Context, numMetricPoints int64) { - eor.failedToEnqueueMetricPointsEntry.Inc(numMetricPoints) -} - -// recordLogsEnqueueFailure records number of log records that failed to be added to the sending queue. -func (eor *obsExporter) recordLogsEnqueueFailure(_ context.Context, numLogRecords int64) { - eor.failedToEnqueueLogRecordsEntry.Inc(numLogRecords) -} diff --git a/exporter/exporterhelper/obsreport_test.go b/exporter/exporterhelper/obsreport_test.go index af2616eb7ee..e0101f112df 100644 --- a/exporter/exporterhelper/obsreport_test.go +++ b/exporter/exporterhelper/obsreport_test.go @@ -8,61 +8,33 @@ import ( "testing" "github.com/stretchr/testify/require" - "go.opencensus.io/metric" - "go.opencensus.io/tag" "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/exporter/exportertest" - "go.opentelemetry.io/collector/obsreport/obsreporttest" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/exporter" ) func TestExportEnqueueFailure(t *testing.T) { - exporter := component.NewID("fakeExporter") - tt, err := obsreporttest.SetupTelemetry(exporter) + exporterID := component.MustNewID("fakeExporter") + tt, err := componenttest.SetupTelemetry(exporterID) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - insts := newInstruments(metric.NewRegistry()) - obsrep, err := newObsExporter(ObsReportSettings{ - ExporterID: exporter, - ExporterCreateSettings: exportertest.NewCreateSettings(exporter, tt.TelemetrySettings), - }, insts) + obsrep, err := NewObsReport(ObsReportSettings{ + ExporterID: exporterID, + ExporterCreateSettings: exporter.CreateSettings{ID: exporterID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) require.NoError(t, err) logRecords := int64(7) - obsrep.recordLogsEnqueueFailure(context.Background(), logRecords) - checkExporterEnqueueFailedLogsStats(t, insts, exporter, logRecords) + obsrep.recordEnqueueFailure(context.Background(), component.DataTypeLogs, logRecords) + require.NoError(t, tt.CheckExporterEnqueueFailedLogs(logRecords)) spans := int64(12) - obsrep.recordTracesEnqueueFailure(context.Background(), spans) - checkExporterEnqueueFailedTracesStats(t, insts, exporter, spans) + obsrep.recordEnqueueFailure(context.Background(), component.DataTypeTraces, spans) + require.NoError(t, tt.CheckExporterEnqueueFailedTraces(spans)) metricPoints := int64(21) - obsrep.recordMetricsEnqueueFailure(context.Background(), metricPoints) - checkExporterEnqueueFailedMetricsStats(t, insts, exporter, metricPoints) -} - -// checkExporterEnqueueFailedTracesStats checks that reported number of spans failed to enqueue match given values. -// When this function is called it is required to also call SetupTelemetry as first thing. -func checkExporterEnqueueFailedTracesStats(t *testing.T, insts *instruments, exporter component.ID, spans int64) { - checkValueForProducer(t, insts.registry, tagsForExporterView(exporter), spans, "exporter/enqueue_failed_spans") -} - -// checkExporterEnqueueFailedMetricsStats checks that reported number of metric points failed to enqueue match given values. -// When this function is called it is required to also call SetupTelemetry as first thing. -func checkExporterEnqueueFailedMetricsStats(t *testing.T, insts *instruments, exporter component.ID, metricPoints int64) { - checkValueForProducer(t, insts.registry, tagsForExporterView(exporter), metricPoints, "exporter/enqueue_failed_metric_points") -} - -// checkExporterEnqueueFailedLogsStats checks that reported number of log records failed to enqueue match given values. -// When this function is called it is required to also call SetupTelemetry as first thing. -func checkExporterEnqueueFailedLogsStats(t *testing.T, insts *instruments, exporter component.ID, logRecords int64) { - checkValueForProducer(t, insts.registry, tagsForExporterView(exporter), logRecords, "exporter/enqueue_failed_log_records") -} - -// tagsForExporterView returns the tags that are needed for the exporter views. -func tagsForExporterView(exporter component.ID) []tag.Tag { - return []tag.Tag{ - {Key: exporterTag, Value: exporter.String()}, - } + obsrep.recordEnqueueFailure(context.Background(), component.DataTypeMetrics, metricPoints) + require.NoError(t, tt.CheckExporterEnqueueFailedMetrics(metricPoints)) } diff --git a/exporter/exporterhelper/package_test.go b/exporter/exporterhelper/package_test.go new file mode 100644 index 00000000000..6cf68017a7d --- /dev/null +++ b/exporter/exporterhelper/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterhelper + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/exporter/exporterhelper/queue_sender.go b/exporter/exporterhelper/queue_sender.go index d3da29500fe..3092c60c98f 100644 --- a/exporter/exporterhelper/queue_sender.go +++ b/exporter/exporterhelper/queue_sender.go @@ -6,23 +6,26 @@ package exporterhelper // import "go.opentelemetry.io/collector/exporter/exporte import ( "context" "errors" - "fmt" "time" - "go.opencensus.io/metric/metricdata" "go.opentelemetry.io/otel/attribute" + otelmetric "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/trace" + "go.uber.org/multierr" "go.uber.org/zap" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/exporter" - "go.opentelemetry.io/collector/exporter/exporterhelper/internal" + "go.opentelemetry.io/collector/exporter/exporterqueue" + "go.opentelemetry.io/collector/exporter/internal/queue" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" ) const defaultQueueSize = 1000 -var errSendingQueueIsFull = errors.New("sending_queue is full") +var ( + scopeName = "go.opentelemetry.io/collector/exporterhelper" +) // QueueSettings defines configuration for queueing batches before sending to the consumerSender. type QueueSettings struct { @@ -59,132 +62,98 @@ func (qCfg *QueueSettings) Validate() error { return errors.New("queue size must be positive") } + if qCfg.NumConsumers <= 0 { + return errors.New("number of queue consumers must be positive") + } + return nil } type queueSender struct { baseRequestSender - fullName string - id component.ID - signal component.DataType - queue internal.ProducerConsumerQueue - traceAttribute attribute.KeyValue - logger *zap.Logger - requeuingEnabled bool + fullName string + queue exporterqueue.Queue[Request] + traceAttribute attribute.KeyValue + logger *zap.Logger + meter otelmetric.Meter + consumers *queue.Consumers[Request] + + metricCapacity otelmetric.Int64ObservableGauge + metricSize otelmetric.Int64ObservableGauge } -func newQueueSender(id component.ID, signal component.DataType, queue internal.ProducerConsumerQueue, logger *zap.Logger) *queueSender { - return &queueSender{ - fullName: id.String(), - id: id, - signal: signal, - queue: queue, - traceAttribute: attribute.String(obsmetrics.ExporterKey, id.String()), - logger: logger, - // TODO: this can be further exposed as a config param rather than relying on a type of queue - requeuingEnabled: queue != nil && queue.IsPersistent(), +func newQueueSender(q exporterqueue.Queue[Request], set exporter.CreateSettings, numConsumers int, + exportFailureMessage string) *queueSender { + qs := &queueSender{ + fullName: set.ID.String(), + queue: q, + traceAttribute: attribute.String(obsmetrics.ExporterKey, set.ID.String()), + logger: set.TelemetrySettings.Logger, + meter: set.TelemetrySettings.MeterProvider.Meter(scopeName), } -} - -func (qs *queueSender) onTemporaryFailure(logger *zap.Logger, req internal.Request, err error) error { - if !qs.requeuingEnabled || qs.queue == nil { - logger.Error( - "Exporting failed. No more retries left. Dropping data.", - zap.Error(err), - zap.Int("dropped_items", req.Count()), - ) + consumeFunc := func(ctx context.Context, req Request) error { + err := qs.nextSender.send(ctx, req) + if err != nil { + set.Logger.Error("Exporting failed. Dropping data."+exportFailureMessage, + zap.Error(err), zap.Int("dropped_items", req.ItemsCount())) + } return err } - - if qs.queue.Produce(req) { - logger.Error( - "Exporting failed. Putting back to the end of the queue.", - zap.Error(err), - ) - } else { - logger.Error( - "Exporting failed. Queue did not accept requeuing request. Dropping data.", - zap.Error(err), - zap.Int("dropped_items", req.Count()), - ) - } - return err + qs.consumers = queue.NewQueueConsumers[Request](q, numConsumers, consumeFunc) + return qs } -// start is invoked during service startup. -func (qs *queueSender) start(ctx context.Context, host component.Host, set exporter.CreateSettings) error { - if qs.queue == nil { - return nil - } - - err := qs.queue.Start(ctx, host, internal.QueueSettings{ - CreateSettings: set, - DataType: qs.signal, - Callback: func(item internal.Request) { - _ = qs.nextSender.send(item) - item.OnProcessingFinished() - }, - }) - if err != nil { +// Start is invoked during service startup. +func (qs *queueSender) Start(ctx context.Context, host component.Host) error { + if err := qs.consumers.Start(ctx, host); err != nil { return err } - // Start reporting queue length metric - err = globalInstruments.queueSize.UpsertEntry(func() int64 { - return int64(qs.queue.Size()) - }, metricdata.NewLabelValue(qs.fullName)) - if err != nil { - return fmt.Errorf("failed to create retry queue size metric: %w", err) - } - err = globalInstruments.queueCapacity.UpsertEntry(func() int64 { - return int64(qs.queue.Capacity()) - }, metricdata.NewLabelValue(qs.fullName)) - if err != nil { - return fmt.Errorf("failed to create retry queue capacity metric: %w", err) - } - - return nil + var err, errs error + + attrs := otelmetric.WithAttributeSet(attribute.NewSet(attribute.String(obsmetrics.ExporterKey, qs.fullName))) + + qs.metricSize, err = qs.meter.Int64ObservableGauge( + obsmetrics.ExporterKey+"/queue_size", + otelmetric.WithDescription("Current size of the retry queue (in batches)"), + otelmetric.WithUnit("1"), + otelmetric.WithInt64Callback(func(_ context.Context, o otelmetric.Int64Observer) error { + o.Observe(int64(qs.queue.Size()), attrs) + return nil + }), + ) + errs = multierr.Append(errs, err) + + qs.metricCapacity, err = qs.meter.Int64ObservableGauge( + obsmetrics.ExporterKey+"/queue_capacity", + otelmetric.WithDescription("Fixed capacity of the retry queue (in batches)"), + otelmetric.WithUnit("1"), + otelmetric.WithInt64Callback(func(_ context.Context, o otelmetric.Int64Observer) error { + o.Observe(int64(qs.queue.Capacity()), attrs) + return nil + })) + + errs = multierr.Append(errs, err) + return errs } -// shutdown is invoked during service shutdown. -func (qs *queueSender) shutdown() { - if qs.queue != nil { - // Cleanup queue metrics reporting - _ = globalInstruments.queueSize.UpsertEntry(func() int64 { - return int64(0) - }, metricdata.NewLabelValue(qs.fullName)) - - // Stop the queued sender, this will drain the queue and will call the retry (which is stopped) that will only - // try once every request. - qs.queue.Stop() - } +// 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 + // try once every request. + return qs.consumers.Shutdown(ctx) } -// send implements the requestSender interface -func (qs *queueSender) send(req internal.Request) error { - if qs.queue == nil { - err := qs.nextSender.send(req) - if err != nil { - qs.logger.Error( - "Exporting failed. Dropping data. Try enabling sending_queue to survive temporary failures.", - zap.Int("dropped_items", req.Count()), - ) - } - return err - } - +// send implements the requestSender interface. It puts the request in the queue. +func (qs *queueSender) send(ctx context.Context, req 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. - req.SetContext(noCancellationContext{Context: req.Context()}) - - span := trace.SpanFromContext(req.Context()) - if !qs.queue.Produce(req) { - qs.logger.Error( - "Dropping data because sending_queue is full. Try increasing queue_size.", - zap.Int("dropped_items", req.Count()), - ) - span.AddEvent("Dropped item, sending_queue is full.", trace.WithAttributes(qs.traceAttribute)) - return errSendingQueueIsFull + c := noCancellationContext{Context: ctx} + + span := trace.SpanFromContext(c) + if err := qs.queue.Offer(c, req); err != nil { + span.AddEvent("Failed to enqueue item.", trace.WithAttributes(qs.traceAttribute)) + return err } span.AddEvent("Enqueued item.", trace.WithAttributes(qs.traceAttribute)) diff --git a/exporter/exporterhelper/queue_sender_test.go b/exporter/exporterhelper/queue_sender_test.go index 2cc21f62380..a2616152ea6 100644 --- a/exporter/exporterhelper/queue_sender_test.go +++ b/exporter/exporterhelper/queue_sender_test.go @@ -6,42 +6,45 @@ package exporterhelper import ( "context" "errors" - "sync/atomic" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "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/consumer/consumererror" - "go.opentelemetry.io/collector/exporter/exporterhelper/internal" + "go.opentelemetry.io/collector/config/configretry" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exporterqueue" "go.opentelemetry.io/collector/exporter/exportertest" - "go.opentelemetry.io/collector/internal/testdata" - "go.opentelemetry.io/collector/obsreport/obsreporttest" + "go.opentelemetry.io/collector/exporter/internal/queue" ) func TestQueuedRetry_StopWhileWaiting(t *testing.T) { qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 1 - rCfg := NewDefaultRetrySettings() - be, err := newBaseExporter(defaultSettings, "", false, nil, nil, newObservabilityConsumerSender, WithRetry(rCfg), WithQueue(qCfg)) + rCfg := configretry.NewDefaultBackOffConfig() + be, err := newBaseExporter(defaultSettings, defaultType, 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())) - firstMockR := newErrorRequest(context.Background()) + firstMockR := newErrorRequest() ocs.run(func() { // This is asynchronous so it should just enqueue, no errors expected. - require.NoError(t, be.send(firstMockR)) + require.NoError(t, be.send(context.Background(), firstMockR)) }) // Enqueue another request to ensure when calling shutdown we drain the queue. - secondMockR := newMockRequest(context.Background(), 3, nil) + secondMockR := newMockRequest(3, nil) ocs.run(func() { // This is asynchronous so it should just enqueue, no errors expected. - require.NoError(t, be.send(secondMockR)) + require.NoError(t, be.send(context.Background(), secondMockR)) }) require.LessOrEqual(t, 1, be.queueSender.(*queueSender).queue.Size()) @@ -57,8 +60,10 @@ func TestQueuedRetry_StopWhileWaiting(t *testing.T) { func TestQueuedRetry_DoNotPreserveCancellation(t *testing.T) { qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 1 - rCfg := NewDefaultRetrySettings() - be, err := newBaseExporter(defaultSettings, "", false, nil, nil, newObservabilityConsumerSender, WithRetry(rCfg), WithQueue(qCfg)) + rCfg := configretry.NewDefaultBackOffConfig() + be, err := newBaseExporter(defaultSettings, defaultType, 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())) @@ -68,10 +73,10 @@ func TestQueuedRetry_DoNotPreserveCancellation(t *testing.T) { ctx, cancelFunc := context.WithCancel(context.Background()) cancelFunc() - mockR := newMockRequest(ctx, 2, nil) + mockR := newMockRequest(2, nil) ocs.run(func() { // This is asynchronous so it should just enqueue, no errors expected. - require.NoError(t, be.send(mockR)) + require.NoError(t, be.send(ctx, mockR)) }) ocs.awaitAsyncProcessing() @@ -81,72 +86,143 @@ func TestQueuedRetry_DoNotPreserveCancellation(t *testing.T) { require.Zero(t, be.queueSender.(*queueSender).queue.Size()) } -func TestQueuedRetry_DropOnFull(t *testing.T) { +func TestQueuedRetry_RejectOnFull(t *testing.T) { qCfg := NewDefaultQueueSettings() qCfg.QueueSize = 0 - be, err := newBaseExporter(defaultSettings, "", false, nil, nil, newObservabilityConsumerSender, WithQueue(qCfg)) + qCfg.NumConsumers = 0 + set := exportertest.NewNopCreateSettings() + logger, observed := observer.New(zap.ErrorLevel) + set.Logger = zap.New(logger) + be, err := newBaseExporter(set, defaultType, newNoopObsrepSender, + withMarshaler(mockRequestMarshaler), withUnmarshaler(mockRequestUnmarshaler(&mockRequest{})), + 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())) }) - require.Error(t, be.send(newMockRequest(context.Background(), 2, nil))) + require.Error(t, be.send(context.Background(), newMockRequest(2, nil))) + assert.Len(t, observed.All(), 1) + assert.Equal(t, "Exporting failed. Rejecting data.", observed.All()[0].Message) + assert.Equal(t, "sending queue is full", observed.All()[0].ContextMap()["error"]) } func TestQueuedRetryHappyPath(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(defaultID) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - qCfg := NewDefaultQueueSettings() - rCfg := NewDefaultRetrySettings() - set := exportertest.NewCreateSettings(defaultID, tt.TelemetrySettings) - be, err := newBaseExporter(set, "", false, nil, nil, newObservabilityConsumerSender, 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())) - }) - - wantRequests := 10 - reqs := make([]*mockRequest, 0, 10) - for i := 0; i < wantRequests; i++ { - ocs.run(func() { - req := newMockRequest(context.Background(), 2, nil) - reqs = append(reqs, req) - require.NoError(t, be.send(req)) - }) + tests := []struct { + name string + queueOptions []Option + }{ + { + name: "WithQueue", + queueOptions: []Option{ + withMarshaler(mockRequestMarshaler), + withUnmarshaler(mockRequestUnmarshaler(&mockRequest{})), + WithQueue(QueueSettings{ + Enabled: true, + QueueSize: 10, + NumConsumers: 1, + }), + WithRetry(configretry.NewDefaultBackOffConfig()), + }, + }, + { + name: "WithRequestQueue/MemoryQueueFactory", + queueOptions: []Option{ + WithRequestQueue(exporterqueue.Config{ + Enabled: true, + QueueSize: 10, + NumConsumers: 1, + }, exporterqueue.NewMemoryQueueFactory[Request]()), + WithRetry(configretry.NewDefaultBackOffConfig()), + }, + }, + { + name: "WithRequestQueue/PersistentQueueFactory", + queueOptions: []Option{ + WithRequestQueue(exporterqueue.Config{ + Enabled: true, + QueueSize: 10, + NumConsumers: 1, + }, exporterqueue.NewPersistentQueueFactory[Request](nil, exporterqueue.PersistentQueueSettings[Request]{})), + WithRetry(configretry.NewDefaultBackOffConfig()), + }, + }, + { + name: "WithRequestQueue/PersistentQueueFactory/RequestsLimit", + queueOptions: []Option{ + WithRequestQueue(exporterqueue.Config{ + Enabled: true, + QueueSize: 10, + NumConsumers: 1, + }, exporterqueue.NewPersistentQueueFactory[Request](nil, exporterqueue.PersistentQueueSettings[Request]{})), + WithRetry(configretry.NewDefaultBackOffConfig()), + }, + }, } - - // Wait until all batches received - ocs.awaitAsyncProcessing() - - require.Len(t, reqs, wantRequests) - for _, req := range reqs { - req.checkNumRequests(t, 1) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tel, err := componenttest.SetupTelemetry(defaultID) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tel.Shutdown(context.Background())) }) + + set := exporter.CreateSettings{ID: defaultID, TelemetrySettings: tel.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()} + be, err := newBaseExporter(set, defaultType, newObservabilityConsumerSender, tt.queueOptions...) + require.NoError(t, err) + ocs := be.obsrepSender.(*observabilityConsumerSender) + + wantRequests := 10 + reqs := make([]*mockRequest, 0, 10) + for i := 0; i < wantRequests; i++ { + ocs.run(func() { + req := newMockRequest(2, nil) + reqs = append(reqs, req) + require.NoError(t, be.send(context.Background(), req)) + }) + } + + // expect queue to be full + require.Error(t, be.send(context.Background(), newMockRequest(2, nil))) + + require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) + t.Cleanup(func() { + assert.NoError(t, be.Shutdown(context.Background())) + }) + + // Wait until all batches received + ocs.awaitAsyncProcessing() + + require.Len(t, reqs, wantRequests) + for _, req := range reqs { + req.checkNumRequests(t, 1) + } + + ocs.checkSendItemsCount(t, 2*wantRequests) + ocs.checkDroppedItemsCount(t, 0) + }) } - - ocs.checkSendItemsCount(t, 2*wantRequests) - ocs.checkDroppedItemsCount(t, 0) } - func TestQueuedRetry_QueueMetricsReported(t *testing.T) { + tt, err := componenttest.SetupTelemetry(defaultID) + require.NoError(t, err) + qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 0 // to make every request go straight to the queue - rCfg := NewDefaultRetrySettings() - be, err := newBaseExporter(defaultSettings, "", false, nil, nil, newObservabilityConsumerSender, WithRetry(rCfg), WithQueue(qCfg)) + rCfg := configretry.NewDefaultBackOffConfig() + set := exporter.CreateSettings{ID: defaultID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()} + be, err := newBaseExporter(set, defaultType, newObservabilityConsumerSender, + withMarshaler(mockRequestMarshaler), withUnmarshaler(mockRequestUnmarshaler(&mockRequest{})), + WithRetry(rCfg), WithQueue(qCfg)) require.NoError(t, err) require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - checkValueForGlobalManager(t, defaultExporterTags, int64(defaultQueueSize), "exporter/queue_capacity") + require.NoError(t, tt.CheckExporterMetricGauge("exporter_queue_capacity", int64(defaultQueueSize))) + for i := 0; i < 7; i++ { - require.NoError(t, be.send(newErrorRequest(context.Background()))) + require.NoError(t, be.send(context.Background(), newErrorRequest())) } - checkValueForGlobalManager(t, defaultExporterTags, int64(7), "exporter/queue_size") + require.NoError(t, tt.CheckExporterMetricGauge("exporter_queue_size", int64(7))) assert.NoError(t, be.Shutdown(context.Background())) - checkValueForGlobalManager(t, defaultExporterTags, int64(0), "exporter/queue_size") } func TestNoCancellationContext(t *testing.T) { @@ -172,98 +248,103 @@ func TestQueueSettings_Validate(t *testing.T) { qCfg.QueueSize = 0 assert.EqualError(t, qCfg.Validate(), "queue size must be positive") + qCfg = NewDefaultQueueSettings() + qCfg.NumConsumers = 0 + + assert.EqualError(t, qCfg.Validate(), "number of queue consumers must be positive") + // Confirm Validate doesn't return error with invalid config when feature is disabled qCfg.Enabled = false assert.NoError(t, qCfg.Validate()) } -// if requeueing is enabled, we eventually retry even if we failed at first -func TestQueuedRetry_RequeuingEnabled(t *testing.T) { - qCfg := NewDefaultQueueSettings() - qCfg.NumConsumers = 1 - rCfg := NewDefaultRetrySettings() - rCfg.MaxElapsedTime = time.Nanosecond // we don't want to retry at all, but requeue instead - be, err := newBaseExporter(defaultSettings, "", false, nil, nil, newObservabilityConsumerSender, WithRetry(rCfg), WithQueue(qCfg)) - require.NoError(t, err) - ocs := be.obsrepSender.(*observabilityConsumerSender) - be.queueSender.(*queueSender).requeuingEnabled = true - require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - t.Cleanup(func() { - assert.NoError(t, be.Shutdown(context.Background())) - }) - - traceErr := consumererror.NewTraces(errors.New("some error"), testdata.GenerateTraces(1)) - mockR := newMockRequest(context.Background(), 1, traceErr) - ocs.run(func() { - // This is asynchronous so it should just enqueue, no errors expected. - require.NoError(t, be.send(mockR)) - ocs.waitGroup.Add(1) // necessary because we'll call send() again after requeueing - }) - ocs.awaitAsyncProcessing() - - // In the newMockConcurrentExporter we count requests and items even for failed requests - mockR.checkNumRequests(t, 2) - ocs.checkSendItemsCount(t, 1) - ocs.checkDroppedItemsCount(t, 1) // not actually dropped, but ocs counts each failed send here -} - -// if requeueing is enabled, but the queue is full, we get an error -func TestQueuedRetry_RequeuingEnabledQueueFull(t *testing.T) { - qCfg := NewDefaultQueueSettings() - qCfg.NumConsumers = 0 - qCfg.QueueSize = 0 - rCfg := NewDefaultRetrySettings() - rCfg.MaxElapsedTime = time.Nanosecond // we don't want to retry at all, but requeue instead - be, err := newBaseExporter(defaultSettings, "", false, nil, nil, newObservabilityConsumerSender, WithRetry(rCfg), WithQueue(qCfg)) - require.NoError(t, err) - be.queueSender.(*queueSender).requeuingEnabled = true - require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - t.Cleanup(func() { - assert.NoError(t, be.Shutdown(context.Background())) - }) +func TestQueueRetryWithDisabledQueue(t *testing.T) { + tests := []struct { + name string + queueOptions []Option + }{ + { + name: "WithQueue", + queueOptions: []Option{ + withMarshaler(mockRequestMarshaler), + withUnmarshaler(mockRequestUnmarshaler(&mockRequest{})), + func() Option { + qs := NewDefaultQueueSettings() + qs.Enabled = false + return WithQueue(qs) + }(), + }, + }, + { + name: "WithRequestQueue", + queueOptions: []Option{ + func() Option { + qs := exporterqueue.NewDefaultConfig() + qs.Enabled = false + return WithRequestQueue(qs, exporterqueue.NewMemoryQueueFactory[Request]()) + }(), + }, + }, + } - traceErr := consumererror.NewTraces(errors.New("some error"), testdata.GenerateTraces(1)) - mockR := newMockRequest(context.Background(), 1, traceErr) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + set := exportertest.NewNopCreateSettings() + logger, observed := observer.New(zap.ErrorLevel) + set.Logger = zap.New(logger) + be, err := newBaseExporter(set, component.DataTypeLogs, newObservabilityConsumerSender, tt.queueOptions...) + 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 sending_queue to survive temporary failures.", 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())) + }) + } - require.Error(t, be.retrySender.send(mockR), "sending_queue is full") - mockR.checkNumRequests(t, 1) } -func TestQueueRetryWithDisabledQueue(t *testing.T) { - qs := NewDefaultQueueSettings() - qs.Enabled = false - be, err := newBaseExporter(exportertest.NewNopCreateSettings(), component.DataTypeLogs, false, nil, nil, newObservabilityConsumerSender, WithQueue(qs)) - require.Nil(t, be.queueSender.(*queueSender).queue) +func TestQueueFailedRequestDropped(t *testing.T) { + set := exportertest.NewNopCreateSettings() + logger, observed := observer.New(zap.ErrorLevel) + set.Logger = zap.New(logger) + be, err := newBaseExporter(set, component.DataTypeLogs, newNoopObsrepSender, + WithRequestQueue(exporterqueue.NewDefaultConfig(), exporterqueue.NewMemoryQueueFactory[Request]())) require.NoError(t, err) require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) - ocs := be.obsrepSender.(*observabilityConsumerSender) - mockR := newMockRequest(context.Background(), 2, errors.New("some error")) - ocs.run(func() { - // This is asynchronous so it should just enqueue, no errors expected. - require.Error(t, be.send(mockR)) - }) - ocs.awaitAsyncProcessing() - mockR.checkNumRequests(t, 1) - ocs.checkSendItemsCount(t, 0) - ocs.checkDroppedItemsCount(t, 2) + 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) + assert.Len(t, observed.All(), 1) + assert.Equal(t, "Exporting failed. Dropping data.", observed.All()[0].Message) } func TestQueuedRetryPersistenceEnabled(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(defaultID) + tt, err := componenttest.SetupTelemetry(defaultID) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) qCfg := NewDefaultQueueSettings() - storageID := component.NewIDWithName("file_storage", "storage") + storageID := component.MustNewIDWithName("file_storage", "storage") qCfg.StorageID = &storageID // enable persistence - rCfg := NewDefaultRetrySettings() - set := exportertest.NewCreateSettings(defaultID, tt.TelemetrySettings) - be, err := newBaseExporter(set, "", false, nil, nil, newObservabilityConsumerSender, WithRetry(rCfg), WithQueue(qCfg)) + rCfg := configretry.NewDefaultBackOffConfig() + set := exporter.CreateSettings{ID: defaultID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()} + be, err := newBaseExporter(set, defaultType, newObservabilityConsumerSender, + withMarshaler(mockRequestMarshaler), withUnmarshaler(mockRequestUnmarshaler(&mockRequest{})), + WithRetry(rCfg), WithQueue(qCfg)) require.NoError(t, err) var extensions = map[component.ID]component.Component{ - storageID: internal.NewMockStorageExtension(nil), + storageID: queue.NewMockStorageExtension(nil), } host := &mockHost{ext: extensions} @@ -274,20 +355,21 @@ func TestQueuedRetryPersistenceEnabled(t *testing.T) { func TestQueuedRetryPersistenceEnabledStorageError(t *testing.T) { storageError := errors.New("could not get storage client") - tt, err := obsreporttest.SetupTelemetry(defaultID) + tt, err := componenttest.SetupTelemetry(defaultID) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) qCfg := NewDefaultQueueSettings() - storageID := component.NewIDWithName("file_storage", "storage") + storageID := component.MustNewIDWithName("file_storage", "storage") qCfg.StorageID = &storageID // enable persistence - rCfg := NewDefaultRetrySettings() - set := exportertest.NewCreateSettings(defaultID, tt.TelemetrySettings) - be, err := newBaseExporter(set, "", false, mockRequestMarshaler, mockRequestUnmarshaler(&mockRequest{}), newObservabilityConsumerSender, WithRetry(rCfg), WithQueue(qCfg)) + rCfg := configretry.NewDefaultBackOffConfig() + set := exporter.CreateSettings{ID: defaultID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()} + be, err := newBaseExporter(set, defaultType, newObservabilityConsumerSender, withMarshaler(mockRequestMarshaler), + withUnmarshaler(mockRequestUnmarshaler(&mockRequest{})), WithRetry(rCfg), WithQueue(qCfg)) require.NoError(t, err) var extensions = map[component.ID]component.Component{ - storageID: internal.NewMockStorageExtension(storageError), + storageID: queue.NewMockStorageExtension(storageError), } host := &mockHost{ext: extensions} @@ -295,48 +377,55 @@ func TestQueuedRetryPersistenceEnabledStorageError(t *testing.T) { require.Error(t, be.Start(context.Background(), host), "could not get storage client") } -func TestQueuedRetryPersistentEnabled_shutdown_dataIsRequeued(t *testing.T) { - - produceCounter := &atomic.Uint32{} - +func TestQueuedRetryPersistentEnabled_NoDataLossOnShutdown(t *testing.T) { qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 1 - rCfg := NewDefaultRetrySettings() + storageID := component.MustNewIDWithName("file_storage", "storage") + qCfg.StorageID = &storageID // enable persistence to ensure data is re-queued on shutdown + + rCfg := configretry.NewDefaultBackOffConfig() rCfg.InitialInterval = time.Millisecond rCfg.MaxElapsedTime = 0 // retry infinitely so shutdown can be triggered - req := newMockRequest(context.Background(), 3, errors.New("some error")) - - be, err := newBaseExporter(defaultSettings, "", false, nil, nil, newNoopObsrepSender, WithRetry(rCfg), WithQueue(qCfg)) + mockReq := newErrorRequest() + be, err := newBaseExporter(defaultSettings, defaultType, newNoopObsrepSender, withMarshaler(mockRequestMarshaler), + withUnmarshaler(mockRequestUnmarshaler(mockReq)), WithRetry(rCfg), WithQueue(qCfg)) require.NoError(t, err) - require.NoError(t, be.Start(context.Background(), &mockHost{})) - - // wraps original queue so we can count operations - be.queueSender.(*queueSender).queue = &producerConsumerQueueWithCounter{ - ProducerConsumerQueue: be.queueSender.(*queueSender).queue, - produceCounter: produceCounter, + var extensions = map[component.ID]component.Component{ + storageID: queue.NewMockStorageExtension(nil), } - be.queueSender.(*queueSender).requeuingEnabled = true + host := &mockHost{ext: extensions} - // replace nextSender inside retrySender to always return error so it doesn't exit send loop - be.retrySender.setNextSender(&errorRequestSender{ - errToReturn: errors.New("some error"), - }) + require.NoError(t, be.Start(context.Background(), host)) // Invoke queuedRetrySender so the producer will put the item for consumer to poll - require.NoError(t, be.send(req)) + require.NoError(t, be.send(context.Background(), mockReq)) - // first wait for the item to be produced to the queue initially + // first wait for the item to be consumed from the queue assert.Eventually(t, func() bool { - return produceCounter.Load() == uint32(1) + return be.queueSender.(*queueSender).queue.Size() == 0 }, time.Second, 1*time.Millisecond) - // shuts down and ensure the item is produced in the queue again + // shuts down the exporter, unsent data should be preserved as in-flight data in the persistent queue. require.NoError(t, be.Shutdown(context.Background())) - assert.Eventually(t, func() bool { - return produceCounter.Load() == uint32(2) - }, time.Second, 1*time.Millisecond) + + // start the exporter again replacing the preserved mockRequest in the unmarshaler with a new one that doesn't fail. + replacedReq := newMockRequest(1, nil) + be, err = newBaseExporter(defaultSettings, defaultType, newNoopObsrepSender, withMarshaler(mockRequestMarshaler), + withUnmarshaler(mockRequestUnmarshaler(replacedReq)), WithRetry(rCfg), WithQueue(qCfg)) + require.NoError(t, err) + require.NoError(t, be.Start(context.Background(), host)) + t.Cleanup(func() { require.NoError(t, be.Shutdown(context.Background())) }) + + // wait for the item to be consumed from the queue + replacedReq.checkNumRequests(t, 1) +} + +func TestQueueSenderNoStartShutdown(t *testing.T) { + queue := queue.NewBoundedMemoryQueue[Request](queue.MemoryQueueSettings[Request]{}) + qs := newQueueSender(queue, exportertest.NewNopCreateSettings(), 1, "") + assert.NoError(t, qs.Shutdown(context.Background())) } type mockHost struct { diff --git a/exporter/exporterhelper/request.go b/exporter/exporterhelper/request.go index ef05aa6395d..03276f9c19e 100644 --- a/exporter/exporterhelper/request.go +++ b/exporter/exporterhelper/request.go @@ -5,8 +5,6 @@ package exporterhelper // import "go.opentelemetry.io/collector/exporter/exporte import ( "context" - - "go.opentelemetry.io/collector/exporter/exporterhelper/internal" ) // Request represents a single request that can be sent to an external endpoint. @@ -15,47 +13,38 @@ import ( type Request interface { // Export exports the request to an external endpoint. Export(ctx context.Context) error -} - -// RequestItemsCounter is an optional interface that can be implemented by Request to provide a number of items -// in the request. This is a recommended interface to implement for exporters. It is required for batching and queueing -// based on number of items. Also, it's used for reporting number of items in collector's logs, metrics and traces. -// If not implemented, collector's logs, metrics and traces will report 0 items. -// This API is at the early stage of development and may change without backward compatibility -// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. -type RequestItemsCounter interface { // ItemsCount returns a number of basic items in the request where item is the smallest piece of data that can be // sent. For example, for OTLP exporter, this value represents the number of spans, // metric data points or log records. ItemsCount() int } -type request struct { +// RequestErrorHandler is an optional interface that can be implemented by Request to provide a way handle partial +// temporary failures. For example, if some items failed to process and can be retried, this interface allows to +// return a new Request that contains the items left to be sent. Otherwise, the original Request should be returned. +// If not implemented, the original Request will be returned assuming the error is applied to the whole Request. +// This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. +type RequestErrorHandler interface { Request - baseRequest + // OnError returns a new Request may contain the items left to be sent if some items failed to process and can be retried. + // Otherwise, it should return the original Request. + OnError(error) Request } -var _ internal.Request = (*request)(nil) +// RequestMarshaler is a function that can marshal a Request into bytes. +// Deprecated: [v0.94.0] Use exporterqueue.Marshaler[Request] instead. +type RequestMarshaler func(req Request) ([]byte, error) -func newRequest(ctx context.Context, req Request) *request { - return &request{ - Request: req, - baseRequest: baseRequest{ctx: ctx}, - } -} - -func (req *request) OnError(_ error) internal.Request { - // Potentially we could introduce a new RequestError type that would represent partially succeeded request. - // In that case we should consider returning them back to the pipeline converted back to pdata in case if - // sending queue is disabled. We leave it as a future improvement if decided that it's needed. - return req -} +// RequestUnmarshaler is a function that can unmarshal bytes into a Request. +// Deprecated: [v0.94.0] Use exporterqueue.Unmarshaler[Request] instead. +type RequestUnmarshaler func(data []byte) (Request, error) -// Count returns a number of items in the request. If the request does not implement RequestItemsCounter -// then 0 is returned. -func (req *request) Count() int { - if counter, ok := req.Request.(RequestItemsCounter); ok { - return counter.ItemsCount() +// extractPartialRequest returns a new Request that may contain the items left to be sent +// if only some items failed to process and can be retried. Otherwise, it returns the original Request. +func extractPartialRequest(req Request, err error) Request { + if errReq, ok := req.(RequestErrorHandler); ok { + return errReq.OnError(err) } - return 0 + return req } diff --git a/exporter/exporterhelper/request_test.go b/exporter/exporterhelper/request_test.go index 6dd3f67800a..18e8228f946 100644 --- a/exporter/exporterhelper/request_test.go +++ b/exporter/exporterhelper/request_test.go @@ -16,7 +16,7 @@ type fakeRequest struct { err error } -func (r fakeRequest) Export(_ context.Context) error { +func (r fakeRequest) Export(context.Context) error { return r.err } @@ -31,14 +31,14 @@ type fakeRequestConverter struct { requestError error } -func (c fakeRequestConverter) RequestFromMetrics(_ context.Context, md pmetric.Metrics) (Request, error) { - return fakeRequest{items: md.DataPointCount(), err: c.requestError}, c.metricsError +func (frc *fakeRequestConverter) requestFromMetricsFunc(_ context.Context, md pmetric.Metrics) (Request, error) { + return fakeRequest{items: md.DataPointCount(), err: frc.requestError}, frc.metricsError } -func (c fakeRequestConverter) RequestFromTraces(_ context.Context, td ptrace.Traces) (Request, error) { - return fakeRequest{items: td.SpanCount(), err: c.requestError}, c.tracesError +func (frc *fakeRequestConverter) requestFromTracesFunc(_ context.Context, md ptrace.Traces) (Request, error) { + return fakeRequest{items: md.SpanCount(), err: frc.requestError}, frc.tracesError } -func (c fakeRequestConverter) RequestFromLogs(_ context.Context, ld plog.Logs) (Request, error) { - return fakeRequest{items: ld.LogRecordCount(), err: c.requestError}, c.logsError +func (frc *fakeRequestConverter) requestFromLogsFunc(_ context.Context, md plog.Logs) (Request, error) { + return fakeRequest{items: md.LogRecordCount(), err: frc.requestError}, frc.logsError } diff --git a/exporter/exporterhelper/retry_sender.go b/exporter/exporterhelper/retry_sender.go index 14a90a9c1e6..6e8a36f9ef4 100644 --- a/exporter/exporterhelper/retry_sender.go +++ b/exporter/exporterhelper/retry_sender.go @@ -4,6 +4,7 @@ package exporterhelper // import "go.opentelemetry.io/collector/exporter/exporterhelper" import ( + "context" "errors" "fmt" "time" @@ -13,44 +14,13 @@ 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/exporterhelper/internal" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/internal/experr" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" ) -// RetrySettings defines configuration for retrying batches in case of export failure. -// The current supported strategy is exponential backoff. -type RetrySettings struct { - // Enabled indicates whether to not retry sending batches in case of export failure. - Enabled bool `mapstructure:"enabled"` - // InitialInterval the time to wait after the first failure before retrying. - InitialInterval time.Duration `mapstructure:"initial_interval"` - // RandomizationFactor is a random factor used to calculate next backoffs - // Randomized interval = RetryInterval * (1 ± RandomizationFactor) - RandomizationFactor float64 `mapstructure:"randomization_factor"` - // Multiplier is the value multiplied by the backoff interval bounds - Multiplier float64 `mapstructure:"multiplier"` - // MaxInterval is the upper bound on backoff interval. Once this value is reached the delay between - // consecutive retries will always be `MaxInterval`. - MaxInterval time.Duration `mapstructure:"max_interval"` - // MaxElapsedTime is the maximum amount of time (including retries) spent trying to send a request/batch. - // Once this value is reached, the data is discarded. - MaxElapsedTime time.Duration `mapstructure:"max_elapsed_time"` -} - -// NewDefaultRetrySettings returns the default settings for RetrySettings. -func NewDefaultRetrySettings() RetrySettings { - return RetrySettings{ - Enabled: true, - InitialInterval: 5 * time.Second, - RandomizationFactor: backoff.DefaultRandomizationFactor, - Multiplier: backoff.DefaultMultiplier, - MaxInterval: 30 * time.Second, - MaxElapsedTime: 5 * time.Minute, - } -} - // TODO: Clean this by forcing all exporters to return an internal error type that always include the information about retries. type throttleRetry struct { err error @@ -73,49 +43,30 @@ func NewThrottleRetry(err error, delay time.Duration) error { } } -type onRequestHandlingFinishedFunc func(*zap.Logger, internal.Request, error) error - type retrySender struct { baseRequestSender - traceAttribute attribute.KeyValue - cfg RetrySettings - stopCh chan struct{} - logger *zap.Logger - onTemporaryFailure onRequestHandlingFinishedFunc + traceAttribute attribute.KeyValue + cfg configretry.BackOffConfig + stopCh chan struct{} + logger *zap.Logger } -func newRetrySender(id component.ID, rCfg RetrySettings, logger *zap.Logger, onTemporaryFailure onRequestHandlingFinishedFunc) *retrySender { - if onTemporaryFailure == nil { - onTemporaryFailure = func(logger *zap.Logger, req internal.Request, err error) error { - return err - } - } +func newRetrySender(config configretry.BackOffConfig, set exporter.CreateSettings) *retrySender { return &retrySender{ - traceAttribute: attribute.String(obsmetrics.ExporterKey, id.String()), - cfg: rCfg, - stopCh: make(chan struct{}), - logger: logger, - onTemporaryFailure: onTemporaryFailure, + traceAttribute: attribute.String(obsmetrics.ExporterKey, set.ID.String()), + cfg: config, + stopCh: make(chan struct{}), + logger: set.Logger, } } -func (rs *retrySender) shutdown() { +func (rs *retrySender) Shutdown(context.Context) error { close(rs.stopCh) + return nil } // send implements the requestSender interface -func (rs *retrySender) send(req internal.Request) error { - if !rs.cfg.Enabled { - err := rs.nextSender.send(req) - if err != nil { - rs.logger.Error( - "Exporting failed. Try enabling retry_on_failure config option to retry on retryable errors", - zap.Error(err), - ) - } - return err - } - +func (rs *retrySender) send(ctx context.Context, req Request) error { // Do not use NewExponentialBackOff since it calls Reset and the code here must // call Reset after changing the InitialInterval (this saves an unnecessary call to Now). expBackoff := backoff.ExponentialBackOff{ @@ -128,42 +79,32 @@ func (rs *retrySender) send(req internal.Request) error { Clock: backoff.SystemClock, } expBackoff.Reset() - span := trace.SpanFromContext(req.Context()) + span := trace.SpanFromContext(ctx) retryNum := int64(0) for { span.AddEvent( "Sending request.", trace.WithAttributes(rs.traceAttribute, attribute.Int64("retry_num", retryNum))) - err := rs.nextSender.send(req) + err := rs.nextSender.send(ctx, req) if err == nil { return nil } // Immediately drop data on permanent errors. if consumererror.IsPermanent(err) { - rs.logger.Error( - "Exporting failed. The error is not retryable. Dropping data.", - zap.Error(err), - zap.Int("dropped_items", req.Count()), - ) - return err + return fmt.Errorf("not retryable error: %w", err) } - // Give the request a chance to extract signal data to retry if only some data - // failed to process. - req = req.OnError(err) + req = extractPartialRequest(req, err) backoffDelay := expBackoff.NextBackOff() if backoffDelay == backoff.Stop { - // throw away the batch - err = fmt.Errorf("max elapsed time expired %w", err) - return rs.onTemporaryFailure(rs.logger, req, err) + return fmt.Errorf("no more retries left: %w", err) } throttleErr := throttleRetry{} - isThrottle := errors.As(err, &throttleErr) - if isThrottle { + if errors.As(err, &throttleErr) { backoffDelay = max(backoffDelay, throttleErr.delay) } @@ -183,10 +124,10 @@ func (rs *retrySender) send(req internal.Request) error { // back-off, but get interrupted when shutting down or request is cancelled or timed out. select { - case <-req.Context().Done(): - return fmt.Errorf("Request is cancelled or timed out %w", err) + case <-ctx.Done(): + return fmt.Errorf("request is cancelled or timed out %w", err) case <-rs.stopCh: - return rs.onTemporaryFailure(rs.logger, req, fmt.Errorf("interrupted due to shutdown %w", err)) + return experr.NewShutdownErr(err) case <-time.After(backoffDelay): } } diff --git a/exporter/exporterhelper/retry_sender_test.go b/exporter/exporterhelper/retry_sender_test.go index 1da5fb29ebd..96b4904f372 100644 --- a/exporter/exporterhelper/retry_sender_test.go +++ b/exporter/exporterhelper/retry_sender_test.go @@ -6,7 +6,6 @@ package exporterhelper import ( "context" "errors" - "fmt" "sync" "sync/atomic" "testing" @@ -14,33 +13,34 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opencensus.io/metric/metricdata" - "go.opencensus.io/metric/metricproducer" - "go.opencensus.io/tag" + "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" - "go.opentelemetry.io/collector/exporter/exporterhelper/internal" + "go.opentelemetry.io/collector/exporter/exporterqueue" "go.opentelemetry.io/collector/exporter/exportertest" "go.opentelemetry.io/collector/internal/testdata" ) -func mockRequestUnmarshaler(mr *mockRequest) internal.RequestUnmarshaler { - return func(bytes []byte) (internal.Request, error) { +func mockRequestUnmarshaler(mr Request) exporterqueue.Unmarshaler[Request] { + return func([]byte) (Request, error) { return mr, nil } } -func mockRequestMarshaler(_ internal.Request) ([]byte, error) { - return nil, nil +func mockRequestMarshaler(Request) ([]byte, error) { + return []byte("mockRequest"), nil } func TestQueuedRetry_DropOnPermanentError(t *testing.T) { qCfg := NewDefaultQueueSettings() - rCfg := NewDefaultRetrySettings() - mockR := newMockRequest(context.Background(), 2, consumererror.NewPermanent(errors.New("bad data"))) - be, err := newBaseExporter(defaultSettings, "", false, nil, nil, newObservabilityConsumerSender, WithRetry(rCfg), WithQueue(qCfg)) + rCfg := configretry.NewDefaultBackOffConfig() + mockR := newMockRequest(2, consumererror.NewPermanent(errors.New("bad data"))) + be, err := newBaseExporter(defaultSettings, defaultType, 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())) @@ -50,7 +50,7 @@ func TestQueuedRetry_DropOnPermanentError(t *testing.T) { ocs.run(func() { // This is asynchronous so it should just enqueue, no errors expected. - require.NoError(t, be.send(mockR)) + require.NoError(t, be.send(context.Background(), mockR)) }) ocs.awaitAsyncProcessing() // In the newMockConcurrentExporter we count requests and items even for failed requests @@ -61,11 +61,11 @@ func TestQueuedRetry_DropOnPermanentError(t *testing.T) { func TestQueuedRetry_DropOnNoRetry(t *testing.T) { qCfg := NewDefaultQueueSettings() - rCfg := NewDefaultRetrySettings() + rCfg := configretry.NewDefaultBackOffConfig() rCfg.Enabled = false - be, err := newBaseExporter(defaultSettings, "", false, mockRequestMarshaler, - mockRequestUnmarshaler(newMockRequest(context.Background(), 2, errors.New("transient error"))), - newObservabilityConsumerSender, WithRetry(rCfg), WithQueue(qCfg)) + be, err := newBaseExporter(defaultSettings, defaultType, 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())) @@ -73,10 +73,10 @@ func TestQueuedRetry_DropOnNoRetry(t *testing.T) { assert.NoError(t, be.Shutdown(context.Background())) }) - mockR := newMockRequest(context.Background(), 2, errors.New("transient error")) + 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(mockR)) + require.NoError(t, be.send(context.Background(), mockR)) }) ocs.awaitAsyncProcessing() // In the newMockConcurrentExporter we count requests and items even for failed requests @@ -88,9 +88,11 @@ func TestQueuedRetry_DropOnNoRetry(t *testing.T) { func TestQueuedRetry_OnError(t *testing.T) { qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 1 - rCfg := NewDefaultRetrySettings() + rCfg := configretry.NewDefaultBackOffConfig() rCfg.InitialInterval = 0 - be, err := newBaseExporter(defaultSettings, "", false, nil, nil, newObservabilityConsumerSender, WithRetry(rCfg), WithQueue(qCfg)) + be, err := newBaseExporter(defaultSettings, defaultType, 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() { @@ -98,11 +100,11 @@ func TestQueuedRetry_OnError(t *testing.T) { }) traceErr := consumererror.NewTraces(errors.New("some error"), testdata.GenerateTraces(1)) - mockR := newMockRequest(context.Background(), 2, traceErr) + 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(mockR)) + require.NoError(t, be.send(context.Background(), mockR)) }) ocs.awaitAsyncProcessing() @@ -115,10 +117,12 @@ func TestQueuedRetry_OnError(t *testing.T) { func TestQueuedRetry_MaxElapsedTime(t *testing.T) { qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 1 - rCfg := NewDefaultRetrySettings() + rCfg := configretry.NewDefaultBackOffConfig() rCfg.InitialInterval = time.Millisecond rCfg.MaxElapsedTime = 100 * time.Millisecond - be, err := newBaseExporter(defaultSettings, "", false, nil, nil, newObservabilityConsumerSender, WithRetry(rCfg), WithQueue(qCfg)) + be, err := newBaseExporter(defaultSettings, defaultType, 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())) @@ -128,14 +132,14 @@ func TestQueuedRetry_MaxElapsedTime(t *testing.T) { ocs.run(func() { // Add an item that will always fail. - require.NoError(t, be.send(newErrorRequest(context.Background()))) + require.NoError(t, be.send(context.Background(), newErrorRequest())) }) - mockR := newMockRequest(context.Background(), 2, nil) + 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(mockR)) + require.NoError(t, be.send(context.Background(), mockR)) }) ocs.awaitAsyncProcessing() @@ -162,9 +166,11 @@ func (e wrappedError) Unwrap() error { func TestQueuedRetry_ThrottleError(t *testing.T) { qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 1 - rCfg := NewDefaultRetrySettings() + rCfg := configretry.NewDefaultBackOffConfig() rCfg.InitialInterval = 10 * time.Millisecond - be, err := newBaseExporter(defaultSettings, "", false, nil, nil, newObservabilityConsumerSender, WithRetry(rCfg), WithQueue(qCfg)) + be, err := newBaseExporter(defaultSettings, defaultType, 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())) @@ -173,11 +179,11 @@ func TestQueuedRetry_ThrottleError(t *testing.T) { }) retry := NewThrottleRetry(errors.New("throttle error"), 100*time.Millisecond) - mockR := newMockRequest(context.Background(), 2, wrappedError{retry}) + 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(mockR)) + require.NoError(t, be.send(context.Background(), mockR)) }) ocs.awaitAsyncProcessing() @@ -194,9 +200,11 @@ func TestQueuedRetry_RetryOnError(t *testing.T) { qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 1 qCfg.QueueSize = 1 - rCfg := NewDefaultRetrySettings() + rCfg := configretry.NewDefaultBackOffConfig() rCfg.InitialInterval = 0 - be, err := newBaseExporter(defaultSettings, "", false, nil, nil, newObservabilityConsumerSender, WithRetry(rCfg), WithQueue(qCfg)) + be, err := newBaseExporter(defaultSettings, defaultType, 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())) @@ -204,10 +212,10 @@ func TestQueuedRetry_RetryOnError(t *testing.T) { assert.NoError(t, be.Shutdown(context.Background())) }) - mockR := newMockRequest(context.Background(), 2, errors.New("transient error")) + 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(mockR)) + require.NoError(t, be.send(context.Background(), mockR)) }) ocs.awaitAsyncProcessing() @@ -219,16 +227,15 @@ func TestQueuedRetry_RetryOnError(t *testing.T) { } func TestQueueRetryWithNoQueue(t *testing.T) { - rCfg := NewDefaultRetrySettings() + rCfg := configretry.NewDefaultBackOffConfig() rCfg.MaxElapsedTime = time.Nanosecond // fail fast - be, err := newBaseExporter(exportertest.NewNopCreateSettings(), component.DataTypeLogs, false, nil, nil, newObservabilityConsumerSender, WithRetry(rCfg)) + be, err := newBaseExporter(exportertest.NewNopCreateSettings(), component.DataTypeLogs, newObservabilityConsumerSender, WithRetry(rCfg)) require.NoError(t, err) require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) ocs := be.obsrepSender.(*observabilityConsumerSender) - mockR := newMockRequest(context.Background(), 2, errors.New("some error")) + mockR := newMockRequest(2, errors.New("some error")) ocs.run(func() { - // This is asynchronous so it should just enqueue, no errors expected. - require.Error(t, be.send(mockR)) + require.Error(t, be.send(context.Background(), mockR)) }) ocs.awaitAsyncProcessing() mockR.checkNumRequests(t, 1) @@ -237,30 +244,49 @@ func TestQueueRetryWithNoQueue(t *testing.T) { require.NoError(t, be.Shutdown(context.Background())) } -type mockErrorRequest struct { - baseRequest +func TestQueueRetryWithDisabledRetires(t *testing.T) { + rCfg := configretry.NewDefaultBackOffConfig() + rCfg.Enabled = false + set := exportertest.NewNopCreateSettings() + logger, observed := observer.New(zap.ErrorLevel) + set.Logger = zap.New(logger) + be, err := newBaseExporter(set, component.DataTypeLogs, 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())) } -func (mer *mockErrorRequest) Export(_ context.Context) error { +type mockErrorRequest struct{} + +func (mer *mockErrorRequest) Export(context.Context) error { return errors.New("transient error") } -func (mer *mockErrorRequest) OnError(error) internal.Request { +func (mer *mockErrorRequest) OnError(error) Request { return mer } -func (mer *mockErrorRequest) Count() int { +func (mer *mockErrorRequest) ItemsCount() int { return 7 } -func newErrorRequest(ctx context.Context) internal.Request { - return &mockErrorRequest{ - baseRequest: baseRequest{ctx: ctx}, - } +func newErrorRequest() Request { + return &mockErrorRequest{} } type mockRequest struct { - baseRequest cnt int mu sync.Mutex consumeError error @@ -280,9 +306,8 @@ func (m *mockRequest) Export(ctx context.Context) error { return ctx.Err() } -func (m *mockRequest) OnError(error) internal.Request { +func (m *mockRequest) OnError(error) Request { return &mockRequest{ - baseRequest: m.baseRequest, cnt: 1, consumeError: nil, requestCount: m.requestCount, @@ -295,13 +320,12 @@ func (m *mockRequest) checkNumRequests(t *testing.T, want int) { }, time.Second, 1*time.Millisecond) } -func (m *mockRequest) Count() int { +func (m *mockRequest) ItemsCount() int { return m.cnt } -func newMockRequest(ctx context.Context, cnt int, consumeError error) *mockRequest { +func newMockRequest(cnt int, consumeError error) *mockRequest { return &mockRequest{ - baseRequest: baseRequest{ctx: ctx}, cnt: cnt, consumeError: consumeError, requestCount: &atomic.Int64{}, @@ -315,7 +339,7 @@ type observabilityConsumerSender struct { droppedItemsCount *atomic.Int64 } -func newObservabilityConsumerSender(_ *obsExporter) requestSender { +func newObservabilityConsumerSender(*ObsReport) requestSender { return &observabilityConsumerSender{ waitGroup: new(sync.WaitGroup), droppedItemsCount: &atomic.Int64{}, @@ -323,12 +347,12 @@ func newObservabilityConsumerSender(_ *obsExporter) requestSender { } } -func (ocs *observabilityConsumerSender) send(req internal.Request) error { - err := ocs.nextSender.send(req) +func (ocs *observabilityConsumerSender) send(ctx context.Context, req Request) error { + err := ocs.nextSender.send(ctx, req) if err != nil { - ocs.droppedItemsCount.Add(int64(req.Count())) + ocs.droppedItemsCount.Add(int64(req.ItemsCount())) } else { - ocs.sentItemsCount.Add(int64(req.Count())) + ocs.sentItemsCount.Add(int64(req.ItemsCount())) } ocs.waitGroup.Done() return err @@ -350,66 +374,3 @@ func (ocs *observabilityConsumerSender) checkSendItemsCount(t *testing.T, want i func (ocs *observabilityConsumerSender) checkDroppedItemsCount(t *testing.T, want int) { assert.EqualValues(t, want, ocs.droppedItemsCount.Load()) } - -// checkValueForGlobalManager checks that the given metrics with wantTags is reported by one of the -// metric producers -func checkValueForGlobalManager(t *testing.T, wantTags []tag.Tag, value int64, vName string) { - producers := metricproducer.GlobalManager().GetAll() - for _, producer := range producers { - if checkValueForProducer(t, producer, wantTags, value, vName) { - return - } - } - require.Fail(t, fmt.Sprintf("could not find metric %v with tags %s reported", vName, wantTags)) -} - -// checkValueForProducer checks that the given metrics with wantTags is reported by the metric producer -func checkValueForProducer(t *testing.T, producer metricproducer.Producer, wantTags []tag.Tag, value int64, vName string) bool { - for _, metric := range producer.Read() { - if metric.Descriptor.Name == vName && len(metric.TimeSeries) > 0 { - for _, ts := range metric.TimeSeries { - if tagsMatchLabelKeys(wantTags, metric.Descriptor.LabelKeys, ts.LabelValues) { - require.Equal(t, value, ts.Points[len(ts.Points)-1].Value.(int64)) - return true - } - } - } - } - return false -} - -// tagsMatchLabelKeys returns true if provided tags match keys and values -func tagsMatchLabelKeys(tags []tag.Tag, keys []metricdata.LabelKey, labels []metricdata.LabelValue) bool { - if len(tags) != len(keys) { - return false - } - for i := 0; i < len(tags); i++ { - var labelVal string - if labels[i].Present { - labelVal = labels[i].Value - } - if tags[i].Key.Name() != keys[i].Key || tags[i].Value != labelVal { - return false - } - } - return true -} - -type producerConsumerQueueWithCounter struct { - internal.ProducerConsumerQueue - produceCounter *atomic.Uint32 -} - -func (pcq *producerConsumerQueueWithCounter) Produce(item internal.Request) bool { - pcq.produceCounter.Add(1) - return pcq.ProducerConsumerQueue.Produce(item) -} - -type errorRequestSender struct { - baseRequestSender - errToReturn error -} - -func (rs *errorRequestSender) send(_ internal.Request) error { - return rs.errToReturn -} diff --git a/exporter/exporterhelper/timeout_sender.go b/exporter/exporterhelper/timeout_sender.go index 11b85cf08be..2a6364a2aaf 100644 --- a/exporter/exporterhelper/timeout_sender.go +++ b/exporter/exporterhelper/timeout_sender.go @@ -5,17 +5,25 @@ package exporterhelper // import "go.opentelemetry.io/collector/exporter/exporte import ( "context" + "errors" "time" - - "go.opentelemetry.io/collector/exporter/exporterhelper/internal" ) // TimeoutSettings for timeout. The timeout applies to individual attempts to send data to the backend. type TimeoutSettings struct { // Timeout is the timeout for every attempt to send data to the backend. + // A zero timeout means no timeout. Timeout time.Duration `mapstructure:"timeout"` } +func (ts *TimeoutSettings) Validate() error { + // Negative timeouts are not acceptable, since all sends will fail. + if ts.Timeout < 0 { + return errors.New("'timeout' must be non-negative") + } + return nil +} + // NewDefaultTimeoutSettings returns the default settings for TimeoutSettings. func NewDefaultTimeoutSettings() TimeoutSettings { return TimeoutSettings{ @@ -29,14 +37,14 @@ type timeoutSender struct { cfg TimeoutSettings } -func (ts *timeoutSender) send(req internal.Request) error { +func (ts *timeoutSender) send(ctx context.Context, req Request) error { + // TODO: Remove this by avoiding to create the timeout sender if timeout is 0. + if ts.cfg.Timeout == 0 { + return req.Export(ctx) + } // Intentionally don't overwrite the context inside the request, because in case of retries deadline will not be // updated because this deadline most likely is before the next one. - ctx := req.Context() - if ts.cfg.Timeout > 0 { - var cancelFunc func() - ctx, cancelFunc = context.WithTimeout(req.Context(), ts.cfg.Timeout) - defer cancelFunc() - } - return req.Export(ctx) + tCtx, cancelFunc := context.WithTimeout(ctx, ts.cfg.Timeout) + defer cancelFunc() + return req.Export(tCtx) } diff --git a/exporter/exporterhelper/timeout_sender_test.go b/exporter/exporterhelper/timeout_sender_test.go new file mode 100644 index 00000000000..205ac094c07 --- /dev/null +++ b/exporter/exporterhelper/timeout_sender_test.go @@ -0,0 +1,24 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterhelper + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestNewDefaultTimeoutSettings(t *testing.T) { + cfg := NewDefaultTimeoutSettings() + assert.NoError(t, cfg.Validate()) + assert.Equal(t, TimeoutSettings{Timeout: 5 * time.Second}, cfg) +} + +func TestInvalidTimeout(t *testing.T) { + cfg := NewDefaultTimeoutSettings() + assert.NoError(t, cfg.Validate()) + cfg.Timeout = -1 + assert.Error(t, cfg.Validate()) +} diff --git a/exporter/exporterhelper/traces.go b/exporter/exporterhelper/traces.go index 4b9e397ec43..778c0d63989 100644 --- a/exporter/exporterhelper/traces.go +++ b/exporter/exporterhelper/traces.go @@ -13,7 +13,8 @@ import ( "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/exporter" - "go.opentelemetry.io/collector/exporter/exporterhelper/internal" + "go.opentelemetry.io/collector/exporter/exporterqueue" + "go.opentelemetry.io/collector/exporter/internal/queue" "go.opentelemetry.io/collector/pdata/ptrace" ) @@ -21,37 +22,35 @@ var tracesMarshaler = &ptrace.ProtoMarshaler{} var tracesUnmarshaler = &ptrace.ProtoUnmarshaler{} type tracesRequest struct { - baseRequest td ptrace.Traces pusher consumer.ConsumeTracesFunc } -func newTracesRequest(ctx context.Context, td ptrace.Traces, pusher consumer.ConsumeTracesFunc) internal.Request { +func newTracesRequest(td ptrace.Traces, pusher consumer.ConsumeTracesFunc) Request { return &tracesRequest{ - baseRequest: baseRequest{ctx: ctx}, - td: td, - pusher: pusher, + td: td, + pusher: pusher, } } -func newTraceRequestUnmarshalerFunc(pusher consumer.ConsumeTracesFunc) internal.RequestUnmarshaler { - return func(bytes []byte) (internal.Request, error) { +func newTraceRequestUnmarshalerFunc(pusher consumer.ConsumeTracesFunc) exporterqueue.Unmarshaler[Request] { + return func(bytes []byte) (Request, error) { traces, err := tracesUnmarshaler.UnmarshalTraces(bytes) if err != nil { return nil, err } - return newTracesRequest(context.Background(), traces, pusher), nil + return newTracesRequest(traces, pusher), nil } } -func tracesRequestMarshaler(req internal.Request) ([]byte, error) { +func tracesRequestMarshaler(req Request) ([]byte, error) { return tracesMarshaler.MarshalTraces(req.(*tracesRequest).td) } -func (req *tracesRequest) OnError(err error) internal.Request { +func (req *tracesRequest) OnError(err error) Request { var traceError consumererror.Traces if errors.As(err, &traceError) { - return newTracesRequest(req.ctx, traceError.Data(), req.pusher) + return newTracesRequest(traceError.Data(), req.pusher) } return req } @@ -60,7 +59,7 @@ func (req *tracesRequest) Export(ctx context.Context) error { return req.pusher(ctx, req.td) } -func (req *tracesRequest) Count() int { +func (req *tracesRequest) ItemsCount() int { return req.td.SpanCount() } @@ -71,7 +70,7 @@ type traceExporter struct { // NewTracesExporter creates an exporter.Traces that records observability metrics and wraps every request with a Span. func NewTracesExporter( - _ context.Context, + ctx context.Context, set exporter.CreateSettings, cfg component.Config, pusher consumer.ConsumeTracesFunc, @@ -80,42 +79,23 @@ func NewTracesExporter( if cfg == nil { return nil, errNilConfig } - - if set.Logger == nil { - return nil, errNilLogger - } - if pusher == nil { return nil, errNilPushTraceData } - - be, err := newBaseExporter(set, component.DataTypeTraces, false, tracesRequestMarshaler, - newTraceRequestUnmarshalerFunc(pusher), newTracesExporterWithObservability, options...) - if err != nil { - return nil, err - } - - tc, err := consumer.NewTraces(func(ctx context.Context, td ptrace.Traces) error { - req := newTracesRequest(ctx, td, pusher) - serr := be.send(req) - if errors.Is(serr, errSendingQueueIsFull) { - be.obsrep.recordTracesEnqueueFailure(req.Context(), int64(req.Count())) - } - return serr - }, be.consumerOptions...) - - return &traceExporter{ - baseExporter: be, - Traces: tc, - }, err + tracesOpts := []Option{withMarshaler(tracesRequestMarshaler), withUnmarshaler(newTraceRequestUnmarshalerFunc(pusher))} + return NewTracesRequestExporter(ctx, set, requestFromTraces(pusher), append(tracesOpts, options...)...) } -// TracesConverter provides an interface for converting ptrace.Traces into a request. +// RequestFromTracesFunc converts ptrace.Traces into a user-defined Request. // This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. -type TracesConverter interface { - // RequestFromTraces converts ptrace.Traces into a Request. - RequestFromTraces(context.Context, ptrace.Traces) (Request, error) +type RequestFromTracesFunc func(context.Context, ptrace.Traces) (Request, error) + +// requestFromTraces returns a RequestFromTracesFunc that converts ptrace.Traces into a Request. +func requestFromTraces(pusher consumer.ConsumeTracesFunc) RequestFromTracesFunc { + return func(_ context.Context, traces ptrace.Traces) (Request, error) { + return newTracesRequest(traces, pusher), nil + } } // NewTracesRequestExporter creates a new traces exporter based on a custom TracesConverter and RequestSender. @@ -124,7 +104,7 @@ type TracesConverter interface { func NewTracesRequestExporter( _ context.Context, set exporter.CreateSettings, - converter TracesConverter, + converter RequestFromTracesFunc, options ...Option, ) (exporter.Traces, error) { if set.Logger == nil { @@ -135,23 +115,22 @@ func NewTracesRequestExporter( return nil, errNilTracesConverter } - be, err := newBaseExporter(set, component.DataTypeTraces, true, nil, nil, newTracesExporterWithObservability, options...) + be, err := newBaseExporter(set, component.DataTypeTraces, newTracesExporterWithObservability, options...) if err != nil { return nil, err } tc, err := consumer.NewTraces(func(ctx context.Context, td ptrace.Traces) error { - req, cErr := converter.RequestFromTraces(ctx, td) + req, cErr := converter(ctx, td) if cErr != nil { set.Logger.Error("Failed to convert traces. Dropping data.", zap.Int("dropped_spans", td.SpanCount()), zap.Error(err)) return consumererror.NewPermanent(cErr) } - r := newRequest(ctx, req) - sErr := be.send(r) - if errors.Is(sErr, errSendingQueueIsFull) { - be.obsrep.recordTracesEnqueueFailure(r.Context(), int64(r.Count())) + sErr := be.send(ctx, req) + if errors.Is(sErr, queue.ErrQueueIsFull) { + be.obsrep.recordEnqueueFailure(ctx, component.DataTypeTraces, int64(req.ItemsCount())) } return sErr }, be.consumerOptions...) @@ -164,17 +143,17 @@ func NewTracesRequestExporter( type tracesExporterWithObservability struct { baseRequestSender - obsrep *obsExporter + obsrep *ObsReport } -func newTracesExporterWithObservability(obsrep *obsExporter) requestSender { +func newTracesExporterWithObservability(obsrep *ObsReport) requestSender { return &tracesExporterWithObservability{obsrep: obsrep} } -func (tewo *tracesExporterWithObservability) send(req internal.Request) error { - req.SetContext(tewo.obsrep.StartTracesOp(req.Context())) +func (tewo *tracesExporterWithObservability) send(ctx context.Context, req Request) error { + c := tewo.obsrep.StartTracesOp(ctx) // Forward the data to the next consumer (this pusher is the next). - err := tewo.nextSender.send(req) - tewo.obsrep.EndTracesOp(req.Context(), req.Count(), err) + err := tewo.nextSender.send(c, req) + tewo.obsrep.EndTracesOp(c, req.ItemsCount(), err) return err } diff --git a/exporter/exporterhelper/traces_test.go b/exporter/exporterhelper/traces_test.go index ff7847b6990..0c8bec25f5f 100644 --- a/exporter/exporterhelper/traces_test.go +++ b/exporter/exporterhelper/traces_test.go @@ -16,18 +16,19 @@ import ( sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/sdk/trace/tracetest" "go.opentelemetry.io/otel/trace" + nooptrace "go.opentelemetry.io/otel/trace/noop" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/exporter" - "go.opentelemetry.io/collector/exporter/exporterhelper/internal" "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/exporter/internal/queue" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" "go.opentelemetry.io/collector/internal/testdata" - "go.opentelemetry.io/collector/obsreport/obsreporttest" "go.opentelemetry.io/collector/pdata/ptrace" ) @@ -36,15 +37,15 @@ const ( ) var ( - fakeTracesExporterName = component.NewIDWithName("fake_traces_exporter", "with_name") + fakeTracesExporterName = component.MustNewIDWithName("fake_traces_exporter", "with_name") fakeTracesExporterConfig = struct{}{} ) func TestTracesRequest(t *testing.T) { - mr := newTracesRequest(context.Background(), testdata.GenerateTraces(1), nil) + mr := newTracesRequest(testdata.GenerateTraces(1), nil) traceErr := consumererror.NewTraces(errors.New("some error"), ptrace.NewTraces()) - assert.EqualValues(t, newTracesRequest(context.Background(), ptrace.NewTraces(), nil), mr.OnError(traceErr)) + assert.EqualValues(t, newTracesRequest(ptrace.NewTraces(), nil), mr.(RequestErrorHandler).OnError(traceErr)) } func TestTracesExporter_InvalidName(t *testing.T) { @@ -60,7 +61,7 @@ func TestTracesExporter_NilLogger(t *testing.T) { } func TestTracesRequestExporter_NilLogger(t *testing.T) { - te, err := NewTracesRequestExporter(context.Background(), exporter.CreateSettings{}, &fakeRequestConverter{}) + te, err := NewTracesRequestExporter(context.Background(), exporter.CreateSettings{}, (&fakeRequestConverter{}).requestFromTracesFunc) require.Nil(t, te) require.Equal(t, errNilLogger, err) } @@ -91,7 +92,8 @@ func TestTracesExporter_Default(t *testing.T) { func TestTracesRequestExporter_Default(t *testing.T) { td := ptrace.NewTraces() - te, err := NewTracesRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), &fakeRequestConverter{}) + te, err := NewTracesRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), + (&fakeRequestConverter{}).requestFromTracesFunc) assert.NotNil(t, te) assert.NoError(t, err) @@ -112,7 +114,8 @@ func TestTracesExporter_WithCapabilities(t *testing.T) { func TestTracesRequestExporter_WithCapabilities(t *testing.T) { capabilities := consumer.Capabilities{MutatesData: true} - te, err := NewTracesRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), &fakeRequestConverter{}, WithCapabilities(capabilities)) + te, err := NewTracesRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), + (&fakeRequestConverter{}).requestFromTracesFunc, WithCapabilities(capabilities)) assert.NotNil(t, te) assert.NoError(t, err) @@ -134,7 +137,7 @@ func TestTracesRequestExporter_Default_ConvertError(t *testing.T) { td := ptrace.NewTraces() want := errors.New("convert_error") te, err := NewTracesRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), - &fakeRequestConverter{tracesError: want}) + (&fakeRequestConverter{tracesError: want}).requestFromTracesFunc) require.NoError(t, err) require.NotNil(t, te) require.Equal(t, consumererror.NewPermanent(want), te.ConsumeTraces(context.Background(), td)) @@ -143,7 +146,8 @@ func TestTracesRequestExporter_Default_ConvertError(t *testing.T) { func TestTracesRequestExporter_Default_ExportError(t *testing.T) { td := ptrace.NewTraces() want := errors.New("export_error") - te, err := NewTracesRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), &fakeRequestConverter{requestError: want}) + te, err := NewTracesRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), + (&fakeRequestConverter{requestError: want}).requestFromTracesFunc) require.NoError(t, err) require.NotNil(t, te) require.Equal(t, want, te.ConsumeTraces(context.Background(), td)) @@ -151,17 +155,17 @@ func TestTracesRequestExporter_Default_ExportError(t *testing.T) { func TestTracesExporter_WithPersistentQueue(t *testing.T) { qCfg := NewDefaultQueueSettings() - storageID := component.NewIDWithName("file_storage", "storage") + storageID := component.MustNewIDWithName("file_storage", "storage") qCfg.StorageID = &storageID - rCfg := NewDefaultRetrySettings() + rCfg := configretry.NewDefaultBackOffConfig() ts := consumertest.TracesSink{} set := exportertest.NewNopCreateSettings() - set.ID = component.NewIDWithName("test_traces", "with_persistent_queue") + set.ID = component.MustNewIDWithName("test_traces", "with_persistent_queue") te, err := NewTracesExporter(context.Background(), set, &fakeTracesExporterConfig, ts.ConsumeTraces, WithRetry(rCfg), WithQueue(qCfg)) require.NoError(t, err) host := &mockHost{ext: map[component.ID]component.Component{ - storageID: internal.NewMockStorageExtension(nil), + storageID: queue.NewMockStorageExtension(nil), }} require.NoError(t, te.Start(context.Background(), host)) t.Cleanup(func() { require.NoError(t, te.Shutdown(context.Background())) }) @@ -174,11 +178,11 @@ func TestTracesExporter_WithPersistentQueue(t *testing.T) { } func TestTracesExporter_WithRecordMetrics(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(fakeTracesExporterName) + tt, err := componenttest.SetupTelemetry(fakeTracesExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - te, err := NewTracesExporter(context.Background(), exportertest.NewCreateSettings(fakeTracesExporterName, tt.TelemetrySettings), &fakeTracesExporterConfig, newTraceDataPusher(nil)) + te, err := NewTracesExporter(context.Background(), exporter.CreateSettings{ID: fakeTracesExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, &fakeTracesExporterConfig, newTraceDataPusher(nil)) require.NoError(t, err) require.NotNil(t, te) @@ -186,11 +190,13 @@ func TestTracesExporter_WithRecordMetrics(t *testing.T) { } func TestTracesRequestExporter_WithRecordMetrics(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(fakeTracesExporterName) + tt, err := componenttest.SetupTelemetry(fakeTracesExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - te, err := NewTracesRequestExporter(context.Background(), exportertest.NewCreateSettings(fakeTracesExporterName, tt.TelemetrySettings), &fakeRequestConverter{}) + te, err := NewTracesRequestExporter(context.Background(), + exporter.CreateSettings{ID: fakeTracesExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + (&fakeRequestConverter{}).requestFromTracesFunc) require.NoError(t, err) require.NotNil(t, te) @@ -199,11 +205,11 @@ func TestTracesRequestExporter_WithRecordMetrics(t *testing.T) { func TestTracesExporter_WithRecordMetrics_ReturnError(t *testing.T) { want := errors.New("my_error") - tt, err := obsreporttest.SetupTelemetry(fakeTracesExporterName) + tt, err := componenttest.SetupTelemetry(fakeTracesExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - te, err := NewTracesExporter(context.Background(), exportertest.NewCreateSettings(fakeTracesExporterName, tt.TelemetrySettings), &fakeTracesExporterConfig, newTraceDataPusher(want)) + te, err := NewTracesExporter(context.Background(), exporter.CreateSettings{ID: fakeTracesExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, &fakeTracesExporterConfig, newTraceDataPusher(want)) require.NoError(t, err) require.NotNil(t, te) @@ -212,11 +218,13 @@ func TestTracesExporter_WithRecordMetrics_ReturnError(t *testing.T) { func TestTracesRequestExporter_WithRecordMetrics_RequestSenderError(t *testing.T) { want := errors.New("export_error") - tt, err := obsreporttest.SetupTelemetry(fakeTracesExporterName) + tt, err := componenttest.SetupTelemetry(fakeTracesExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - te, err := NewTracesRequestExporter(context.Background(), exportertest.NewCreateSettings(fakeTracesExporterName, tt.TelemetrySettings), &fakeRequestConverter{requestError: want}) + te, err := NewTracesRequestExporter(context.Background(), + exporter.CreateSettings{ID: fakeTracesExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + (&fakeRequestConverter{requestError: want}).requestFromTracesFunc) require.NoError(t, err) require.NotNil(t, te) @@ -224,16 +232,16 @@ func TestTracesRequestExporter_WithRecordMetrics_RequestSenderError(t *testing.T } func TestTracesExporter_WithRecordEnqueueFailedMetrics(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(fakeTracesExporterName) + tt, err := componenttest.SetupTelemetry(fakeTracesExporterName) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - rCfg := NewDefaultRetrySettings() + rCfg := configretry.NewDefaultBackOffConfig() qCfg := NewDefaultQueueSettings() qCfg.NumConsumers = 1 qCfg.QueueSize = 2 wantErr := errors.New("some-error") - te, err := NewTracesExporter(context.Background(), exportertest.NewCreateSettings(fakeTracesExporterName, tt.TelemetrySettings), &fakeTracesExporterConfig, newTraceDataPusher(wantErr), WithRetry(rCfg), WithQueue(qCfg)) + te, err := NewTracesExporter(context.Background(), exporter.CreateSettings{ID: fakeTracesExporterName, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, &fakeTracesExporterConfig, newTraceDataPusher(wantErr), WithRetry(rCfg), WithQueue(qCfg)) require.NoError(t, err) require.NotNil(t, te) @@ -245,7 +253,7 @@ func TestTracesExporter_WithRecordEnqueueFailedMetrics(t *testing.T) { } // 2 batched must be in queue, and 5 batches (10 spans) rejected due to queue overflow - checkExporterEnqueueFailedTracesStats(t, globalInstruments, fakeTracesExporterName, int64(10)) + require.NoError(t, tt.CheckExporterEnqueueFailedTraces(int64(10))) } func TestTracesExporter_WithSpan(t *testing.T) { @@ -253,7 +261,7 @@ func TestTracesExporter_WithSpan(t *testing.T) { sr := new(tracetest.SpanRecorder) set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) otel.SetTracerProvider(set.TracerProvider) - defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) te, err := NewTracesExporter(context.Background(), set, &fakeTracesExporterConfig, newTraceDataPusher(nil)) require.NoError(t, err) @@ -267,9 +275,9 @@ func TestTracesRequestExporter_WithSpan(t *testing.T) { sr := new(tracetest.SpanRecorder) set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) otel.SetTracerProvider(set.TracerProvider) - defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) - te, err := NewTracesRequestExporter(context.Background(), set, &fakeRequestConverter{}) + te, err := NewTracesRequestExporter(context.Background(), set, (&fakeRequestConverter{}).requestFromTracesFunc) require.NoError(t, err) require.NotNil(t, te) @@ -281,7 +289,7 @@ func TestTracesExporter_WithSpan_ReturnError(t *testing.T) { sr := new(tracetest.SpanRecorder) set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) otel.SetTracerProvider(set.TracerProvider) - defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) want := errors.New("my_error") te, err := NewTracesExporter(context.Background(), set, &fakeTracesExporterConfig, newTraceDataPusher(want)) @@ -296,10 +304,10 @@ func TestTracesRequestExporter_WithSpan_ExportError(t *testing.T) { sr := new(tracetest.SpanRecorder) set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) otel.SetTracerProvider(set.TracerProvider) - defer otel.SetTracerProvider(trace.NewNoopTracerProvider()) + defer otel.SetTracerProvider(nooptrace.NewTracerProvider()) want := errors.New("export_error") - te, err := NewTracesRequestExporter(context.Background(), set, &fakeRequestConverter{requestError: want}) + te, err := NewTracesRequestExporter(context.Background(), set, (&fakeRequestConverter{requestError: want}).requestFromTracesFunc) require.NoError(t, err) require.NotNil(t, te) @@ -323,7 +331,8 @@ func TestTracesRequestExporter_WithShutdown(t *testing.T) { shutdownCalled := false shutdown := func(context.Context) error { shutdownCalled = true; return nil } - te, err := NewTracesRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), &fakeRequestConverter{}, WithShutdown(shutdown)) + te, err := NewTracesRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), + (&fakeRequestConverter{}).requestFromTracesFunc, WithShutdown(shutdown)) assert.NotNil(t, te) assert.NoError(t, err) @@ -348,7 +357,8 @@ func TestTracesRequestExporter_WithShutdown_ReturnError(t *testing.T) { want := errors.New("my_error") shutdownErr := func(context.Context) error { return want } - te, err := NewTracesRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), &fakeRequestConverter{}, WithShutdown(shutdownErr)) + te, err := NewTracesRequestExporter(context.Background(), exportertest.NewNopCreateSettings(), + (&fakeRequestConverter{}).requestFromTracesFunc, WithShutdown(shutdownErr)) assert.NotNil(t, te) assert.NoError(t, err) @@ -357,12 +367,12 @@ func TestTracesRequestExporter_WithShutdown_ReturnError(t *testing.T) { } func newTraceDataPusher(retError error) consumer.ConsumeTracesFunc { - return func(ctx context.Context, td ptrace.Traces) error { + return func(context.Context, ptrace.Traces) error { return retError } } -func checkRecordedMetricsForTracesExporter(t *testing.T, tt obsreporttest.TestTelemetry, te exporter.Traces, wantError error) { +func checkRecordedMetricsForTracesExporter(t *testing.T, tt componenttest.TestTelemetry, te exporter.Traces, wantError error) { td := testdata.GenerateTraces(2) const numBatches = 7 for i := 0; i < numBatches; i++ { diff --git a/exporter/exporterqueue/config.go b/exporter/exporterqueue/config.go new file mode 100644 index 00000000000..ac888a0c227 --- /dev/null +++ b/exporter/exporterqueue/config.go @@ -0,0 +1,61 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterqueue // import "go.opentelemetry.io/collector/exporter/exporterqueue" + +import ( + "errors" + + "go.opentelemetry.io/collector/component" +) + +// Config defines configuration for queueing requests before exporting. +// It's supposed to be used with the new exporter helpers New[Traces|Metrics|Logs]RequestExporter. +// 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 Config struct { + // Enabled indicates whether to not enqueue batches before exporting. + Enabled bool `mapstructure:"enabled"` + // NumConsumers is the number of consumers from the queue. + NumConsumers int `mapstructure:"num_consumers"` + // QueueSize is the maximum number of requests allowed in queue at any given time. + QueueSize int `mapstructure:"queue_size"` +} + +// NewDefaultConfig returns the default Config. +// 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 NewDefaultConfig() Config { + return Config{ + Enabled: true, + NumConsumers: 10, + QueueSize: 1_000, + } +} + +// Validate checks if the QueueSettings configuration is valid +func (qCfg *Config) Validate() error { + if !qCfg.Enabled { + return nil + } + if qCfg.NumConsumers <= 0 { + return errors.New("number of consumers must be positive") + } + if qCfg.QueueSize <= 0 { + return errors.New("queue size must be positive") + } + return nil +} + +// PersistentQueueConfig defines configuration for queueing requests in a persistent storage. +// The struct is provided to be added in the exporter configuration as one struct under the "sending_queue" key. +// The exporter helper Go interface requires the fields to be provided separately to WithRequestQueue and +// NewPersistentQueueFactory. +// 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 PersistentQueueConfig struct { + Config `mapstructure:",squash"` + // StorageID if not empty, enables the persistent storage and uses the component specified + // as a storage extension for the persistent queue + StorageID *component.ID `mapstructure:"storage"` +} diff --git a/exporter/exporterqueue/config_test.go b/exporter/exporterqueue/config_test.go new file mode 100644 index 00000000000..c1b43ba5f8e --- /dev/null +++ b/exporter/exporterqueue/config_test.go @@ -0,0 +1,26 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterqueue + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestQueueConfig_Validate(t *testing.T) { + qCfg := NewDefaultConfig() + assert.NoError(t, qCfg.Validate()) + + qCfg.NumConsumers = 0 + assert.EqualError(t, qCfg.Validate(), "number of consumers must be positive") + + qCfg = NewDefaultConfig() + qCfg.QueueSize = 0 + assert.EqualError(t, qCfg.Validate(), "queue size must be positive") + + // Confirm Validate doesn't return error with invalid config when feature is disabled + qCfg.Enabled = false + assert.NoError(t, qCfg.Validate()) +} diff --git a/exporter/exporterqueue/queue.go b/exporter/exporterqueue/queue.go new file mode 100644 index 00000000000..556dce9f9c2 --- /dev/null +++ b/exporter/exporterqueue/queue.go @@ -0,0 +1,96 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterqueue // import "go.opentelemetry.io/collector/exporter/exporterqueue" + +import ( + "context" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/internal/queue" +) + +// 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) +// 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 Queue[T any] queue.Queue[T] + +// Settings defines settings for creating a queue. +type Settings struct { + DataType component.DataType + ExporterSettings exporter.CreateSettings +} + +// Marshaler is a function that can marshal a request into bytes. +// 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 Marshaler[T any] func(T) ([]byte, error) + +// Unmarshaler is a function that can unmarshal bytes into a request. +// This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. +type Unmarshaler[T any] func([]byte) (T, error) + +// Factory is a function that creates a new queue. +// 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] + +// NewMemoryQueueFactory returns a factory to create a new memory queue. +// 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 itemsCounter]() Factory[T] { + return func(_ context.Context, _ Settings, cfg Config) Queue[T] { + return queue.NewBoundedMemoryQueue[T](queue.MemoryQueueSettings[T]{ + Sizer: sizerFromConfig[T](cfg), + Capacity: capacityFromConfig(cfg), + }) + } +} + +// PersistentQueueSettings defines developer settings for the persistent queue factory. +// 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 PersistentQueueSettings[T any] struct { + // Marshaler is used to serialize queue elements before storing them in the persistent storage. + Marshaler Marshaler[T] + // Unmarshaler is used to deserialize requests after reading them from the persistent storage. + Unmarshaler Unmarshaler[T] +} + +// NewPersistentQueueFactory returns a factory to create a new persistent queue. +// If cfg.StorageID is nil then it falls back to memory queue. +// 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 NewPersistentQueueFactory[T itemsCounter](storageID *component.ID, factorySettings PersistentQueueSettings[T]) Factory[T] { + if storageID == nil { + return NewMemoryQueueFactory[T]() + } + return func(_ context.Context, set Settings, cfg Config) Queue[T] { + return queue.NewPersistentQueue[T](queue.PersistentQueueSettings[T]{ + Sizer: sizerFromConfig[T](cfg), + Capacity: capacityFromConfig(cfg), + DataType: set.DataType, + StorageID: *storageID, + Marshaler: factorySettings.Marshaler, + Unmarshaler: factorySettings.Unmarshaler, + ExporterSettings: set.ExporterSettings, + }) + } +} + +type itemsCounter interface { + ItemsCount() int +} + +func sizerFromConfig[T itemsCounter](Config) queue.Sizer[T] { + // TODO: Handle other ways to measure the queue size once they are added. + return &queue.RequestSizer[T]{} +} + +func capacityFromConfig(cfg Config) int { + // TODO: Handle other ways to measure the queue size once they are added. + return cfg.QueueSize +} diff --git a/exporter/exportertest/contract_checker.go b/exporter/exportertest/contract_checker.go new file mode 100644 index 00000000000..7b3f55c1902 --- /dev/null +++ b/exporter/exportertest/contract_checker.go @@ -0,0 +1,280 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exportertest // import "go.opentelemetry.io/collector/exporter/exportertest" + +import ( + "context" + "fmt" + "strconv" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/collector/receiver" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +// uniqueIDAttrName is the attribute name that is used in log records/spans/datapoints as the unique identifier. +const uniqueIDAttrName = "test_id" + +// uniqueIDAttrVal is the value type of the uniqueIDAttrName. +type uniqueIDAttrVal string + +type CheckConsumeContractParams struct { + T *testing.T + NumberOfTestElements int + // DataType to test for. + DataType component.DataType + // ExporterFactory to create an exporter to be tested. + ExporterFactory exporter.Factory + ExporterConfig component.Config + // ReceiverFactory to create a mock receiver. + ReceiverFactory receiver.Factory + ReceiverConfig component.Config +} + +func CheckConsumeContract(params CheckConsumeContractParams) { + // Different scenarios to test for. + // The decision function defines the testing scenario (i.e. to test for + // success case or for error case or a mix of both). See for example randomErrorsConsumeDecision. + scenarios := []struct { + name string + decisionFunc func() error + checkIfTestPassed func(*testing.T, int, requestCounter) + }{ + { + name: "always_succeed", + // Always succeed. We expect all data to be delivered as is. + decisionFunc: func() error { return nil }, + checkIfTestPassed: alwaysSucceedsPassed, + }, + { + name: "random_non_permanent_error", + decisionFunc: randomNonPermanentErrorConsumeDecision, + checkIfTestPassed: randomNonPermanentErrorConsumeDecisionPassed, + }, + { + name: "random_permanent_error", + decisionFunc: randomPermanentErrorConsumeDecision, + checkIfTestPassed: randomPermanentErrorConsumeDecisionPassed, + }, + { + name: "random_error", + decisionFunc: randomErrorsConsumeDecision, + checkIfTestPassed: randomErrorConsumeDecisionPassed, + }, + } + for _, scenario := range scenarios { + params.T.Run( + scenario.name, func(t *testing.T) { + checkConsumeContractScenario(t, params, scenario.decisionFunc, scenario.checkIfTestPassed) + }, + ) + } +} + +func checkConsumeContractScenario(t *testing.T, params CheckConsumeContractParams, decisionFunc func() error, checkIfTestPassed func(*testing.T, int, requestCounter)) { + mockConsumerInstance := newMockConsumer(decisionFunc) + switch params.DataType { + case component.DataTypeLogs: + r, err := params.ReceiverFactory.CreateLogsReceiver(context.Background(), receivertest.NewNopCreateSettings(), params.ReceiverConfig, &mockConsumerInstance) + require.NoError(t, err) + require.NoError(t, r.Start(context.Background(), componenttest.NewNopHost())) + checkLogs(t, params, r, &mockConsumerInstance, checkIfTestPassed) + case component.DataTypeTraces: + r, err := params.ReceiverFactory.CreateTracesReceiver(context.Background(), receivertest.NewNopCreateSettings(), params.ReceiverConfig, &mockConsumerInstance) + require.NoError(t, err) + require.NoError(t, r.Start(context.Background(), componenttest.NewNopHost())) + checkTraces(t, params, r, &mockConsumerInstance, checkIfTestPassed) + case component.DataTypeMetrics: + r, err := params.ReceiverFactory.CreateMetricsReceiver(context.Background(), receivertest.NewNopCreateSettings(), params.ReceiverConfig, &mockConsumerInstance) + require.NoError(t, err) + require.NoError(t, r.Start(context.Background(), componenttest.NewNopHost())) + checkMetrics(t, params, r, &mockConsumerInstance, checkIfTestPassed) + default: + require.FailNow(t, "must specify a valid DataType to test for") + } +} + +func checkMetrics(t *testing.T, params CheckConsumeContractParams, mockReceiver component.Component, + mockConsumer *mockConsumer, checkIfTestPassed func(*testing.T, int, requestCounter)) { + ctx := context.Background() + var exp exporter.Metrics + var err error + exp, err = params.ExporterFactory.CreateMetricsExporter(ctx, NewNopCreateSettings(), params.ExporterConfig) + require.NoError(t, err) + require.NotNil(t, exp) + + err = exp.Start(ctx, componenttest.NewNopHost()) + require.NoError(t, err) + + defer func(exp exporter.Metrics, ctx context.Context) { + err = exp.Shutdown(ctx) + require.NoError(t, err) + err = mockReceiver.Shutdown(ctx) + require.NoError(t, err) + mockConsumer.clear() + }(exp, ctx) + + for i := 0; i < params.NumberOfTestElements; i++ { + id := uniqueIDAttrVal(strconv.Itoa(i)) + data := createOneMetricWithID(id) + + err = exp.ConsumeMetrics(ctx, data) + } + + reqCounter := mockConsumer.getRequestCounter() + // The overall number of requests sent by exporter + fmt.Printf("Number of export tries: %d\n", reqCounter.total) + // Successfully delivered items + fmt.Printf("Total items received successfully: %d\n", reqCounter.success) + // Number of errors that happened + fmt.Printf("Number of permanent errors: %d\n", reqCounter.error.permanent) + fmt.Printf("Number of non-permanent errors: %d\n", reqCounter.error.nonpermanent) + + assert.EventuallyWithT(t, func(*assert.CollectT) { + checkIfTestPassed(t, params.NumberOfTestElements, *reqCounter) + }, 2*time.Second, 100*time.Millisecond) +} + +func checkTraces(t *testing.T, params CheckConsumeContractParams, mockReceiver component.Component, mockConsumer *mockConsumer, checkIfTestPassed func(*testing.T, int, requestCounter)) { + ctx := context.Background() + var exp exporter.Traces + var err error + exp, err = params.ExporterFactory.CreateTracesExporter(ctx, NewNopCreateSettings(), params.ExporterConfig) + require.NoError(t, err) + require.NotNil(t, exp) + + err = exp.Start(ctx, componenttest.NewNopHost()) + require.NoError(t, err) + + defer func(exp exporter.Traces, ctx context.Context) { + err = exp.Shutdown(ctx) + require.NoError(t, err) + err = mockReceiver.Shutdown(ctx) + require.NoError(t, err) + mockConsumer.clear() + }(exp, ctx) + + for i := 0; i < params.NumberOfTestElements; i++ { + id := uniqueIDAttrVal(strconv.Itoa(i)) + data := createOneTraceWithID(id) + + err = exp.ConsumeTraces(ctx, data) + } + + reqCounter := mockConsumer.getRequestCounter() + // The overall number of requests sent by exporter + fmt.Printf("Number of export tries: %d\n", reqCounter.total) + // Successfully delivered items + fmt.Printf("Total items received successfully: %d\n", reqCounter.success) + // Number of errors that happened + fmt.Printf("Number of permanent errors: %d\n", reqCounter.error.permanent) + fmt.Printf("Number of non-permanent errors: %d\n", reqCounter.error.nonpermanent) + + assert.EventuallyWithT(t, func(*assert.CollectT) { + checkIfTestPassed(t, params.NumberOfTestElements, *reqCounter) + }, 2*time.Second, 100*time.Millisecond) +} + +func checkLogs(t *testing.T, params CheckConsumeContractParams, mockReceiver component.Component, mockConsumer *mockConsumer, checkIfTestPassed func(*testing.T, int, requestCounter)) { + ctx := context.Background() + var exp exporter.Logs + var err error + exp, err = params.ExporterFactory.CreateLogsExporter(ctx, NewNopCreateSettings(), params.ExporterConfig) + require.NoError(t, err) + require.NotNil(t, exp) + + err = exp.Start(ctx, componenttest.NewNopHost()) + require.NoError(t, err) + + defer func(exp exporter.Logs, ctx context.Context) { + err = exp.Shutdown(ctx) + require.NoError(t, err) + err = mockReceiver.Shutdown(ctx) + require.NoError(t, err) + mockConsumer.clear() + }(exp, ctx) + + for i := 0; i < params.NumberOfTestElements; i++ { + id := uniqueIDAttrVal(strconv.Itoa(i)) + data := createOneLogWithID(id) + + err = exp.ConsumeLogs(ctx, data) + } + reqCounter := mockConsumer.getRequestCounter() + // The overall number of requests sent by exporter + fmt.Printf("Number of export tries: %d\n", reqCounter.total) + // Successfully delivered items + fmt.Printf("Total items received successfully: %d\n", reqCounter.success) + // Number of errors that happened + fmt.Printf("Number of permanent errors: %d\n", reqCounter.error.permanent) + fmt.Printf("Number of non-permanent errors: %d\n", reqCounter.error.nonpermanent) + + assert.EventuallyWithT(t, func(*assert.CollectT) { + checkIfTestPassed(t, params.NumberOfTestElements, *reqCounter) + }, 2*time.Second, 100*time.Millisecond) +} + +// Test is successful if all the elements were received successfully and no error was returned +func alwaysSucceedsPassed(t *testing.T, allRecordsNumber int, reqCounter requestCounter) { + require.Equal(t, allRecordsNumber, reqCounter.success) + require.Equal(t, reqCounter.total, allRecordsNumber) + require.Equal(t, reqCounter.error.nonpermanent, 0) + require.Equal(t, reqCounter.error.permanent, 0) +} + +// Test is successful if all the elements were retried on non-permanent errors +func randomNonPermanentErrorConsumeDecisionPassed(t *testing.T, allRecordsNumber int, reqCounter requestCounter) { + // more or equal tries than successes + require.GreaterOrEqual(t, reqCounter.total, reqCounter.success) + // it is retried on every error + require.Equal(t, reqCounter.total-reqCounter.error.nonpermanent, reqCounter.success) + require.Equal(t, allRecordsNumber+reqCounter.error.nonpermanent, reqCounter.total) +} + +// Test is successful if the calls are not retried on permanent errors +func randomPermanentErrorConsumeDecisionPassed(t *testing.T, allRecordsNumber int, reqCounter requestCounter) { + require.Equal(t, allRecordsNumber-reqCounter.error.permanent, reqCounter.success) + require.Equal(t, reqCounter.total, allRecordsNumber) +} + +// Test is successful if the calls are not retried on permanent errors +func randomErrorConsumeDecisionPassed(t *testing.T, allRecordsNumber int, reqCounter requestCounter) { + require.Equal(t, allRecordsNumber-reqCounter.error.permanent, reqCounter.success) + require.Equal(t, reqCounter.total, allRecordsNumber+reqCounter.error.nonpermanent) +} + +func createOneLogWithID(id uniqueIDAttrVal) plog.Logs { + data := plog.NewLogs() + data.ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty().Attributes().PutStr( + uniqueIDAttrName, + string(id), + ) + return data +} + +func createOneTraceWithID(id uniqueIDAttrVal) ptrace.Traces { + data := ptrace.NewTraces() + data.ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty().Attributes().PutStr( + uniqueIDAttrName, + string(id), + ) + return data +} + +func createOneMetricWithID(id uniqueIDAttrVal) pmetric.Metrics { + data := pmetric.NewMetrics() + data.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptyHistogram(). + DataPoints().AppendEmpty().Attributes().PutStr(uniqueIDAttrName, string(id)) + return data +} diff --git a/exporter/exportertest/contract_checker_test.go b/exporter/exportertest/contract_checker_test.go new file mode 100644 index 00000000000..7b0a6d5abb3 --- /dev/null +++ b/exporter/exportertest/contract_checker_test.go @@ -0,0 +1,143 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exportertest + +import ( + "context" + "testing" + "time" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/configretry" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exporterhelper" + "go.opentelemetry.io/collector/receiver" +) + +// retryConfig is a configuration to quickly retry failed exports. +var retryConfig = func() configretry.BackOffConfig { + c := configretry.NewDefaultBackOffConfig() + c.InitialInterval = time.Millisecond + return c +}() + +// mockReceiver is a receiver with pass-through consumers. +type mockReceiver struct { + component.StartFunc + component.ShutdownFunc + consumer.Traces + consumer.Metrics + consumer.Logs +} + +// mockExporterFactory is a factory to create exporters sending data to the mockReceiver. +type mockExporterFactory struct { + mr *mockReceiver + component.StartFunc + component.ShutdownFunc +} + +func (mef *mockExporterFactory) createMockTracesExporter( + ctx context.Context, + set exporter.CreateSettings, + cfg component.Config, +) (exporter.Traces, error) { + return exporterhelper.NewTracesExporter(ctx, set, cfg, + mef.mr.Traces.ConsumeTraces, + exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), + exporterhelper.WithRetry(retryConfig), + ) +} + +func (mef *mockExporterFactory) createMockMetricsExporter( + ctx context.Context, + set exporter.CreateSettings, + cfg component.Config, +) (exporter.Metrics, error) { + return exporterhelper.NewMetricsExporter(ctx, set, cfg, + mef.mr.Metrics.ConsumeMetrics, + exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), + exporterhelper.WithRetry(retryConfig), + ) +} + +func (mef *mockExporterFactory) createMockLogsExporter( + ctx context.Context, + set exporter.CreateSettings, + cfg component.Config, +) (exporter.Logs, error) { + return exporterhelper.NewLogsExporter(ctx, set, cfg, + mef.mr.Logs.ConsumeLogs, + exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), + exporterhelper.WithRetry(retryConfig), + ) +} + +func newMockExporterFactory(mr *mockReceiver) exporter.Factory { + mef := &mockExporterFactory{mr: mr} + return exporter.NewFactory( + component.MustNewType("pass_through_exporter"), + func() component.Config { return &nopConfig{} }, + exporter.WithTraces(mef.createMockTracesExporter, component.StabilityLevelBeta), + exporter.WithMetrics(mef.createMockMetricsExporter, component.StabilityLevelBeta), + exporter.WithLogs(mef.createMockLogsExporter, component.StabilityLevelBeta), + ) +} + +func newMockReceiverFactory(mr *mockReceiver) receiver.Factory { + return receiver.NewFactory(component.MustNewType("pass_through_receiver"), + func() component.Config { return &nopConfig{} }, + receiver.WithTraces(func(_ context.Context, _ receiver.CreateSettings, _ component.Config, c consumer.Traces) (receiver.Traces, error) { + mr.Traces = c + return mr, nil + }, component.StabilityLevelStable), + receiver.WithMetrics(func(_ context.Context, _ receiver.CreateSettings, _ component.Config, c consumer.Metrics) (receiver.Metrics, error) { + mr.Metrics = c + return mr, nil + }, component.StabilityLevelStable), + receiver.WithLogs(func(_ context.Context, _ receiver.CreateSettings, _ component.Config, c consumer.Logs) (receiver.Logs, error) { + mr.Logs = c + return mr, nil + }, component.StabilityLevelStable), + ) +} + +func TestCheckConsumeContractLogs(t *testing.T) { + mr := &mockReceiver{} + params := CheckConsumeContractParams{ + T: t, + ExporterFactory: newMockExporterFactory(mr), + DataType: component.DataTypeLogs, + ExporterConfig: nopConfig{}, + NumberOfTestElements: 10, + ReceiverFactory: newMockReceiverFactory(mr), + } + + CheckConsumeContract(params) +} + +func TestCheckConsumeContractMetrics(t *testing.T) { + mr := &mockReceiver{} + CheckConsumeContract(CheckConsumeContractParams{ + T: t, + ExporterFactory: newMockExporterFactory(mr), + DataType: component.DataTypeMetrics, // Change to the appropriate data type + ExporterConfig: nopConfig{}, + NumberOfTestElements: 10, + ReceiverFactory: newMockReceiverFactory(mr), + }) +} + +func TestCheckConsumeContractTraces(t *testing.T) { + mr := &mockReceiver{} + CheckConsumeContract(CheckConsumeContractParams{ + T: t, + ExporterFactory: newMockExporterFactory(mr), + DataType: component.DataTypeTraces, + ExporterConfig: nopConfig{}, + NumberOfTestElements: 10, + ReceiverFactory: newMockReceiverFactory(mr), + }) +} diff --git a/exporter/exportertest/mock_consumer.go b/exporter/exportertest/mock_consumer.go new file mode 100644 index 00000000000..b513e524735 --- /dev/null +++ b/exporter/exportertest/mock_consumer.go @@ -0,0 +1,212 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 +package exportertest // import "go.opentelemetry.io/collector/exporter/exportertest" + +import ( + "context" + "fmt" + "math/rand" + "sync" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumererror" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" +) + +var errNonPermanent = status.Error(codes.DeadlineExceeded, "non Permanent error") +var errPermanent = status.Error(codes.Internal, "Permanent error") + +// // randomNonPermanentErrorConsumeDecision is a decision function that succeeds approximately +// // half of the time and fails with a non-permanent error the rest of the time. +func randomNonPermanentErrorConsumeDecision() error { + if rand.Float32() < 0.5 { + return errNonPermanent + } + return nil +} + +// randomPermanentErrorConsumeDecision is a decision function that succeeds approximately +// half of the time and fails with a permanent error the rest of the time. +func randomPermanentErrorConsumeDecision() error { + if rand.Float32() < 0.5 { + return consumererror.NewPermanent(errPermanent) + } + return nil +} + +// randomErrorsConsumeDecision is a decision function that succeeds approximately +// a third of the time, fails with a permanent error the third of the time and fails with +// a non-permanent error the rest of the time. +func randomErrorsConsumeDecision() error { + r := rand.Float64() + third := 1.0 / 3.0 + if r < third { + return consumererror.NewPermanent(errPermanent) + } + if r < 2*third { + return errNonPermanent + } + return nil +} + +type mockConsumer struct { + consumer.Traces + consumer.Logs + consumer.Metrics + reqCounter *requestCounter + mux sync.Mutex + exportErrorFunction func() error + receivedTraces []ptrace.Traces + receivedMetrics []pmetric.Metrics + receivedLogs []plog.Logs +} + +func newMockConsumer(decisionFunc func() error) mockConsumer { + return mockConsumer{ + reqCounter: newRequestCounter(), + mux: sync.Mutex{}, + exportErrorFunction: decisionFunc, + receivedTraces: nil, + receivedMetrics: nil, + receivedLogs: nil, + } +} + +func (r *mockConsumer) ConsumeLogs(_ context.Context, ld plog.Logs) error { + r.mux.Lock() + defer r.mux.Unlock() + r.reqCounter.total++ + generatedError := r.exportErrorFunction() + if generatedError != nil { + r.processError(generatedError) + return generatedError + } + r.reqCounter.success++ + r.receivedLogs = append(r.receivedLogs, ld) + return nil +} + +func (r *mockConsumer) ConsumeTraces(_ context.Context, td ptrace.Traces) error { + r.mux.Lock() + defer r.mux.Unlock() + r.reqCounter.total++ + generatedError := r.exportErrorFunction() + if generatedError != nil { + r.processError(generatedError) + return generatedError + } + r.reqCounter.success++ + r.receivedTraces = append(r.receivedTraces, td) + return nil +} + +func (r *mockConsumer) ConsumeMetrics(_ context.Context, md pmetric.Metrics) error { + r.mux.Lock() + defer r.mux.Unlock() + r.reqCounter.total++ + generatedError := r.exportErrorFunction() + if generatedError != nil { + r.processError(generatedError) + return generatedError + } + r.reqCounter.success++ + r.receivedMetrics = append(r.receivedMetrics, md) + return nil +} + +func (r *mockConsumer) Capabilities() consumer.Capabilities { + return consumer.Capabilities{} +} + +func (r *mockConsumer) processError(err error) { + if consumererror.IsPermanent(err) { + r.reqCounter.error.permanent++ + } else { + r.reqCounter.error.nonpermanent++ + } +} + +func (r *mockConsumer) clear() { + r.mux.Lock() + defer r.mux.Unlock() + r.reqCounter = newRequestCounter() +} + +func (r *mockConsumer) getRequestCounter() *requestCounter { + return r.reqCounter +} + +type requestCounter struct { + success int + error errorCounter + total int +} + +type errorCounter struct { + permanent int + nonpermanent int +} + +func newErrorCounter() errorCounter { + return errorCounter{ + permanent: 0, + nonpermanent: 0, + } +} + +func newRequestCounter() *requestCounter { + return &requestCounter{ + success: 0, + error: newErrorCounter(), + total: 0, + } +} + +func idFromLogs(data plog.Logs) (string, error) { + var logID string + rss := data.ResourceLogs() + key, exists := rss.At(0).ScopeLogs().At(0).LogRecords().At(0).Attributes().Get(uniqueIDAttrName) + if !exists { + return "", fmt.Errorf("invalid data element, attribute %q is missing", uniqueIDAttrName) + } + if key.Type() != pcommon.ValueTypeStr { + return "", fmt.Errorf("invalid data element, attribute %q is wrong type %v", uniqueIDAttrName, key.Type()) + } + logID = key.Str() + return logID, nil +} + +func idFromTraces(data ptrace.Traces) (string, error) { + var traceID string + rss := data.ResourceSpans() + key, exists := rss.At(0).ScopeSpans().At(0).Spans().At(0).Attributes().Get(uniqueIDAttrName) + if !exists { + return "", fmt.Errorf("invalid data element, attribute %q is missing", uniqueIDAttrName) + } + if key.Type() != pcommon.ValueTypeStr { + return "", fmt.Errorf("invalid data element, attribute %q is wrong type %v", uniqueIDAttrName, key.Type()) + } + traceID = key.Str() + return traceID, nil +} + +func idFromMetrics(data pmetric.Metrics) (string, error) { + var metricID string + rss := data.ResourceMetrics() + key, exists := rss.At(0).ScopeMetrics().At(0).Metrics().At(0).Histogram().DataPoints().At(0).Attributes().Get( + uniqueIDAttrName) + if !exists { + return "", fmt.Errorf("invalid data element, attribute %q is missing", uniqueIDAttrName) + } + if key.Type() != pcommon.ValueTypeStr { + return "", fmt.Errorf("invalid data element, attribute %q is wrong type %v", uniqueIDAttrName, key.Type()) + } + metricID = key.Str() + return metricID, nil +} diff --git a/exporter/exportertest/mock_consumer_test.go b/exporter/exportertest/mock_consumer_test.go new file mode 100644 index 00000000000..63eec26d7fd --- /dev/null +++ b/exporter/exportertest/mock_consumer_test.go @@ -0,0 +1,256 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exportertest + +import ( + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" +) + +func createLog(id string) plog.Logs { + validData := plog.NewLogs() + validData.ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty().Attributes().PutStr( + uniqueIDAttrName, + id, + ) + return validData +} + +func createTrace(id string) ptrace.Traces { + validData := ptrace.NewTraces() + validData.ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty().Attributes().PutStr( + uniqueIDAttrName, + id, + ) + return validData +} + +func createMetric(id string) pmetric.Metrics { + validData := pmetric.NewMetrics() + validData.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptyHistogram().DataPoints().AppendEmpty().Attributes().PutStr(uniqueIDAttrName, id) + return validData +} + +func TestIDFromMetrics(t *testing.T) { + // Test case 1: Valid data + id := "metric_id" + validData := createMetric(id) + metricID, err := idFromMetrics(validData) + assert.Equal(t, metricID, id) + assert.NoError(t, err) + + // Test case 2: Missing uniqueIDAttrName attribute + invalidData := pmetric.NewMetrics() // Create an invalid pmetric.Metrics object with missing attribute + invalidData.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptyHistogram().DataPoints().AppendEmpty().Attributes() + _, err = idFromMetrics(invalidData) + assert.Error(t, err) + assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is missing", uniqueIDAttrName)) + + // Test case 3: Wrong attribute type + var intID int64 = 12 + wrongAttribute := pmetric.NewMetrics() // Create a valid pmetric.Metrics object + wrongAttribute.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty(). + SetEmptyHistogram().DataPoints().AppendEmpty().Attributes().PutInt(uniqueIDAttrName, intID) + _, err = idFromMetrics(wrongAttribute) + assert.Error(t, err) + assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is wrong type Int", uniqueIDAttrName)) +} + +func TestIDFromTraces(t *testing.T) { + // Test case 1: Valid data + id := "trace_id" + validData := createTrace(id) + traceID, err := idFromTraces(validData) + assert.Equal(t, traceID, id) + assert.NoError(t, err) + + // Test case 2: Missing uniqueIDAttrName attribute + invalidData := ptrace.NewTraces() + invalidData.ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty().Attributes() + _, err = idFromTraces(invalidData) + assert.Error(t, err) + assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is missing", uniqueIDAttrName)) + + // Test case 3: Wrong attribute type + var intID int64 = 12 + wrongAttribute := ptrace.NewTraces() + wrongAttribute.ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty().Attributes(). + PutInt(uniqueIDAttrName, intID) + _, err = idFromTraces(wrongAttribute) + assert.Error(t, err) + assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is wrong type Int", uniqueIDAttrName)) +} + +func TestIDFromLogs(t *testing.T) { + // Test case 1: Valid data + id := "log_id" + validData := createLog(id) + logID, err := idFromLogs(validData) + assert.Equal(t, logID, id) + assert.NoError(t, err) + + // Test case 2: Missing uniqueIDAttrName attribute + invalidData := plog.NewLogs() + invalidData.ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty().Attributes() + _, err = idFromLogs(invalidData) + assert.Error(t, err) + assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is missing", uniqueIDAttrName)) + + // Test case 3: Wrong attribute type + var intID int64 = 12 + wrongAttribute := plog.NewLogs() // Create a valid plog.Metrics object + wrongAttribute.ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty().Attributes(). + PutInt(uniqueIDAttrName, intID) + _, err = idFromLogs(wrongAttribute) + assert.Error(t, err) + assert.Equal(t, err.Error(), fmt.Sprintf("invalid data element, attribute %q is wrong type Int", uniqueIDAttrName)) +} + +func returnNonPermanentError() error { + return errNonPermanent +} + +func returnPermanentError() error { + return errPermanent +} + +func TestConsumeLogsNonPermanent(t *testing.T) { + mc := newMockConsumer(returnNonPermanentError) + validData := createLog("logId") + err := mc.ConsumeLogs(context.Background(), validData) + if err != nil { + return + } + assert.Equal(t, mc.reqCounter.error.nonpermanent, 1) + assert.Equal(t, mc.reqCounter.error.permanent, 0) + assert.Equal(t, mc.reqCounter.success, 0) + assert.Equal(t, mc.reqCounter.total, 1) + +} + +func TestConsumeLogsPermanent(t *testing.T) { + + mc := newMockConsumer(returnPermanentError) + validData := createLog("logId") + err := mc.ConsumeLogs(context.Background(), validData) + if err != nil { + return + } + assert.Equal(t, mc.reqCounter.error.nonpermanent, 0) + assert.Equal(t, mc.reqCounter.error.permanent, 1) + assert.Equal(t, mc.reqCounter.success, 0) + assert.Equal(t, mc.reqCounter.total, 1) + +} + +func TestConsumeLogsSuccess(t *testing.T) { + mc := newMockConsumer(func() error { return nil }) + validData := createLog("logId") + err := mc.ConsumeLogs(context.Background(), validData) + if err != nil { + return + } + assert.Equal(t, mc.reqCounter.error.nonpermanent, 0) + assert.Equal(t, mc.reqCounter.error.permanent, 0) + assert.Equal(t, mc.reqCounter.success, 1) + assert.Equal(t, mc.reqCounter.total, 1) + +} + +func TestConsumeTracesNonPermanent(t *testing.T) { + mc := newMockConsumer(returnNonPermanentError) + validData := createTrace("traceId") + err := mc.ConsumeTraces(context.Background(), validData) + if err != nil { + return + } + assert.Equal(t, mc.reqCounter.error.nonpermanent, 1) + assert.Equal(t, mc.reqCounter.error.permanent, 0) + assert.Equal(t, mc.reqCounter.success, 0) + assert.Equal(t, mc.reqCounter.total, 1) + +} + +func TestConsumeTracesPermanent(t *testing.T) { + + mc := newMockConsumer(returnPermanentError) + validData := createTrace("traceId") + err := mc.ConsumeTraces(context.Background(), validData) + if err != nil { + return + } + assert.Equal(t, mc.reqCounter.error.nonpermanent, 0) + assert.Equal(t, mc.reqCounter.error.permanent, 1) + assert.Equal(t, mc.reqCounter.success, 0) + assert.Equal(t, mc.reqCounter.total, 1) + +} + +func TestConsumeTracesSuccess(t *testing.T) { + mc := newMockConsumer(func() error { return nil }) + validData := createTrace("traceId") + err := mc.ConsumeTraces(context.Background(), validData) + if err != nil { + return + } + assert.Equal(t, mc.reqCounter.error.nonpermanent, 0) + assert.Equal(t, mc.reqCounter.error.permanent, 0) + assert.Equal(t, mc.reqCounter.success, 1) + assert.Equal(t, mc.reqCounter.total, 1) + +} +func TestConsumeMetricsNonPermanent(t *testing.T) { + mc := newMockConsumer(returnNonPermanentError) + validData := createMetric("metricId") + err := mc.ConsumeMetrics(context.Background(), validData) + if err != nil { + return + } + assert.Equal(t, mc.reqCounter.error.nonpermanent, 1) + assert.Equal(t, mc.reqCounter.error.permanent, 0) + assert.Equal(t, mc.reqCounter.success, 0) + assert.Equal(t, mc.reqCounter.total, 1) + +} + +func TestConsumeMetricsPermanent(t *testing.T) { + mc := newMockConsumer(returnPermanentError) + validData := createMetric("metricId") + err := mc.ConsumeMetrics(context.Background(), validData) + if err != nil { + return + } + assert.Equal(t, mc.reqCounter.error.nonpermanent, 0) + assert.Equal(t, mc.reqCounter.error.permanent, 1) + assert.Equal(t, mc.reqCounter.success, 0) + assert.Equal(t, mc.reqCounter.total, 1) + +} + +func TestConsumeMetricsSuccess(t *testing.T) { + mc := newMockConsumer(func() error { return nil }) + validData := createMetric("metricId") + err := mc.ConsumeMetrics(context.Background(), validData) + if err != nil { + return + } + assert.Equal(t, mc.reqCounter.error.nonpermanent, 0) + assert.Equal(t, mc.reqCounter.error.permanent, 0) + assert.Equal(t, mc.reqCounter.success, 1) + assert.Equal(t, mc.reqCounter.total, 1) + +} + +func TestCapabilites(t *testing.T) { + mc := newMockConsumer(func() error { return nil }) + assert.Equal(t, mc.Capabilities(), consumer.Capabilities{}) +} diff --git a/exporter/exportertest/nop_exporter.go b/exporter/exportertest/nop_exporter.go index 676e8e04d96..e7e9f350331 100644 --- a/exporter/exportertest/nop_exporter.go +++ b/exporter/exportertest/nop_exporter.go @@ -12,11 +12,12 @@ import ( "go.opentelemetry.io/collector/exporter" ) -const typeStr = "nop" +var nopType = component.MustNewType("nop") // NewNopCreateSettings returns a new nop settings for Create*Exporter functions. func NewNopCreateSettings() exporter.CreateSettings { return exporter.CreateSettings{ + ID: component.NewID(nopType), TelemetrySettings: componenttest.NewNopTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo(), } @@ -25,7 +26,7 @@ func NewNopCreateSettings() exporter.CreateSettings { // NewNopFactory returns an exporter.Factory that constructs nop exporters. func NewNopFactory() exporter.Factory { return exporter.NewFactory( - "nop", + nopType, func() component.Config { return &nopConfig{} }, exporter.WithTraces(createTracesExporter, component.StabilityLevelStable), exporter.WithMetrics(createMetricsExporter, component.StabilityLevelStable), @@ -62,14 +63,6 @@ type nopExporter struct { func NewNopBuilder() *exporter.Builder { nopFactory := NewNopFactory() return exporter.NewBuilder( - map[component.ID]component.Config{component.NewID(typeStr): nopFactory.CreateDefaultConfig()}, - map[component.Type]exporter.Factory{typeStr: nopFactory}) -} - -func NewCreateSettings(id component.ID, set component.TelemetrySettings) exporter.CreateSettings { - return exporter.CreateSettings{ - ID: id, - TelemetrySettings: set, - BuildInfo: component.NewDefaultBuildInfo(), - } + map[component.ID]component.Config{component.NewID(nopType): nopFactory.CreateDefaultConfig()}, + map[component.Type]exporter.Factory{nopType: nopFactory}) } diff --git a/exporter/exportertest/nop_exporter_test.go b/exporter/exportertest/nop_exporter_test.go index ed7a36bc062..6ae95efc08d 100644 --- a/exporter/exportertest/nop_exporter_test.go +++ b/exporter/exportertest/nop_exporter_test.go @@ -20,7 +20,7 @@ import ( func TestNewNopFactory(t *testing.T) { factory := NewNopFactory() require.NotNil(t, factory) - assert.Equal(t, component.Type("nop"), factory.Type()) + assert.Equal(t, component.MustNewType("nop"), factory.Type()) cfg := factory.CreateDefaultConfig() assert.Equal(t, &nopConfig{}, cfg) @@ -50,7 +50,7 @@ func TestNewNopBuilder(t *testing.T) { factory := NewNopFactory() cfg := factory.CreateDefaultConfig() set := NewNopCreateSettings() - set.ID = component.NewID(typeStr) + set.ID = component.NewID(nopType) traces, err := factory.CreateTracesExporter(context.Background(), set, cfg) require.NoError(t, err) diff --git a/exporter/exportertest/package_test.go b/exporter/exportertest/package_test.go new file mode 100644 index 00000000000..8fa8a72b85f --- /dev/null +++ b/exporter/exportertest/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exportertest + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/exporter/go.mod b/exporter/go.mod index 7800ed9ab57..e353c8a8bd8 100644 --- a/exporter/go.mod +++ b/exporter/go.mod @@ -1,66 +1,58 @@ module go.opentelemetry.io/collector/exporter -go 1.20 +go 1.21 require ( github.com/cenkalti/backoff/v4 v4.2.1 github.com/stretchr/testify v1.8.4 - go.opencensus.io v0.24.0 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 - go.opentelemetry.io/collector/consumer v0.85.0 - go.opentelemetry.io/collector/extension v0.85.0 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/otel v1.18.0 - go.opentelemetry.io/otel/metric v1.18.0 - go.opentelemetry.io/otel/sdk v1.18.0 - go.opentelemetry.io/otel/sdk/metric v0.41.0 - go.opentelemetry.io/otel/trace v1.18.0 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/configretry v0.96.0 + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 + go.opentelemetry.io/collector/consumer v0.96.0 + go.opentelemetry.io/collector/extension v0.96.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/collector/receiver v0.96.0 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 - go.uber.org/zap v1.26.0 - golang.org/x/sys v0.12.0 + go.uber.org/zap v1.27.0 + golang.org/x/sys v0.17.0 + google.golang.org/grpc v1.62.0 ) require ( - contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect - github.com/prometheus/statsd_exporter v0.22.7 // indirect - go.opentelemetry.io/collector/confmap v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/processor v0.85.0 // indirect - go.opentelemetry.io/collector/receiver v0.85.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector/confmap v0.96.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -74,24 +66,14 @@ replace go.opentelemetry.io/collector/consumer => ../consumer replace go.opentelemetry.io/collector/extension => ../extension -replace go.opentelemetry.io/collector/extension/zpagesextension => ../extension/zpagesextension - replace go.opentelemetry.io/collector/featuregate => ../featuregate replace go.opentelemetry.io/collector/pdata => ../pdata -replace go.opentelemetry.io/collector/processor => ../processor - replace go.opentelemetry.io/collector/receiver => ../receiver -replace go.opentelemetry.io/collector/semconv => ../semconv - retract v0.76.0 // Depends on retracted pdata v1.0.0-rc10 module -replace go.opentelemetry.io/collector/connector => ../connector - -replace go.opentelemetry.io/collector/config/confignet => ../config/confignet +replace go.opentelemetry.io/collector/config/configretry => ../config/configretry replace go.opentelemetry.io/collector/config/configtelemetry => ../config/configtelemetry - -replace go.opentelemetry.io/collector/service => ../service diff --git a/exporter/go.sum b/exporter/go.sum index 1e7d2abfab4..dbdb92fd3bb 100644 --- a/exporter/go.sum +++ b/exporter/go.sum @@ -1,583 +1,128 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/exporter/internal/common/package_test.go b/exporter/internal/common/package_test.go new file mode 100644 index 00000000000..abc80d8f317 --- /dev/null +++ b/exporter/internal/common/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package common + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/exporter/internal/experr/err.go b/exporter/internal/experr/err.go new file mode 100644 index 00000000000..6bff64b162d --- /dev/null +++ b/exporter/internal/experr/err.go @@ -0,0 +1,27 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package experr // import "go.opentelemetry.io/collector/exporter/internal/experr" + +import "errors" + +type shutdownErr struct { + err error +} + +func NewShutdownErr(err error) error { + return shutdownErr{err: err} +} + +func (s shutdownErr) Error() string { + return "interrupted due to shutdown: " + s.err.Error() +} + +func (s shutdownErr) Unwrap() error { + return s.err +} + +func IsShutdownErr(err error) bool { + var sdErr shutdownErr + return errors.As(err, &sdErr) +} diff --git a/exporter/internal/experr/err_test.go b/exporter/internal/experr/err_test.go new file mode 100644 index 00000000000..ac0580025e5 --- /dev/null +++ b/exporter/internal/experr/err_test.go @@ -0,0 +1,24 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package experr + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewShutdownErr(t *testing.T) { + err := NewShutdownErr(errors.New("some error")) + assert.Equal(t, "interrupted due to shutdown: some error", err.Error()) +} + +func TestIsShutdownErr(t *testing.T) { + err := errors.New("testError") + require.False(t, IsShutdownErr(err)) + err = NewShutdownErr(err) + require.True(t, IsShutdownErr(err)) +} diff --git a/exporter/internal/otlptext/known_sync_error.go b/exporter/internal/otlptext/known_sync_error.go index 06d5913ad2b..3745fea0e79 100644 --- a/exporter/internal/otlptext/known_sync_error.go +++ b/exporter/internal/otlptext/known_sync_error.go @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 //go:build linux || darwin -// +build linux darwin package otlptext // import "go.opentelemetry.io/collector/exporter/internal/otlptext" diff --git a/exporter/internal/otlptext/known_sync_error_other.go b/exporter/internal/otlptext/known_sync_error_other.go index ab8a343f877..6c9f10f8ad0 100644 --- a/exporter/internal/otlptext/known_sync_error_other.go +++ b/exporter/internal/otlptext/known_sync_error_other.go @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 //go:build !linux && !darwin && !windows -// +build !linux,!darwin,!windows package otlptext // import "go.opentelemetry.io/collector/exporter/internal/otlptext" diff --git a/exporter/internal/otlptext/known_sync_error_windows.go b/exporter/internal/otlptext/known_sync_error_windows.go index 780f9e65350..b7e0dc472d7 100644 --- a/exporter/internal/otlptext/known_sync_error_windows.go +++ b/exporter/internal/otlptext/known_sync_error_windows.go @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 //go:build windows -// +build windows package otlptext // import "go.opentelemetry.io/collector/exporter/internal/otlptext" diff --git a/exporter/internal/otlptext/package_test.go b/exporter/internal/otlptext/package_test.go new file mode 100644 index 00000000000..bdffd4818e1 --- /dev/null +++ b/exporter/internal/otlptext/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package otlptext + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/exporter/internal/queue/bounded_memory_queue.go b/exporter/internal/queue/bounded_memory_queue.go new file mode 100644 index 00000000000..9f85e8496bf --- /dev/null +++ b/exporter/internal/queue/bounded_memory_queue.go @@ -0,0 +1,70 @@ +// Copyright The OpenTelemetry Authors +// Copyright (c) 2019 The Jaeger Authors. +// Copyright (c) 2017 Uber Technologies, Inc. +// SPDX-License-Identifier: Apache-2.0 + +package queue // import "go.opentelemetry.io/collector/exporter/internal/queue" + +import ( + "context" + + "go.opentelemetry.io/collector/component" +) + +// boundedMemoryQueue implements a producer-consumer exchange similar to a ring buffer queue, +// where the queue is bounded and if it fills up due to slow consumers, the new items written by +// the producer are dropped. +type boundedMemoryQueue[T any] struct { + component.StartFunc + *queueCapacityLimiter[T] + items chan queueRequest[T] +} + +// MemoryQueueSettings defines internal parameters for boundedMemoryQueue creation. +type MemoryQueueSettings[T any] struct { + Sizer Sizer[T] + Capacity int +} + +// NewBoundedMemoryQueue constructs the new queue of specified capacity, and with an optional +// callback for dropped items (e.g. useful to emit metrics). +func NewBoundedMemoryQueue[T any](set MemoryQueueSettings[T]) Queue[T] { + return &boundedMemoryQueue[T]{ + queueCapacityLimiter: newQueueCapacityLimiter[T](set.Sizer, set.Capacity), + items: make(chan queueRequest[T], set.Capacity), + } +} + +// Offer is used by the producer to submit new item to the queue. Calling this method on a stopped queue will panic. +func (q *boundedMemoryQueue[T]) Offer(ctx context.Context, req T) error { + if !q.queueCapacityLimiter.claim(req) { + return ErrQueueIsFull + } + q.items <- queueRequest[T]{ctx: ctx, req: req} + return nil +} + +// Consume applies the provided function on the head of queue. +// The call blocks until there is an item available or the queue is stopped. +// The function returns true when an item is consumed or false if the queue is stopped and emptied. +func (q *boundedMemoryQueue[T]) Consume(consumeFunc func(context.Context, T) error) bool { + item, ok := <-q.items + if !ok { + return false + } + q.queueCapacityLimiter.release(item.req) + // the memory queue doesn't handle consume errors + _ = consumeFunc(item.ctx, item.req) + return true +} + +// Shutdown closes the queue channel to initiate draining of the queue. +func (q *boundedMemoryQueue[T]) Shutdown(context.Context) error { + close(q.items) + return nil +} + +type queueRequest[T any] struct { + req T + ctx context.Context +} diff --git a/exporter/internal/queue/bounded_memory_queue_test.go b/exporter/internal/queue/bounded_memory_queue_test.go new file mode 100644 index 00000000000..d861893eda9 --- /dev/null +++ b/exporter/internal/queue/bounded_memory_queue_test.go @@ -0,0 +1,158 @@ +// Copyright The OpenTelemetry Authors +// Copyright (c) 2019 The Jaeger Authors. +// Copyright (c) 2017 Uber Technologies, Inc. +// SPDX-License-Identifier: Apache-2.0 + +package queue + +import ( + "context" + "strconv" + "sync" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component/componenttest" +) + +// In this test we run a queue with capacity 1 and a single consumer. +// We want to test the overflow behavior, so we block the consumer +// by holding a startLock before submitting items to the queue. +func TestBoundedQueue(t *testing.T) { + q := NewBoundedMemoryQueue[string](MemoryQueueSettings[string]{Sizer: &RequestSizer[string]{}, Capacity: 1}) + + assert.NoError(t, q.Offer(context.Background(), "a")) + + numConsumed := 0 + assert.True(t, q.Consume(func(_ context.Context, item string) error { + assert.Equal(t, "a", item) + numConsumed++ + return nil + })) + assert.Equal(t, 1, numConsumed) + assert.Equal(t, 0, q.Size()) + + // produce two more items. The first one should be accepted, but not consumed. + assert.NoError(t, q.Offer(context.Background(), "b")) + assert.Equal(t, 1, q.Size()) + + // the second should be rejected since the queue is full + assert.ErrorIs(t, q.Offer(context.Background(), "c"), ErrQueueIsFull) + assert.Equal(t, 1, q.Size()) + + assert.True(t, q.Consume(func(_ context.Context, item string) error { + assert.Equal(t, "b", item) + numConsumed++ + return nil + })) + assert.Equal(t, 2, numConsumed) + + for _, toAddItem := range []string{"d", "e", "f"} { + assert.NoError(t, q.Offer(context.Background(), toAddItem)) + assert.True(t, q.Consume(func(_ context.Context, item string) error { + assert.Equal(t, toAddItem, item) + numConsumed++ + return nil + })) + } + assert.Equal(t, 5, numConsumed) + assert.NoError(t, q.Shutdown(context.Background())) + assert.False(t, q.Consume(func(_ context.Context, item string) error { + panic(item) + })) +} + +// In this test we run a queue with many items and a slow consumer. +// When the queue is stopped, the remaining items should be processed. +// Due to the way q.Stop() waits for all consumers to finish, the +// same lock strategy use above will not work, as calling Unlock +// only after Stop will mean the consumers are still locked while +// trying to perform the final consumptions. +func TestShutdownWhileNotEmpty(t *testing.T) { + q := NewBoundedMemoryQueue[string](MemoryQueueSettings[string]{Sizer: &RequestSizer[string]{}, Capacity: 1000}) + + assert.NoError(t, q.Start(context.Background(), componenttest.NewNopHost())) + for i := 0; i < 10; i++ { + assert.NoError(t, q.Offer(context.Background(), strconv.FormatInt(int64(i), 10))) + } + assert.NoError(t, q.Shutdown(context.Background())) + + assert.Equal(t, 10, q.Size()) + numConsumed := 0 + for i := 0; i < 10; i++ { + assert.True(t, q.Consume(func(_ context.Context, item string) error { + assert.Equal(t, strconv.FormatInt(int64(i), 10), item) + numConsumed++ + return nil + })) + } + assert.Equal(t, 10, numConsumed) + assert.Equal(t, 0, q.Size()) + + assert.False(t, q.Consume(func(_ context.Context, item string) error { + panic(item) + })) +} + +func Benchmark_QueueUsage_1000_requests(b *testing.B) { + benchmarkQueueUsage(b, &RequestSizer[fakeReq]{}, 1000) +} + +func Benchmark_QueueUsage_100000_requests(b *testing.B) { + benchmarkQueueUsage(b, &RequestSizer[fakeReq]{}, 100000) +} + +func Benchmark_QueueUsage_10000_items(b *testing.B) { + // each request has 10 items: 1000 requests = 10000 items + benchmarkQueueUsage(b, &ItemsSizer[fakeReq]{}, 1000) +} + +func Benchmark_QueueUsage_1M_items(b *testing.B) { + // each request has 10 items: 100000 requests = 1M items + benchmarkQueueUsage(b, &ItemsSizer[fakeReq]{}, 100000) +} + +func TestQueueUsage(t *testing.T) { + t.Run("requests_based", func(t *testing.T) { + queueUsage(t, &RequestSizer[fakeReq]{}, 10) + }) + t.Run("items_based", func(t *testing.T) { + queueUsage(t, &ItemsSizer[fakeReq]{}, 10) + }) +} + +func benchmarkQueueUsage(b *testing.B, sizer Sizer[fakeReq], requestsCount int) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + queueUsage(b, sizer, requestsCount) + } +} + +func queueUsage(tb testing.TB, sizer Sizer[fakeReq], requestsCount int) { + var wg sync.WaitGroup + wg.Add(requestsCount) + q := NewBoundedMemoryQueue[fakeReq](MemoryQueueSettings[fakeReq]{Sizer: sizer, Capacity: 10 * requestsCount}) + consumers := NewQueueConsumers(q, 1, func(context.Context, fakeReq) error { + wg.Done() + return nil + }) + require.NoError(tb, consumers.Start(context.Background(), componenttest.NewNopHost())) + for j := 0; j < requestsCount; j++ { + require.NoError(tb, q.Offer(context.Background(), fakeReq{10})) + } + assert.NoError(tb, consumers.Shutdown(context.Background())) + wg.Wait() +} + +func TestZeroSizeNoConsumers(t *testing.T) { + q := NewBoundedMemoryQueue[string](MemoryQueueSettings[string]{Sizer: &RequestSizer[string]{}, Capacity: 0}) + + err := q.Start(context.Background(), componenttest.NewNopHost()) + assert.NoError(t, err) + + assert.ErrorIs(t, q.Offer(context.Background(), "a"), ErrQueueIsFull) // in process + + assert.NoError(t, q.Shutdown(context.Background())) +} diff --git a/exporter/internal/queue/consumers.go b/exporter/internal/queue/consumers.go new file mode 100644 index 00000000000..7c57fea9620 --- /dev/null +++ b/exporter/internal/queue/consumers.go @@ -0,0 +1,61 @@ +// 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" +) + +type Consumers[T any] struct { + queue Queue[T] + numConsumers int + consumeFunc func(context.Context, T) error + stopWG sync.WaitGroup +} + +func NewQueueConsumers[T any](q Queue[T], numConsumers int, consumeFunc func(context.Context, T) error) *Consumers[T] { + return &Consumers[T]{ + queue: q, + numConsumers: numConsumers, + consumeFunc: consumeFunc, + stopWG: sync.WaitGroup{}, + } +} + +// Start ensures that queue and all consumers are started. +func (qc *Consumers[T]) Start(ctx context.Context, host component.Host) error { + if err := qc.queue.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 { + if !qc.queue.Consume(qc.consumeFunc) { + return + } + } + }() + } + startWG.Wait() + + return nil +} + +// Shutdown ensures that queue and all consumers are stopped. +func (qc *Consumers[T]) Shutdown(ctx context.Context) error { + if err := qc.queue.Shutdown(ctx); err != nil { + return err + } + qc.stopWG.Wait() + return nil +} diff --git a/exporter/internal/queue/mock_storage.go b/exporter/internal/queue/mock_storage.go new file mode 100644 index 00000000000..6ef9810529b --- /dev/null +++ b/exporter/internal/queue/mock_storage.go @@ -0,0 +1,244 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package queue // import "go.opentelemetry.io/collector/exporter/internal/queue" + +import ( + "context" + "errors" + "fmt" + "sync" + "sync/atomic" + "syscall" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/extension/experimental/storage" +) + +type mockStorageExtension struct { + component.StartFunc + component.ShutdownFunc + st sync.Map + getClientError error +} + +func (m *mockStorageExtension) GetClient(context.Context, component.Kind, component.ID, string) (storage.Client, error) { + if m.getClientError != nil { + return nil, m.getClientError + } + return &mockStorageClient{st: &m.st, closed: &atomic.Bool{}}, nil +} + +func NewMockStorageExtension(getClientError error) storage.Extension { + return &mockStorageExtension{getClientError: getClientError} +} + +type mockStorageClient struct { + st *sync.Map + closed *atomic.Bool +} + +func (m *mockStorageClient) Get(ctx context.Context, s string) ([]byte, error) { + getOp := storage.GetOperation(s) + err := m.Batch(ctx, getOp) + return getOp.Value, err +} + +func (m *mockStorageClient) Set(ctx context.Context, s string, bytes []byte) error { + return m.Batch(ctx, storage.SetOperation(s, bytes)) +} + +func (m *mockStorageClient) Delete(ctx context.Context, s string) error { + return m.Batch(ctx, storage.DeleteOperation(s)) +} + +func (m *mockStorageClient) Close(context.Context) error { + m.closed.Store(true) + return nil +} + +func (m *mockStorageClient) Batch(_ context.Context, ops ...storage.Operation) error { + if m.isClosed() { + panic("client already closed") + } + for _, op := range ops { + switch op.Type { + case storage.Get: + val, found := m.st.Load(op.Key) + if !found { + break + } + op.Value = val.([]byte) + case storage.Set: + m.st.Store(op.Key, op.Value) + case storage.Delete: + m.st.Delete(op.Key) + default: + return errors.New("wrong operation type") + } + } + + return nil +} + +func (m *mockStorageClient) isClosed() bool { + return m.closed.Load() +} + +func newFakeBoundedStorageClient(maxSizeInBytes int) *fakeBoundedStorageClient { + return &fakeBoundedStorageClient{ + st: map[string][]byte{}, + MaxSizeInBytes: maxSizeInBytes, + } +} + +// this storage client mimics the behavior of actual storage engines with limited storage space available +// in general, real storage engines often have a per-write-transaction storage overhead, needing to keep +// both the old and the new value stored until the transaction is committed +// this is useful for testing the persistent queue queue behavior with a full disk +type fakeBoundedStorageClient struct { + MaxSizeInBytes int + st map[string][]byte + sizeInBytes int + mux sync.Mutex +} + +func (m *fakeBoundedStorageClient) Get(ctx context.Context, key string) ([]byte, error) { + op := storage.GetOperation(key) + if err := m.Batch(ctx, op); err != nil { + return nil, err + } + + return op.Value, nil +} + +func (m *fakeBoundedStorageClient) Set(ctx context.Context, key string, value []byte) error { + return m.Batch(ctx, storage.SetOperation(key, value)) +} + +func (m *fakeBoundedStorageClient) Delete(ctx context.Context, key string) error { + return m.Batch(ctx, storage.DeleteOperation(key)) +} + +func (m *fakeBoundedStorageClient) Close(context.Context) error { + return nil +} + +func (m *fakeBoundedStorageClient) Batch(_ context.Context, ops ...storage.Operation) error { + m.mux.Lock() + defer m.mux.Unlock() + + totalAdded, totalRemoved := m.getTotalSizeChange(ops) + + // the assumption here is that the new data needs to coexist with the old data on disk + // for the transaction to succeed + // this seems to be true for the file storage extension at least + if m.sizeInBytes+totalAdded > m.MaxSizeInBytes { + return fmt.Errorf("insufficient space available: %w", syscall.ENOSPC) + } + + for _, op := range ops { + switch op.Type { + case storage.Get: + op.Value = m.st[op.Key] + case storage.Set: + m.st[op.Key] = op.Value + case storage.Delete: + delete(m.st, op.Key) + default: + return errors.New("wrong operation type") + } + } + + m.sizeInBytes += totalAdded - totalRemoved + + return nil +} + +func (m *fakeBoundedStorageClient) SetMaxSizeInBytes(newMaxSize int) { + m.mux.Lock() + defer m.mux.Unlock() + m.MaxSizeInBytes = newMaxSize +} + +func (m *fakeBoundedStorageClient) GetSizeInBytes() int { + m.mux.Lock() + defer m.mux.Unlock() + return m.sizeInBytes +} + +func (m *fakeBoundedStorageClient) getTotalSizeChange(ops []storage.Operation) (totalAdded int, totalRemoved int) { + totalAdded, totalRemoved = 0, 0 + for _, op := range ops { + switch op.Type { + case storage.Set: + if oldValue, ok := m.st[op.Key]; ok { + totalRemoved += len(oldValue) + } else { + totalAdded += len(op.Key) + } + totalAdded += len(op.Value) + case storage.Delete: + if value, ok := m.st[op.Key]; ok { + totalRemoved += len(op.Key) + totalRemoved += len(value) + } + default: + } + } + return totalAdded, totalRemoved +} + +func newFakeStorageClientWithErrors(errors []error) *fakeStorageClientWithErrors { + return &fakeStorageClientWithErrors{ + errors: errors, + } +} + +// this storage client just returns errors from a list in order +// used for testing error handling +type fakeStorageClientWithErrors struct { + errors []error + nextErrorIndex int + mux sync.Mutex +} + +func (m *fakeStorageClientWithErrors) Get(ctx context.Context, key string) ([]byte, error) { + op := storage.GetOperation(key) + err := m.Batch(ctx, op) + if err != nil { + return nil, err + } + + return op.Value, nil +} + +func (m *fakeStorageClientWithErrors) Set(ctx context.Context, key string, value []byte) error { + return m.Batch(ctx, storage.SetOperation(key, value)) +} + +func (m *fakeStorageClientWithErrors) Delete(ctx context.Context, key string) error { + return m.Batch(ctx, storage.DeleteOperation(key)) +} + +func (m *fakeStorageClientWithErrors) Close(context.Context) error { + return nil +} + +func (m *fakeStorageClientWithErrors) Batch(context.Context, ...storage.Operation) error { + m.mux.Lock() + defer m.mux.Unlock() + + if m.nextErrorIndex >= len(m.errors) { + return nil + } + + m.nextErrorIndex++ + return m.errors[m.nextErrorIndex-1] +} + +func (m *fakeStorageClientWithErrors) Reset() { + m.mux.Lock() + defer m.mux.Unlock() + m.nextErrorIndex = 0 +} diff --git a/exporter/internal/queue/package_test.go b/exporter/internal/queue/package_test.go new file mode 100644 index 00000000000..e73f51264a8 --- /dev/null +++ b/exporter/internal/queue/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package queue + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/exporter/internal/queue/persistent_queue.go b/exporter/internal/queue/persistent_queue.go new file mode 100644 index 00000000000..b6e5d2be4dd --- /dev/null +++ b/exporter/internal/queue/persistent_queue.go @@ -0,0 +1,573 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package queue // import "go.opentelemetry.io/collector/exporter/internal/queue" + +import ( + "context" + "encoding/binary" + "errors" + "fmt" + "strconv" + "sync" + "sync/atomic" + + "go.uber.org/multierr" + "go.uber.org/zap" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/internal/experr" + "go.opentelemetry.io/collector/extension/experimental/storage" +) + +// persistentQueue provides a persistent queue implementation backed by file storage extension +// +// Write index describes the position at which next item is going to be stored. +// Read index describes which item needs to be read next. +// When Write index = Read index, no elements are in the queue. +// +// The items currently dispatched by consumers are not deleted until the processing is finished. +// Their list is stored under a separate key. +// +// ┌───────file extension-backed queue───────┐ +// │ │ +// │ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ │ +// │ n+1 │ n │ ... │ 4 │ │ 3 │ │ 2 │ │ 1 │ │ +// │ └───┘ └───┘ └─x─┘ └─|─┘ └─x─┘ │ +// │ x | x │ +// └───────────────────────x─────|─────x─────┘ +// ▲ ▲ x | x +// │ │ x | xxxx deleted +// │ │ x | +// write read x └── currently dispatched item +// index index x +// xxxx deleted +type persistentQueue[T any] struct { + *queueCapacityLimiter[T] + + set PersistentQueueSettings[T] + logger *zap.Logger + client storage.Client + + // isRequestSized indicates whether the queue is sized by the number of requests. + isRequestSized bool + + putChan chan struct{} + + // mu guards everything declared below. + mu sync.Mutex + readIndex uint64 + writeIndex uint64 + initIndexSize uint64 + initQueueSize *atomic.Uint64 + currentlyDispatchedItems []uint64 + refClient int64 + stopped bool +} + +const ( + zapKey = "key" + zapErrorCount = "errorCount" + zapNumberOfItems = "numberOfItems" + + readIndexKey = "ri" + writeIndexKey = "wi" + currentlyDispatchedItemsKey = "di" + queueSizeKey = "si" +) + +var ( + errValueNotSet = errors.New("value not set") + errInvalidValue = errors.New("invalid value") + errNoStorageClient = errors.New("no storage client extension found") + errWrongExtensionType = errors.New("requested extension is not a storage extension") +) + +type PersistentQueueSettings[T any] struct { + Sizer Sizer[T] + Capacity int + DataType component.DataType + StorageID component.ID + Marshaler func(req T) ([]byte, error) + Unmarshaler func([]byte) (T, error) + ExporterSettings exporter.CreateSettings +} + +// 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] { + _, isRequestSized := set.Sizer.(*RequestSizer[T]) + return &persistentQueue[T]{ + queueCapacityLimiter: newQueueCapacityLimiter[T](set.Sizer, set.Capacity), + set: set, + logger: set.ExporterSettings.Logger, + initQueueSize: &atomic.Uint64{}, + isRequestSized: isRequestSized, + putChan: make(chan struct{}, set.Capacity), + } +} + +// Start starts the persistentQueue with the given number of consumers. +func (pq *persistentQueue[T]) Start(ctx context.Context, host component.Host) error { + storageClient, err := toStorageClient(ctx, pq.set.StorageID, host, pq.set.ExporterSettings.ID, pq.set.DataType) + if err != nil { + return err + } + pq.initClient(ctx, storageClient) + return nil +} + +func (pq *persistentQueue[T]) initClient(ctx context.Context, client storage.Client) { + pq.client = client + // Start with a reference 1 which is the reference we use for the producer goroutines and initialization. + pq.refClient = 1 + pq.initPersistentContiguousStorage(ctx) + // Make sure the leftover requests are handled + pq.retrieveAndEnqueueNotDispatchedReqs(ctx) +} + +func (pq *persistentQueue[T]) initPersistentContiguousStorage(ctx context.Context) { + riOp := storage.GetOperation(readIndexKey) + wiOp := storage.GetOperation(writeIndexKey) + + err := pq.client.Batch(ctx, riOp, wiOp) + if err == nil { + pq.readIndex, err = bytesToItemIndex(riOp.Value) + } + + if err == nil { + pq.writeIndex, err = bytesToItemIndex(wiOp.Value) + } + + if err != nil { + if errors.Is(err, errValueNotSet) { + pq.logger.Info("Initializing new persistent queue") + } else { + pq.logger.Error("Failed getting read/write index, starting with new ones", zap.Error(err)) + } + pq.readIndex = 0 + pq.writeIndex = 0 + } + pq.initIndexSize = pq.writeIndex - pq.readIndex + + // Ensure the communication channel has the same size as the queue + for i := 0; i < int(pq.initIndexSize); i++ { + pq.putChan <- struct{}{} + } + + // Read snapshot of the queue size from storage. It's not a problem if the value cannot be fetched, + // or it's not accurate. The queue size will be corrected once the recovered queue is drained. + if pq.initIndexSize > 0 { + // If the queue is sized by the number of requests, no need to read the queue size from storage. + if pq.isRequestSized { + pq.initQueueSize.Store(pq.initIndexSize) + return + } + + res, err := pq.client.Get(ctx, queueSizeKey) + if err == nil { + var restoredQueueSize uint64 + restoredQueueSize, err = bytesToItemIndex(res) + pq.initQueueSize.Store(restoredQueueSize) + } + if err != nil { + if errors.Is(err, errValueNotSet) { + pq.logger.Warn("Cannot read the queue size snapshot from storage. "+ + "The reported queue size will be inaccurate until the initial queue is drained. "+ + "It's expected when the items sized queue enabled for the first time", zap.Error(err)) + } else { + pq.logger.Error("Failed to read the queue size snapshot from storage. "+ + "The reported queue size will be inaccurate until the initial queue is drained.", zap.Error(err)) + } + } + } +} + +// Consume applies the provided function on the head of queue. +// The call blocks until there is an item available or the queue is stopped. +// The function returns true when an item is consumed or false if the queue is stopped. +func (pq *persistentQueue[T]) Consume(consumeFunc func(context.Context, T) error) bool { + for { + // If we are stopped we still process all the other events in the channel before, but we + // return fast in the `getNextItem`, so we will free the channel fast and get to the stop. + _, ok := <-pq.putChan + if !ok { + return false + } + + req, onProcessingFinished, consumed := pq.getNextItem(context.Background()) + if consumed { + onProcessingFinished(consumeFunc(context.Background(), req)) + return true + } + } +} + +// Size returns the current size of the queue. +func (pq *persistentQueue[T]) Size() int { + return int(pq.initQueueSize.Load()) + pq.queueCapacityLimiter.Size() +} + +func (pq *persistentQueue[T]) Shutdown(ctx context.Context) error { + close(pq.putChan) + pq.mu.Lock() + defer pq.mu.Unlock() + // Mark this queue as stopped, so consumer don't start any more work. + pq.stopped = true + return multierr.Combine( + pq.backupQueueSize(ctx), + pq.unrefClient(ctx), + ) +} + +// backupQueueSize writes the current queue size to storage. The value is used to recover the queue size +// in case if the collector is killed. +func (pq *persistentQueue[T]) backupQueueSize(ctx context.Context) error { + // Client can be nil if the queue is not initialized yet. + if pq.client == nil { + return nil + } + + // No need to write the queue size if the queue is sized by the number of requests. + // That information is already stored as difference between read and write indexes. + if pq.isRequestSized { + return nil + } + + return pq.client.Set(ctx, queueSizeKey, itemIndexToBytes(uint64(pq.Size()))) +} + +// unrefClient unrefs the client, and closes if no more references. Callers MUST hold the mutex. +// This is needed because consumers of the queue may still process the requests while the queue is shutting down or immediately after. +func (pq *persistentQueue[T]) unrefClient(ctx context.Context) error { + pq.refClient-- + if pq.refClient == 0 { + return pq.client.Close(ctx) + } + return nil +} + +// Offer inserts the specified element into this queue if it is possible to do so immediately +// without violating capacity restrictions. If success returns no error. +// It returns ErrQueueIsFull if no space is currently available. +func (pq *persistentQueue[T]) Offer(ctx context.Context, req T) error { + pq.mu.Lock() + defer pq.mu.Unlock() + return pq.putInternal(ctx, req) +} + +// putInternal is the internal version that requires caller to hold the mutex lock. +func (pq *persistentQueue[T]) putInternal(ctx context.Context, req T) error { + if !pq.queueCapacityLimiter.claim(req) { + pq.logger.Warn("Maximum queue capacity reached") + return ErrQueueIsFull + } + + itemKey := getItemKey(pq.writeIndex) + newIndex := pq.writeIndex + 1 + + reqBuf, err := pq.set.Marshaler(req) + if err != nil { + pq.queueCapacityLimiter.release(req) + return err + } + + // Carry out a transaction where we both add the item and update the write index + ops := []storage.Operation{ + storage.SetOperation(writeIndexKey, itemIndexToBytes(newIndex)), + storage.SetOperation(itemKey, reqBuf), + } + if storageErr := pq.client.Batch(ctx, ops...); storageErr != nil { + pq.queueCapacityLimiter.release(req) + return storageErr + } + + pq.writeIndex = newIndex + // Inform the loop that there's some data to process + pq.putChan <- struct{}{} + + // Back up the queue size to storage every 10 writes. The stored value is used to recover the queue size + // in case if the collector is killed. The recovered queue size is allowed to be inaccurate. + if (pq.writeIndex % 10) == 5 { + if err := pq.backupQueueSize(ctx); err != nil { + pq.logger.Error("Error writing queue size to storage", zap.Error(err)) + } + } + + return nil +} + +// getNextItem pulls the next available item from the persistent storage along with a callback function that should be +// called after the item is processed to clean up the storage. If no new item is available, returns false. +func (pq *persistentQueue[T]) getNextItem(ctx context.Context) (T, func(error), bool) { + pq.mu.Lock() + defer pq.mu.Unlock() + + var request T + + if pq.stopped { + return request, nil, false + } + + if pq.readIndex == pq.writeIndex { + return request, nil, false + } + + index := pq.readIndex + // Increase here, so even if errors happen below, it always iterates + pq.readIndex++ + pq.currentlyDispatchedItems = append(pq.currentlyDispatchedItems, index) + getOp := storage.GetOperation(getItemKey(index)) + err := pq.client.Batch(ctx, + storage.SetOperation(readIndexKey, itemIndexToBytes(pq.readIndex)), + storage.SetOperation(currentlyDispatchedItemsKey, itemIndexArrayToBytes(pq.currentlyDispatchedItems)), + getOp) + + if err == nil { + request, err = pq.set.Unmarshaler(getOp.Value) + } + + if err != nil { + pq.logger.Debug("Failed to dispatch item", zap.Error(err)) + // We need to make sure that currently dispatched items list is cleaned + if err = pq.itemDispatchingFinish(ctx, index); err != nil { + pq.logger.Error("Error deleting item from queue", zap.Error(err)) + } + + return request, nil, false + } + + pq.releaseCapacity(request) + + // Back up the queue size to storage on every 10 reads. The stored value is used to recover the queue size + // in case if the collector is killed. The recovered queue size is allowed to be inaccurate. + if (pq.writeIndex % 10) == 0 { + if qsErr := pq.backupQueueSize(ctx); qsErr != nil { + pq.logger.Error("Error writing queue size to storage", zap.Error(err)) + } + } + + // Increase the reference count, so the client is not closed while the request is being processed. + // The client cannot be closed because we hold the lock since last we checked `stopped`. + pq.refClient++ + return request, func(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. + defer func() { + if err = pq.unrefClient(ctx); err != nil { + pq.logger.Error("Error closing the storage client", zap.Error(err)) + } + pq.mu.Unlock() + }() + + if experr.IsShutdownErr(consumeErr) { + // The queue is shutting down, don't mark the item as dispatched, so it's picked up again after restart. + // TODO: Handle partially delivered requests by updating their values in the storage. + return + } + + if err = pq.itemDispatchingFinish(ctx, index); err != nil { + pq.logger.Error("Error deleting item from queue", zap.Error(err)) + } + + }, true +} + +// releaseCapacity releases the capacity of the queue. The caller must hold the mutex. +func (pq *persistentQueue[T]) releaseCapacity(req T) { + // If the recovered queue size is not emptied yet, decrease it first. + if pq.initIndexSize > 0 { + pq.initIndexSize-- + if pq.initIndexSize == 0 { + pq.initQueueSize.Store(0) + return + } + reqSize := pq.queueCapacityLimiter.sizeOf(req) + if pq.initQueueSize.Load() < reqSize { + pq.initQueueSize.Store(0) + return + } + pq.initQueueSize.Add(^(reqSize - 1)) + return + } + + // Otherwise, decrease the current queue size. + pq.queueCapacityLimiter.release(req) +} + +// retrieveAndEnqueueNotDispatchedReqs gets the items for which sending was not finished, cleans the storage +// and moves the items at the back of the queue. +func (pq *persistentQueue[T]) retrieveAndEnqueueNotDispatchedReqs(ctx context.Context) { + var dispatchedItems []uint64 + + pq.mu.Lock() + defer pq.mu.Unlock() + pq.logger.Debug("Checking if there are items left for dispatch by consumers") + itemKeysBuf, err := pq.client.Get(ctx, currentlyDispatchedItemsKey) + if err == nil { + dispatchedItems, err = bytesToItemIndexArray(itemKeysBuf) + } + if err != nil { + pq.logger.Error("Could not fetch items left for dispatch by consumers", zap.Error(err)) + return + } + + if len(dispatchedItems) == 0 { + pq.logger.Debug("No items left for dispatch by consumers") + return + } + + pq.logger.Info("Fetching items left for dispatch by consumers", zap.Int(zapNumberOfItems, + len(dispatchedItems))) + retrieveBatch := make([]storage.Operation, len(dispatchedItems)) + cleanupBatch := make([]storage.Operation, len(dispatchedItems)) + for i, it := range dispatchedItems { + key := getItemKey(it) + retrieveBatch[i] = storage.GetOperation(key) + cleanupBatch[i] = storage.DeleteOperation(key) + } + retrieveErr := pq.client.Batch(ctx, retrieveBatch...) + cleanupErr := pq.client.Batch(ctx, cleanupBatch...) + + if cleanupErr != nil { + pq.logger.Debug("Failed cleaning items left by consumers", zap.Error(cleanupErr)) + } + + if retrieveErr != nil { + pq.logger.Warn("Failed retrieving items left by consumers", zap.Error(retrieveErr)) + return + } + + errCount := 0 + for _, op := range retrieveBatch { + if op.Value == nil { + pq.logger.Warn("Failed retrieving item", zap.String(zapKey, op.Key), zap.Error(errValueNotSet)) + continue + } + req, err := pq.set.Unmarshaler(op.Value) + // If error happened or item is nil, it will be efficiently ignored + if err != nil { + pq.logger.Warn("Failed unmarshalling item", zap.String(zapKey, op.Key), zap.Error(err)) + continue + } + if pq.putInternal(ctx, req) != nil { + errCount++ + } + } + + if errCount > 0 { + pq.logger.Error("Errors occurred while moving items for dispatching back to queue", + zap.Int(zapNumberOfItems, len(retrieveBatch)), zap.Int(zapErrorCount, errCount)) + } else { + pq.logger.Info("Moved items for dispatching back to queue", + zap.Int(zapNumberOfItems, len(retrieveBatch))) + } +} + +// itemDispatchingFinish removes the item from the list of currently dispatched items and deletes it from the persistent queue +func (pq *persistentQueue[T]) itemDispatchingFinish(ctx context.Context, index uint64) error { + lenCDI := len(pq.currentlyDispatchedItems) + for i := 0; i < lenCDI; i++ { + if pq.currentlyDispatchedItems[i] == index { + pq.currentlyDispatchedItems[i] = pq.currentlyDispatchedItems[lenCDI-1] + pq.currentlyDispatchedItems = pq.currentlyDispatchedItems[:lenCDI-1] + break + } + } + + setOp := storage.SetOperation(currentlyDispatchedItemsKey, itemIndexArrayToBytes(pq.currentlyDispatchedItems)) + deleteOp := storage.DeleteOperation(getItemKey(index)) + if err := pq.client.Batch(ctx, setOp, deleteOp); err != nil { + // got an error, try to gracefully handle it + pq.logger.Warn("Failed updating currently dispatched items, trying to delete the item first", + zap.Error(err)) + } else { + // Everything ok, exit + return nil + } + + if err := pq.client.Batch(ctx, deleteOp); err != nil { + // Return an error here, as this indicates an issue with the underlying storage medium + return fmt.Errorf("failed deleting item from queue, got error from storage: %w", err) + } + + if err := pq.client.Batch(ctx, setOp); err != nil { + // even if this fails, we still have the right dispatched items in memory + // at worst, we'll have the wrong list in storage, and we'll discard the nonexistent items during startup + return fmt.Errorf("failed updating currently dispatched items, but deleted item successfully: %w", err) + } + + return nil +} + +func toStorageClient(ctx context.Context, storageID component.ID, host component.Host, ownerID component.ID, signal component.DataType) (storage.Client, error) { + ext, found := host.GetExtensions()[storageID] + if !found { + return nil, errNoStorageClient + } + + storageExt, ok := ext.(storage.Extension) + if !ok { + return nil, errWrongExtensionType + } + + return storageExt.GetClient(ctx, component.KindExporter, ownerID, signal.String()) +} + +func getItemKey(index uint64) string { + return strconv.FormatUint(index, 10) +} + +func itemIndexToBytes(value uint64) []byte { + return binary.LittleEndian.AppendUint64([]byte{}, value) +} + +func bytesToItemIndex(buf []byte) (uint64, error) { + if buf == nil { + return uint64(0), errValueNotSet + } + // The sizeof uint64 in binary is 8. + if len(buf) < 8 { + return 0, errInvalidValue + } + return binary.LittleEndian.Uint64(buf), nil +} + +func itemIndexArrayToBytes(arr []uint64) []byte { + size := len(arr) + buf := make([]byte, 0, 4+size*8) + buf = binary.LittleEndian.AppendUint32(buf, uint32(size)) + for _, item := range arr { + buf = binary.LittleEndian.AppendUint64(buf, item) + } + return buf +} + +func bytesToItemIndexArray(buf []byte) ([]uint64, error) { + if len(buf) == 0 { + return nil, nil + } + + // The sizeof uint32 in binary is 4. + if len(buf) < 4 { + return nil, errInvalidValue + } + size := int(binary.LittleEndian.Uint32(buf)) + if size == 0 { + return nil, nil + } + + buf = buf[4:] + // The sizeof uint64 in binary is 8, so we need to have size*8 bytes. + if len(buf) < size*8 { + return nil, errInvalidValue + } + + val := make([]uint64, size) + for i := 0; i < size; i++ { + val[i] = binary.LittleEndian.Uint64(buf) + buf = buf[8:] + } + return val, nil +} diff --git a/exporter/internal/queue/persistent_queue_test.go b/exporter/internal/queue/persistent_queue_test.go new file mode 100644 index 00000000000..2b525fa792f --- /dev/null +++ b/exporter/internal/queue/persistent_queue_test.go @@ -0,0 +1,884 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package queue + +import ( + "context" + "errors" + "fmt" + "strconv" + "sync/atomic" + "syscall" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/exporter/internal/experr" + "go.opentelemetry.io/collector/extension/experimental/storage" + "go.opentelemetry.io/collector/extension/extensiontest" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/ptrace" +) + +type tracesRequest struct { + traces ptrace.Traces +} + +func (tr tracesRequest) ItemsCount() int { + return tr.traces.SpanCount() +} + +func marshalTracesRequest(tr tracesRequest) ([]byte, error) { + marshaler := &ptrace.ProtoMarshaler{} + return marshaler.MarshalTraces(tr.traces) +} + +func unmarshalTracesRequest(bytes []byte) (tracesRequest, error) { + unmarshaler := &ptrace.ProtoUnmarshaler{} + traces, err := unmarshaler.UnmarshalTraces(bytes) + return tracesRequest{traces: traces}, err +} + +type mockHost struct { + component.Host + ext map[component.ID]component.Component +} + +func (nh *mockHost) GetExtensions() map[component.ID]component.Component { + return nh.ext +} + +// createAndStartTestPersistentQueue creates and starts a fake queue with the given capacity and number of consumers. +func createAndStartTestPersistentQueue(t *testing.T, sizer Sizer[tracesRequest], capacity int, numConsumers int, + consumeFunc func(_ context.Context, item tracesRequest) error) Queue[tracesRequest] { + pq := NewPersistentQueue[tracesRequest](PersistentQueueSettings[tracesRequest]{ + Sizer: sizer, + Capacity: capacity, + DataType: component.DataTypeTraces, + StorageID: component.ID{}, + Marshaler: marshalTracesRequest, + Unmarshaler: unmarshalTracesRequest, + ExporterSettings: exportertest.NewNopCreateSettings(), + }) + host := &mockHost{ext: map[component.ID]component.Component{ + {}: NewMockStorageExtension(nil), + }} + consumers := NewQueueConsumers(pq, numConsumers, consumeFunc) + require.NoError(t, consumers.Start(context.Background(), host)) + t.Cleanup(func() { + assert.NoError(t, consumers.Shutdown(context.Background())) + }) + return pq +} + +func createTestPersistentQueueWithClient(client storage.Client) *persistentQueue[tracesRequest] { + pq := NewPersistentQueue[tracesRequest](PersistentQueueSettings[tracesRequest]{ + Sizer: &RequestSizer[tracesRequest]{}, + Capacity: 1000, + DataType: component.DataTypeTraces, + StorageID: component.ID{}, + Marshaler: marshalTracesRequest, + Unmarshaler: unmarshalTracesRequest, + ExporterSettings: exportertest.NewNopCreateSettings(), + }).(*persistentQueue[tracesRequest]) + pq.initClient(context.Background(), client) + return pq +} + +func createTestPersistentQueueWithRequestsCapacity(t testing.TB, ext storage.Extension, capacity int) *persistentQueue[tracesRequest] { + return createTestPersistentQueueWithCapacityLimiter(t, ext, &RequestSizer[tracesRequest]{}, capacity) +} + +func createTestPersistentQueueWithItemsCapacity(t testing.TB, ext storage.Extension, capacity int) *persistentQueue[tracesRequest] { + return createTestPersistentQueueWithCapacityLimiter(t, ext, &ItemsSizer[tracesRequest]{}, capacity) +} + +func createTestPersistentQueueWithCapacityLimiter(t testing.TB, ext storage.Extension, sizer Sizer[tracesRequest], + capacity int) *persistentQueue[tracesRequest] { + pq := NewPersistentQueue[tracesRequest](PersistentQueueSettings[tracesRequest]{ + Sizer: sizer, + Capacity: capacity, + DataType: component.DataTypeTraces, + StorageID: component.ID{}, + Marshaler: marshalTracesRequest, + Unmarshaler: unmarshalTracesRequest, + ExporterSettings: exportertest.NewNopCreateSettings(), + }).(*persistentQueue[tracesRequest]) + require.NoError(t, pq.Start(context.Background(), &mockHost{ext: map[component.ID]component.Component{{}: ext}})) + return pq +} + +func TestPersistentQueue_FullCapacity(t *testing.T) { + tests := []struct { + name string + sizer Sizer[tracesRequest] + capacity int + sizeMultiplier int + }{ + { + name: "requests_capacity", + sizer: &RequestSizer[tracesRequest]{}, + capacity: 5, + sizeMultiplier: 1, + }, + { + name: "items_capacity", + sizer: &ItemsSizer[tracesRequest]{}, + capacity: 55, + sizeMultiplier: 10, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + start := make(chan struct{}) + done := make(chan struct{}) + pq := createAndStartTestPersistentQueue(t, tt.sizer, tt.capacity, 1, func(context.Context, tracesRequest) error { + <-start + <-done + return nil + }) + assert.Equal(t, 0, pq.Size()) + + req := newTracesRequest(1, 10) + + // First request is picked by the consumer. Wait until the consumer is blocked on done. + assert.NoError(t, pq.Offer(context.Background(), req)) + start <- struct{}{} + close(start) + + for i := 0; i < 10; i++ { + result := pq.Offer(context.Background(), newTracesRequest(1, 10)) + if i < 5 { + assert.NoError(t, result) + } else { + assert.ErrorIs(t, result, ErrQueueIsFull) + } + } + assert.Equal(t, 5*tt.sizeMultiplier, pq.Size()) + close(done) + }) + } +} + +func TestPersistentQueue_Shutdown(t *testing.T) { + pq := createAndStartTestPersistentQueue(t, &RequestSizer[tracesRequest]{}, 1001, 100, func(context.Context, + tracesRequest) error { + return nil + }) + req := newTracesRequest(1, 10) + + for i := 0; i < 1000; i++ { + assert.NoError(t, pq.Offer(context.Background(), req)) + } + +} + +func TestPersistentQueue_ConsumersProducers(t *testing.T) { + cases := []struct { + numMessagesProduced int + numConsumers int + }{ + { + numMessagesProduced: 1, + numConsumers: 1, + }, + { + numMessagesProduced: 100, + numConsumers: 1, + }, + { + numMessagesProduced: 100, + numConsumers: 3, + }, + { + numMessagesProduced: 1, + numConsumers: 100, + }, + { + numMessagesProduced: 100, + numConsumers: 100, + }, + } + + for _, c := range cases { + t.Run(fmt.Sprintf("#messages: %d #consumers: %d", c.numMessagesProduced, c.numConsumers), func(t *testing.T) { + req := newTracesRequest(1, 10) + + numMessagesConsumed := &atomic.Int32{} + pq := createAndStartTestPersistentQueue(t, &RequestSizer[tracesRequest]{}, 1000, c.numConsumers, + func(context.Context, + tracesRequest) error { + numMessagesConsumed.Add(int32(1)) + return nil + }) + + for i := 0; i < c.numMessagesProduced; i++ { + assert.NoError(t, pq.Offer(context.Background(), req)) + } + + assert.Eventually(t, func() bool { + return c.numMessagesProduced == int(numMessagesConsumed.Load()) + }, 5*time.Second, 10*time.Millisecond) + }) + } +} + +func newTracesRequest(numTraces int, numSpans int) tracesRequest { + traces := ptrace.NewTraces() + batch := traces.ResourceSpans().AppendEmpty() + batch.Resource().Attributes().PutStr("resource-attr", "some-resource") + batch.Resource().Attributes().PutInt("num-traces", int64(numTraces)) + batch.Resource().Attributes().PutInt("num-spans", int64(numSpans)) + + for i := 0; i < numTraces; i++ { + traceID := pcommon.TraceID([16]byte{1, 2, 3, byte(i)}) + ils := batch.ScopeSpans().AppendEmpty() + for j := 0; j < numSpans; j++ { + span := ils.Spans().AppendEmpty() + span.SetTraceID(traceID) + span.SetSpanID([8]byte{1, 2, 3, byte(j)}) + span.SetName("should-not-be-changed") + span.Attributes().PutInt("int-attribute", int64(j)) + span.Attributes().PutStr("str-attribute-1", "foobar") + span.Attributes().PutStr("str-attribute-2", "fdslafjasdk12312312jkl") + span.Attributes().PutStr("str-attribute-3", "AbcDefGeKKjkfdsafasdfsdasdf") + span.Attributes().PutStr("str-attribute-4", "xxxxxx") + span.Attributes().PutStr("str-attribute-5", "abcdef") + } + } + + return tracesRequest{traces: traces} +} + +func TestToStorageClient(t *testing.T) { + getStorageClientError := errors.New("unable to create storage client") + testCases := []struct { + desc string + storage storage.Extension + numStorages int + storageIndex int + expectedError error + getClientError error + }{ + { + desc: "obtain storage extension by name", + numStorages: 2, + storageIndex: 0, + expectedError: nil, + }, + { + desc: "fail on not existing storage extension", + numStorages: 2, + storageIndex: 100, + expectedError: errNoStorageClient, + }, + { + desc: "invalid extension type", + numStorages: 2, + storageIndex: 100, + expectedError: errNoStorageClient, + }, + { + desc: "fail on error getting storage client from extension", + numStorages: 1, + storageIndex: 0, + expectedError: getStorageClientError, + getClientError: getStorageClientError, + }, + } + + for _, tC := range testCases { + t.Run(tC.desc, func(t *testing.T) { + storageID := component.MustNewIDWithName("file_storage", strconv.Itoa(tC.storageIndex)) + + var extensions = map[component.ID]component.Component{} + for i := 0; i < tC.numStorages; i++ { + extensions[component.MustNewIDWithName("file_storage", strconv.Itoa(i))] = NewMockStorageExtension(tC.getClientError) + } + host := &mockHost{ext: extensions} + ownerID := component.MustNewID("foo_exporter") + + // execute + client, err := toStorageClient(context.Background(), storageID, host, ownerID, component.DataTypeTraces) + + // verify + if tC.expectedError != nil { + assert.ErrorIs(t, err, tC.expectedError) + assert.Nil(t, client) + } else { + assert.NoError(t, err) + assert.NotNil(t, client) + } + }) + } +} + +func TestInvalidStorageExtensionType(t *testing.T) { + storageID := component.MustNewIDWithName("extension", "extension") + + // make a test extension + factory := extensiontest.NewNopFactory() + extConfig := factory.CreateDefaultConfig() + settings := extensiontest.NewNopCreateSettings() + extension, err := factory.CreateExtension(context.Background(), settings, extConfig) + assert.NoError(t, err) + var extensions = map[component.ID]component.Component{ + storageID: extension, + } + host := &mockHost{ext: extensions} + ownerID := component.MustNewID("foo_exporter") + + // execute + client, err := toStorageClient(context.Background(), storageID, host, ownerID, component.DataTypeTraces) + + // we should get an error about the extension type + assert.ErrorIs(t, err, errWrongExtensionType) + assert.Nil(t, client) +} + +func TestPersistentQueue_StopAfterBadStart(t *testing.T) { + pq := NewPersistentQueue[tracesRequest](PersistentQueueSettings[tracesRequest]{}) + // verify that stopping a un-start/started w/error queue does not panic + assert.NoError(t, pq.Shutdown(context.Background())) +} + +func TestPersistentQueue_CorruptedData(t *testing.T) { + req := newTracesRequest(5, 10) + + cases := []struct { + name string + corruptAllData bool + corruptSomeData bool + corruptCurrentlyDispatchedItemsKey bool + corruptReadIndex bool + corruptWriteIndex bool + desiredQueueSize int + }{ + { + name: "corrupted no items", + desiredQueueSize: 3, + }, + { + name: "corrupted all items", + corruptAllData: true, + desiredQueueSize: 2, // - the dispatched item which was corrupted. + }, + { + name: "corrupted some items", + corruptSomeData: true, + desiredQueueSize: 2, // - the dispatched item which was corrupted. + }, + { + name: "corrupted dispatched items key", + corruptCurrentlyDispatchedItemsKey: true, + desiredQueueSize: 2, + }, + { + name: "corrupted read index", + corruptReadIndex: true, + desiredQueueSize: 1, // The dispatched item. + }, + { + name: "corrupted write index", + corruptWriteIndex: true, + desiredQueueSize: 1, // The dispatched item. + }, + { + name: "corrupted everything", + corruptAllData: true, + corruptCurrentlyDispatchedItemsKey: true, + corruptReadIndex: true, + corruptWriteIndex: true, + desiredQueueSize: 0, + }, + } + + badBytes := []byte{0, 1, 2} + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + ext := NewMockStorageExtension(nil) + ps := createTestPersistentQueueWithRequestsCapacity(t, ext, 1000) + + // Put some items, make sure they are loaded and shutdown the storage... + for i := 0; i < 3; i++ { + err := ps.Offer(context.Background(), req) + require.NoError(t, err) + } + assert.Equal(t, 3, ps.Size()) + require.True(t, ps.Consume(func(context.Context, tracesRequest) error { + return experr.NewShutdownErr(nil) + })) + assert.Equal(t, 2, ps.Size()) + + // We can corrupt data (in several ways) and not worry since we return ShutdownErr client will not be touched. + if c.corruptAllData || c.corruptSomeData { + require.NoError(t, ps.client.Set(context.Background(), "0", badBytes)) + } + if c.corruptAllData { + require.NoError(t, ps.client.Set(context.Background(), "1", badBytes)) + require.NoError(t, ps.client.Set(context.Background(), "2", badBytes)) + } + + if c.corruptCurrentlyDispatchedItemsKey { + require.NoError(t, ps.client.Set(context.Background(), currentlyDispatchedItemsKey, badBytes)) + } + + if c.corruptReadIndex { + require.NoError(t, ps.client.Set(context.Background(), readIndexKey, badBytes)) + } + + if c.corruptWriteIndex { + require.NoError(t, ps.client.Set(context.Background(), writeIndexKey, badBytes)) + } + + // Cannot close until we corrupt the data because the + assert.NoError(t, ps.Shutdown(context.Background())) + + // Reload + newPs := createTestPersistentQueueWithRequestsCapacity(t, ext, 1000) + assert.Equal(t, c.desiredQueueSize, newPs.Size()) + }) + } +} + +func TestPersistentQueue_CurrentlyProcessedItems(t *testing.T) { + req := newTracesRequest(5, 10) + + ext := NewMockStorageExtension(nil) + ps := createTestPersistentQueueWithRequestsCapacity(t, ext, 1000) + + for i := 0; i < 5; i++ { + err := ps.Offer(context.Background(), req) + require.NoError(t, err) + } + + requireCurrentlyDispatchedItemsEqual(t, ps, []uint64{}) + + // Takes index 0 in process. + readReq, _, found := ps.getNextItem(context.Background()) + require.True(t, found) + assert.Equal(t, req, readReq) + requireCurrentlyDispatchedItemsEqual(t, ps, []uint64{0}) + + // This takes item 1 to process. + secondReadReq, onProcessingFinished, found := ps.getNextItem(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. + onProcessingFinished(nil) + requireCurrentlyDispatchedItemsEqual(t, ps, []uint64{0}) + + // Reload the storage. Since items 0 was not finished, this should be re-enqueued at the end. + // The queue should be essentially {3,4,0,2}. + newPs := createTestPersistentQueueWithRequestsCapacity(t, ext, 1000) + assert.Equal(t, 4, newPs.Size()) + requireCurrentlyDispatchedItemsEqual(t, newPs, []uint64{}) + + // We should be able to pull all remaining items now + for i := 0; i < 4; i++ { + newPs.Consume(func(_ context.Context, traces tracesRequest) error { + assert.Equal(t, req, traces) + return nil + }) + } + + // The queue should be now empty + requireCurrentlyDispatchedItemsEqual(t, newPs, []uint64{}) + assert.Equal(t, 0, newPs.Size()) + // The writeIndex should be now set accordingly + require.EqualValues(t, 6, newPs.writeIndex) + + // There should be no items left in the storage + for i := 0; i < int(newPs.writeIndex); i++ { + bb, err := newPs.client.Get(context.Background(), getItemKey(uint64(i))) + require.NoError(t, err) + require.Nil(t, bb) + } +} + +// this test attempts to check if all the invariants are kept if the queue is recreated while +// close to full and with some items dispatched +func TestPersistentQueueStartWithNonDispatched(t *testing.T) { + req := newTracesRequest(5, 10) + + ext := NewMockStorageExtension(nil) + ps := createTestPersistentQueueWithRequestsCapacity(t, ext, 5) + + // Put in items up to capacity + for i := 0; i < 5; i++ { + err := ps.Offer(context.Background(), req) + require.NoError(t, err) + } + + // get one item out, but don't mark it as processed + <-ps.putChan + require.True(t, ps.Consume(func(context.Context, tracesRequest) error { + // put one more item in + require.NoError(t, ps.Offer(context.Background(), req)) + require.Equal(t, 5, ps.Size()) + return experr.NewShutdownErr(nil) + })) + assert.NoError(t, ps.Shutdown(context.Background())) + + // Reload with extra capacity to make sure we re-enqueue in-progress items. + newPs := createTestPersistentQueueWithRequestsCapacity(t, ext, 6) + require.Equal(t, 6, newPs.Size()) +} + +func TestPersistentQueue_PutCloseReadClose(t *testing.T) { + req := newTracesRequest(5, 10) + ext := NewMockStorageExtension(nil) + ps := createTestPersistentQueueWithRequestsCapacity(t, ext, 1000) + assert.Equal(t, 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)) + assert.Equal(t, 2, ps.Size()) + // TODO: Remove this, after the initialization writes the readIndex. + _, _, _ = ps.getNextItem(context.Background()) + assert.NoError(t, ps.Shutdown(context.Background())) + + newPs := createTestPersistentQueueWithRequestsCapacity(t, ext, 1000) + require.Equal(t, 2, newPs.Size()) + + // Let's read both of the elements we put + newPs.Consume(func(_ context.Context, traces tracesRequest) error { + require.Equal(t, req, traces) + return nil + }) + assert.Equal(t, 1, newPs.Size()) + + newPs.Consume(func(_ context.Context, traces tracesRequest) error { + require.Equal(t, req, traces) + return nil + }) + require.Equal(t, 0, newPs.Size()) + assert.NoError(t, newPs.Shutdown(context.Background())) +} + +func BenchmarkPersistentQueue_TraceSpans(b *testing.B) { + cases := []struct { + numTraces int + numSpansPerTrace int + }{ + { + numTraces: 1, + numSpansPerTrace: 1, + }, + { + numTraces: 1, + numSpansPerTrace: 10, + }, + { + numTraces: 10, + numSpansPerTrace: 10, + }, + } + + for _, c := range cases { + b.Run(fmt.Sprintf("#traces: %d #spansPerTrace: %d", c.numTraces, c.numSpansPerTrace), func(bb *testing.B) { + ext := NewMockStorageExtension(nil) + ps := createTestPersistentQueueWithRequestsCapacity(b, ext, 10000000) + + req := newTracesRequest(c.numTraces, c.numSpansPerTrace) + + bb.ReportAllocs() + bb.ResetTimer() + + for i := 0; i < bb.N; i++ { + require.NoError(bb, ps.Offer(context.Background(), req)) + } + + for i := 0; i < bb.N; i++ { + require.True(bb, ps.Consume(func(context.Context, tracesRequest) error { return nil })) + } + require.NoError(b, ext.Shutdown(context.Background())) + }) + } +} + +func TestItemIndexMarshaling(t *testing.T) { + cases := []struct { + in uint64 + out uint64 + }{ + { + in: 0, + out: 0, + }, + { + in: 1, + out: 1, + }, + { + in: 0xFFFFFFFFFFFFFFFF, + out: 0xFFFFFFFFFFFFFFFF, + }, + } + + for _, c := range cases { + t.Run(fmt.Sprintf("#elements:%v", c.in), func(*testing.T) { + buf := itemIndexToBytes(c.in) + out, err := bytesToItemIndex(buf) + require.NoError(t, err) + require.Equal(t, c.out, out) + }) + } +} + +func TestItemIndexArrayMarshaling(t *testing.T) { + cases := []struct { + in []uint64 + out []uint64 + }{ + { + in: []uint64{0, 1, 2}, + out: []uint64{0, 1, 2}, + }, + { + in: []uint64{}, + out: nil, + }, + { + in: nil, + out: nil, + }, + } + + for _, c := range cases { + t.Run(fmt.Sprintf("#elements:%v", c.in), func(_ *testing.T) { + buf := itemIndexArrayToBytes(c.in) + out, err := bytesToItemIndexArray(buf) + require.NoError(t, err) + require.Equal(t, c.out, out) + }) + } +} + +func TestPersistentQueue_ShutdownWhileConsuming(t *testing.T) { + ps := createTestPersistentQueueWithRequestsCapacity(t, NewMockStorageExtension(nil), 1000) + + assert.Equal(t, 0, ps.Size()) + assert.False(t, ps.client.(*mockStorageClient).isClosed()) + + assert.NoError(t, ps.Offer(context.Background(), newTracesRequest(5, 10))) + + _, onProcessingFinished, ok := ps.getNextItem(context.Background()) + require.True(t, ok) + assert.False(t, ps.client.(*mockStorageClient).isClosed()) + assert.NoError(t, ps.Shutdown(context.Background())) + assert.False(t, ps.client.(*mockStorageClient).isClosed()) + onProcessingFinished(nil) + assert.True(t, ps.client.(*mockStorageClient).isClosed()) +} + +func TestPersistentQueue_StorageFull(t *testing.T) { + req := newTracesRequest(5, 10) + marshaled, err := marshalTracesRequest(req) + require.NoError(t, err) + maxSizeInBytes := len(marshaled) * 5 // arbitrary small number + freeSpaceInBytes := 1 + + client := newFakeBoundedStorageClient(maxSizeInBytes) + ps := createTestPersistentQueueWithClient(client) + + // Put enough items in to fill the underlying storage + reqCount := 0 + for { + err = ps.Offer(context.Background(), req) + if errors.Is(err, syscall.ENOSPC) { + break + } + require.NoError(t, err) + reqCount++ + } + + // Check that the size is correct + require.Equal(t, reqCount, ps.Size(), "Size must be equal to the number of items inserted") + + // Manually set the storage to only have a small amount of free space left + newMaxSize := client.GetSizeInBytes() + freeSpaceInBytes + client.SetMaxSizeInBytes(newMaxSize) + + // Try to put an item in, should fail + require.Error(t, ps.Offer(context.Background(), req)) + + // Take out all the items + // Getting the first item fails, as we can't update the state in storage, so we just delete it without returning it + // Subsequent items succeed, as deleting the first item frees enough space for the state update + reqCount-- + for i := reqCount; i > 0; i-- { + require.True(t, ps.Consume(func(context.Context, tracesRequest) error { return nil })) + } + + // We should be able to put a new item in + // However, this will fail if deleting items fails with full storage + require.NoError(t, ps.Offer(context.Background(), req)) +} + +func TestPersistentQueue_ItemDispatchingFinish_ErrorHandling(t *testing.T) { + errDeletingItem := fmt.Errorf("error deleting item") + errUpdatingDispatched := fmt.Errorf("error updating dispatched items") + testCases := []struct { + storageErrors []error + expectedError error + description string + }{ + { + description: "no errors", + storageErrors: []error{}, + expectedError: nil, + }, + { + description: "error on first transaction, success afterwards", + storageErrors: []error{ + errUpdatingDispatched, + }, + expectedError: nil, + }, + { + description: "error on first and second transaction", + storageErrors: []error{ + errUpdatingDispatched, + errDeletingItem, + }, + expectedError: errDeletingItem, + }, + { + description: "error on first and third transaction", + storageErrors: []error{ + errUpdatingDispatched, + nil, + errUpdatingDispatched, + }, + expectedError: errUpdatingDispatched, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.description, func(t *testing.T) { + client := newFakeStorageClientWithErrors(testCase.storageErrors) + ps := createTestPersistentQueueWithClient(client) + client.Reset() + + err := ps.itemDispatchingFinish(context.Background(), 0) + + require.ErrorIs(t, err, testCase.expectedError) + }) + } +} + +func TestPersistentQueue_ItemsCapacityUsageRestoredOnShutdown(t *testing.T) { + ext := NewMockStorageExtension(nil) + pq := createTestPersistentQueueWithItemsCapacity(t, ext, 100) + + assert.Equal(t, 0, pq.Size()) + + // Fill the queue up to the capacity. + assert.NoError(t, pq.Offer(context.Background(), newTracesRequest(4, 10))) + assert.NoError(t, pq.Offer(context.Background(), newTracesRequest(4, 10))) + assert.NoError(t, pq.Offer(context.Background(), newTracesRequest(2, 10))) + assert.Equal(t, 100, pq.Size()) + + assert.ErrorIs(t, pq.Offer(context.Background(), newTracesRequest(5, 5)), ErrQueueIsFull) + assert.Equal(t, 100, pq.Size()) + + assert.True(t, pq.Consume(func(_ context.Context, traces tracesRequest) error { + assert.Equal(t, 40, traces.traces.SpanCount()) + return nil + })) + assert.Equal(t, 60, pq.Size()) + + assert.NoError(t, pq.Shutdown(context.Background())) + + newPQ := createTestPersistentQueueWithItemsCapacity(t, ext, 100) + + // The queue should be restored to the previous size. + assert.Equal(t, 60, newPQ.Size()) + + assert.NoError(t, newPQ.Offer(context.Background(), newTracesRequest(2, 5))) + + // Check the combined queue size. + assert.Equal(t, 70, newPQ.Size()) + + assert.True(t, newPQ.Consume(func(_ context.Context, traces tracesRequest) error { + assert.Equal(t, 40, traces.traces.SpanCount()) + return nil + })) + assert.Equal(t, 30, newPQ.Size()) + + assert.True(t, newPQ.Consume(func(_ context.Context, traces tracesRequest) error { + assert.Equal(t, 20, traces.traces.SpanCount()) + return nil + })) + assert.Equal(t, 10, newPQ.Size()) + + assert.NoError(t, newPQ.Shutdown(context.Background())) +} + +// This test covers the case when the items capacity queue is enabled for the first time. +func TestPersistentQueue_ItemsCapacityUsageIsNotPreserved(t *testing.T) { + ext := NewMockStorageExtension(nil) + pq := createTestPersistentQueueWithRequestsCapacity(t, ext, 100) + + assert.Equal(t, 0, pq.Size()) + + assert.NoError(t, pq.Offer(context.Background(), newTracesRequest(4, 10))) + assert.NoError(t, pq.Offer(context.Background(), newTracesRequest(2, 10))) + assert.NoError(t, pq.Offer(context.Background(), newTracesRequest(5, 5))) + assert.Equal(t, 3, pq.Size()) + + assert.True(t, pq.Consume(func(_ context.Context, traces tracesRequest) error { + assert.Equal(t, 40, traces.traces.SpanCount()) + return nil + })) + assert.Equal(t, 2, pq.Size()) + + assert.NoError(t, pq.Shutdown(context.Background())) + + newPQ := createTestPersistentQueueWithItemsCapacity(t, ext, 100) + + // The queue items size cannot be restored to the previous size. Falls back to 0. + assert.Equal(t, 0, newPQ.Size()) + + assert.NoError(t, newPQ.Offer(context.Background(), newTracesRequest(2, 5))) + + // Only new items are reflected + assert.Equal(t, 10, newPQ.Size()) + + // Consuming old items should does not affect the size. + assert.True(t, newPQ.Consume(func(_ context.Context, traces tracesRequest) error { + assert.Equal(t, 20, traces.traces.SpanCount()) + return nil + })) + assert.Equal(t, 10, newPQ.Size()) + + assert.True(t, newPQ.Consume(func(_ context.Context, traces tracesRequest) error { + assert.Equal(t, 25, traces.traces.SpanCount()) + return nil + })) + assert.Equal(t, 10, newPQ.Size()) + + assert.True(t, newPQ.Consume(func(_ context.Context, traces tracesRequest) error { + assert.Equal(t, 10, traces.traces.SpanCount()) + return nil + })) + assert.Equal(t, 0, newPQ.Size()) + + assert.NoError(t, newPQ.Shutdown(context.Background())) +} + +func requireCurrentlyDispatchedItemsEqual(t *testing.T, pq *persistentQueue[tracesRequest], compare []uint64) { + pq.mu.Lock() + defer pq.mu.Unlock() + assert.ElementsMatch(t, compare, pq.currentlyDispatchedItems) +} diff --git a/exporter/internal/queue/queue.go b/exporter/internal/queue/queue.go new file mode 100644 index 00000000000..0ae0703b05d --- /dev/null +++ b/exporter/internal/queue/queue.go @@ -0,0 +1,36 @@ +// Copyright The OpenTelemetry Authors +// Copyright (c) 2019 The Jaeger Authors. +// Copyright (c) 2017 Uber Technologies, Inc. +// SPDX-License-Identifier: Apache-2.0 + +package queue // import "go.opentelemetry.io/collector/exporter/internal/queue" + +import ( + "context" + "errors" + + "go.opentelemetry.io/collector/component" +) + +var ( + // ErrQueueIsFull is the error returned when an item is offered to the Queue and the queue is full. + ErrQueueIsFull = errors.New("sending queue is full") +) + +// 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) +type Queue[T any] interface { + component.Component + // Offer inserts the specified element into this queue if it is possible to do so immediately + // without violating capacity restrictions. If success returns no error. + // It returns ErrQueueIsFull if no space is currently available. + Offer(ctx context.Context, item T) error + // Consume applies the provided function on the head of queue. + // The call blocks until there is an item available or the queue is stopped. + // The function returns true when an item is consumed or false if the queue is stopped. + Consume(func(ctx context.Context, item T) error) bool + // Size returns the current Size of the queue + Size() int + // Capacity returns the capacity of the queue. + Capacity() int +} diff --git a/exporter/internal/queue/queue_capacity.go b/exporter/internal/queue/queue_capacity.go new file mode 100644 index 00000000000..1995febcd63 --- /dev/null +++ b/exporter/internal/queue/queue_capacity.go @@ -0,0 +1,74 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package queue // import "go.opentelemetry.io/collector/exporter/internal/queue" + +import ( + "sync/atomic" +) + +type itemsCounter interface { + ItemsCount() int +} + +// Sizer is an interface that returns the size of the given element. +type Sizer[T any] interface { + SizeOf(T) uint64 +} + +// ItemsSizer is a Sizer implementation that returns the size of a queue element as the number of items it contains. +type ItemsSizer[T itemsCounter] struct{} + +func (is *ItemsSizer[T]) SizeOf(el T) uint64 { + return uint64(el.ItemsCount()) +} + +// RequestSizer is a Sizer implementation that returns the size of a queue element as one request. +type RequestSizer[T any] struct{} + +func (rs *RequestSizer[T]) SizeOf(T) uint64 { + return 1 +} + +type queueCapacityLimiter[T any] struct { + used *atomic.Uint64 + cap uint64 + sz Sizer[T] +} + +func (bcl queueCapacityLimiter[T]) Capacity() int { + return int(bcl.cap) +} + +func (bcl queueCapacityLimiter[T]) Size() int { + return int(bcl.used.Load()) +} + +func (bcl queueCapacityLimiter[T]) claim(el T) bool { + size := bcl.sizeOf(el) + if bcl.used.Add(size) > bcl.cap { + bcl.releaseSize(size) + return false + } + return true +} + +func (bcl queueCapacityLimiter[T]) release(el T) { + bcl.releaseSize(bcl.sizeOf(el)) +} + +func (bcl queueCapacityLimiter[T]) releaseSize(size uint64) { + bcl.used.Add(^(size - 1)) +} + +func (bcl queueCapacityLimiter[T]) sizeOf(el T) uint64 { + return bcl.sz.SizeOf(el) +} + +func newQueueCapacityLimiter[T any](sizer Sizer[T], capacity int) *queueCapacityLimiter[T] { + return &queueCapacityLimiter[T]{ + used: &atomic.Uint64{}, + cap: uint64(capacity), + sz: sizer, + } +} diff --git a/exporter/internal/queue/queue_capacity_test.go b/exporter/internal/queue/queue_capacity_test.go new file mode 100644 index 00000000000..3dd6ad2b898 --- /dev/null +++ b/exporter/internal/queue/queue_capacity_test.go @@ -0,0 +1,58 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package queue + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRequestsCapacityLimiter(t *testing.T) { + rl := newQueueCapacityLimiter[fakeReq](&RequestSizer[fakeReq]{}, 2) + assert.Equal(t, 0, rl.Size()) + assert.Equal(t, 2, rl.Capacity()) + + req := fakeReq{itemsCount: 5} + + assert.True(t, rl.claim(req)) + assert.Equal(t, 1, rl.Size()) + + assert.True(t, rl.claim(req)) + assert.Equal(t, 2, rl.Size()) + + assert.False(t, rl.claim(req)) + assert.Equal(t, 2, rl.Size()) + + rl.release(req) + assert.Equal(t, 1, rl.Size()) +} + +func TestItemsCapacityLimiter(t *testing.T) { + rl := newQueueCapacityLimiter[fakeReq](&ItemsSizer[fakeReq]{}, 7) + assert.Equal(t, 0, rl.Size()) + assert.Equal(t, 7, rl.Capacity()) + + req := fakeReq{itemsCount: 3} + + assert.True(t, rl.claim(req)) + assert.Equal(t, 3, rl.Size()) + + assert.True(t, rl.claim(req)) + assert.Equal(t, 6, rl.Size()) + + assert.False(t, rl.claim(req)) + assert.Equal(t, 6, rl.Size()) + + rl.release(req) + assert.Equal(t, 3, rl.Size()) +} + +type fakeReq struct { + itemsCount int +} + +func (r fakeReq) ItemsCount() int { + return r.itemsCount +} diff --git a/exporter/loggingexporter/README.md b/exporter/loggingexporter/README.md index b45701bce3e..f6b7d9d9859 100644 --- a/exporter/loggingexporter/README.md +++ b/exporter/loggingexporter/README.md @@ -1,10 +1,16 @@ # Logging Exporter -| Status | | -| ------------------------ |-----------------------| -| Stability | [Deprecated] | -| Supported pipeline types | traces, metrics, logs | -| Distributions | [core], [contrib] | + +| Status | | +| ------------- |-----------| +| Stability | [deprecated]: traces, metrics, logs | +| Distributions | [core], [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aexporter%2Flogging%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aexporter%2Flogging) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aexporter%2Flogging%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aexporter%2Flogging) | + +[deprecated]: https://github.com/open-telemetry/opentelemetry-collector#deprecated +[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + This exporter is being deprecated in favour of the [debug exporter]. It will be removed in September 2024. @@ -43,7 +49,4 @@ exporters: sampling_thereafter: 200 ``` -[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib -[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol -[Deprecated]: https://github.com/open-telemetry/opentelemetry-collector#deprecated [debug exporter]: ../debugexporter/README.md diff --git a/exporter/loggingexporter/config.go b/exporter/loggingexporter/config.go index 469286b111d..d35cdd6fa4d 100644 --- a/exporter/loggingexporter/config.go +++ b/exporter/loggingexporter/config.go @@ -65,7 +65,7 @@ func (cfg *Config) Unmarshal(conf *confmap.Conf) error { return fmt.Errorf("'loglevel' and 'verbosity' are incompatible. Use only 'verbosity' instead") } - if err := conf.Unmarshal(cfg, confmap.WithErrorUnused()); err != nil { + if err := conf.Unmarshal(cfg); err != nil { return err } diff --git a/exporter/loggingexporter/doc.go b/exporter/loggingexporter/doc.go index bcbf2babaa4..3a5c01850d9 100644 --- a/exporter/loggingexporter/doc.go +++ b/exporter/loggingexporter/doc.go @@ -1,5 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +//go:generate mdatagen metadata.yaml + // Package loggingexporter exports data to console as logs. package loggingexporter // import "go.opentelemetry.io/collector/exporter/loggingexporter" diff --git a/exporter/loggingexporter/factory.go b/exporter/loggingexporter/factory.go index b2d4ec8fe79..1f38b315db0 100644 --- a/exporter/loggingexporter/factory.go +++ b/exporter/loggingexporter/factory.go @@ -12,11 +12,13 @@ import ( "go.opentelemetry.io/collector/config/configtelemetry" "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/internal/common" + "go.opentelemetry.io/collector/exporter/loggingexporter/internal/metadata" ) +// The value of "type" key in configuration. +var componentType = component.MustNewType("logging") + const ( - // The value of "type" key in configuration. - typeStr = "logging" defaultSamplingInitial = 2 defaultSamplingThereafter = 500 ) @@ -24,11 +26,11 @@ const ( // NewFactory creates a factory for Logging exporter func NewFactory() exporter.Factory { return exporter.NewFactory( - typeStr, + componentType, createDefaultConfig, - exporter.WithTraces(createTracesExporter, component.StabilityLevelDeprecated), - exporter.WithMetrics(createMetricsExporter, component.StabilityLevelDeprecated), - exporter.WithLogs(createLogsExporter, component.StabilityLevelDeprecated), + exporter.WithTraces(createTracesExporter, metadata.TracesStability), + exporter.WithMetrics(createMetricsExporter, metadata.MetricsStability), + exporter.WithLogs(createLogsExporter, metadata.LogsStability), ) } diff --git a/exporter/loggingexporter/go.mod b/exporter/loggingexporter/go.mod index 1a026a883eb..97dac63f6aa 100644 --- a/exporter/loggingexporter/go.mod +++ b/exporter/loggingexporter/go.mod @@ -1,52 +1,60 @@ // Deprecated: loggingexporter is deprecated in favour of the debugexporter. It will be removed in September 2024. module go.opentelemetry.io/collector/exporter/loggingexporter -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 - go.opentelemetry.io/collector/confmap v0.85.0 - go.opentelemetry.io/collector/exporter v0.85.0 - go.uber.org/zap v1.26.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 + go.opentelemetry.io/collector/confmap v0.96.0 + go.opentelemetry.io/collector/exporter v0.96.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 + go.uber.org/zap v1.27.0 ) require ( + github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector v0.85.0 // indirect - go.opentelemetry.io/collector/consumer v0.85.0 // indirect - go.opentelemetry.io/collector/extension v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/sdk v1.18.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector v0.96.0 // indirect + go.opentelemetry.io/collector/config/configretry v0.96.0 // indirect + go.opentelemetry.io/collector/consumer v0.96.0 // indirect + go.opentelemetry.io/collector/extension v0.96.0 // indirect + go.opentelemetry.io/collector/pdata v1.3.0 // indirect + go.opentelemetry.io/collector/receiver v0.96.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -66,23 +74,13 @@ replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata -replace go.opentelemetry.io/collector/processor => ../../processor - replace go.opentelemetry.io/collector/receiver => ../../receiver -replace go.opentelemetry.io/collector/semconv => ../../semconv - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension - retract ( v0.76.0 // Depends on retracted pdata v1.0.0-rc10 module, use v0.76.1 v0.69.0 // Release failed, use v0.69.1 ) -replace go.opentelemetry.io/collector/connector => ../../connector - -replace go.opentelemetry.io/collector/config/confignet => ../../config/confignet - replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry -replace go.opentelemetry.io/collector/service => ../../service +replace go.opentelemetry.io/collector/config/configretry => ../../config/configretry diff --git a/exporter/loggingexporter/go.sum b/exporter/loggingexporter/go.sum index 56e97816e75..dbdb92fd3bb 100644 --- a/exporter/loggingexporter/go.sum +++ b/exporter/loggingexporter/go.sum @@ -1,55 +1,28 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -58,15 +31,14 @@ github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NI github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -76,83 +48,64 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -160,38 +113,16 @@ 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/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/exporter/loggingexporter/internal/metadata/generated_status.go b/exporter/loggingexporter/internal/metadata/generated_status.go new file mode 100644 index 00000000000..64c84dcae1f --- /dev/null +++ b/exporter/loggingexporter/internal/metadata/generated_status.go @@ -0,0 +1,29 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("logging") + scopeName = "go.opentelemetry.io/collector/exporter/loggingexporter" +) + +const ( + TracesStability = component.StabilityLevelDeprecated + MetricsStability = component.StabilityLevelDeprecated + LogsStability = component.StabilityLevelDeprecated +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} diff --git a/exporter/loggingexporter/metadata.yaml b/exporter/loggingexporter/metadata.yaml new file mode 100644 index 00000000000..165fa39f173 --- /dev/null +++ b/exporter/loggingexporter/metadata.yaml @@ -0,0 +1,7 @@ +type: logging + +status: + class: exporter + stability: + deprecated: [traces, metrics, logs] + distributions: [core, contrib] diff --git a/exporter/loggingexporter/package_test.go b/exporter/loggingexporter/package_test.go new file mode 100644 index 00000000000..0c1b40739cc --- /dev/null +++ b/exporter/loggingexporter/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package loggingexporter + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/exporter/otlpexporter/README.md b/exporter/otlpexporter/README.md index 9dc48422026..8926a14369b 100644 --- a/exporter/otlpexporter/README.md +++ b/exporter/otlpexporter/README.md @@ -1,12 +1,18 @@ # OTLP gRPC Exporter -| Status | | -| ------------------------ | --------------------- | -| Stability | traces [stable] | -| | metrics [stable] | -| | logs [beta] | -| Supported pipeline types | traces, metrics, logs | -| Distributions | [core], [contrib] | + +| Status | | +| ------------- |-----------| +| Stability | [beta]: logs | +| | [stable]: traces, metrics | +| Distributions | [core], [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aexporter%2Fotlp%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aexporter%2Fotlp) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aexporter%2Fotlp%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aexporter%2Fotlp) | + +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[stable]: https://github.com/open-telemetry/opentelemetry-collector#stable +[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + Export data via gRPC using [OTLP]( https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md) @@ -53,8 +59,3 @@ Several helper files are leveraged to provide additional capabilities automatica - [gRPC settings](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/configgrpc/README.md) - [TLS and mTLS settings](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/configtls/README.md) - [Queuing, retry and timeout settings](https://github.com/open-telemetry/opentelemetry-collector/blob/main/exporter/exporterhelper/README.md) - -[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta -[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib -[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol -[stable]: https://github.com/open-telemetry/opentelemetry-collector#stable diff --git a/exporter/otlpexporter/config.go b/exporter/otlpexporter/config.go index d276f6e7c87..61440c3a9e3 100644 --- a/exporter/otlpexporter/config.go +++ b/exporter/otlpexporter/config.go @@ -4,29 +4,28 @@ package otlpexporter // import "go.opentelemetry.io/collector/exporter/otlpexporter" import ( - "fmt" + "errors" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configgrpc" + "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/exporter/exporterhelper" ) // Config defines configuration for OTLP exporter. type Config struct { - exporterhelper.TimeoutSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. - exporterhelper.QueueSettings `mapstructure:"sending_queue"` - exporterhelper.RetrySettings `mapstructure:"retry_on_failure"` + exporterhelper.TimeoutSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. + QueueConfig exporterhelper.QueueSettings `mapstructure:"sending_queue"` + RetryConfig configretry.BackOffConfig `mapstructure:"retry_on_failure"` - configgrpc.GRPCClientSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. + configgrpc.ClientConfig `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. } -var _ component.Config = (*Config)(nil) - -// Validate checks if the exporter configuration is valid -func (cfg *Config) Validate() error { - if err := cfg.QueueSettings.Validate(); err != nil { - return fmt.Errorf("queue settings has invalid configuration: %w", err) +func (c *Config) Validate() error { + if c.SanitizedEndpoint() == "" { + return errors.New(`requires a non-empty "endpoint"`) } - return nil } + +var _ component.Config = (*Config)(nil) diff --git a/exporter/otlpexporter/config_test.go b/exporter/otlpexporter/config_test.go index ebc1789a41e..c024eb0af88 100644 --- a/exporter/otlpexporter/config_test.go +++ b/exporter/otlpexporter/config_test.go @@ -15,6 +15,7 @@ import ( "go.opentelemetry.io/collector/config/configauth" "go.opentelemetry.io/collector/config/configgrpc" "go.opentelemetry.io/collector/config/configopaque" + "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/config/configtls" "go.opentelemetry.io/collector/confmap" "go.opentelemetry.io/collector/confmap/confmaptest" @@ -39,7 +40,7 @@ func TestUnmarshalConfig(t *testing.T) { TimeoutSettings: exporterhelper.TimeoutSettings{ Timeout: 10 * time.Second, }, - RetrySettings: exporterhelper.RetrySettings{ + RetryConfig: configretry.BackOffConfig{ Enabled: true, InitialInterval: 10 * time.Second, RandomizationFactor: 0.7, @@ -47,12 +48,12 @@ func TestUnmarshalConfig(t *testing.T) { MaxInterval: 1 * time.Minute, MaxElapsedTime: 10 * time.Minute, }, - QueueSettings: exporterhelper.QueueSettings{ + QueueConfig: exporterhelper.QueueSettings{ Enabled: true, NumConsumers: 2, QueueSize: 10, }, - GRPCClientSettings: configgrpc.GRPCClientSettings{ + ClientConfig: configgrpc.ClientConfig{ Headers: map[string]configopaque.String{ "can you have a . here?": "F0000000-0000-0000-0000-000000000000", "header1": "234", @@ -60,8 +61,8 @@ func TestUnmarshalConfig(t *testing.T) { }, Endpoint: "1.2.3.4:1234", Compression: "gzip", - TLSSetting: configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: "/var/lib/mycert.pem", }, Insecure: false, @@ -73,7 +74,43 @@ func TestUnmarshalConfig(t *testing.T) { }, WriteBufferSize: 512 * 1024, BalancerName: "round_robin", - Auth: &configauth.Authentication{AuthenticatorID: component.NewID("nop")}, + Auth: &configauth.Authentication{AuthenticatorID: component.MustNewID("nop")}, }, }, cfg) } + +func TestUnmarshalInvalidConfig(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "invalid_configs.yaml")) + require.NoError(t, err) + factory := NewFactory() + for _, test := range []struct { + name string + errorMsg string + }{ + { + name: "no_endpoint", + errorMsg: `requires a non-empty "endpoint"`, + }, + { + name: "http_endpoint", + errorMsg: `requires a non-empty "endpoint"`, + }, + { + name: "invalid_timeout", + errorMsg: `'timeout' must be non-negative`, + }, + { + name: "invalid_retry", + errorMsg: `'randomization_factor' must be within [0, 1]`, + }, + } { + t.Run(test.name, func(t *testing.T) { + cfg := factory.CreateDefaultConfig() + sub, err := cm.Sub(test.name) + require.NoError(t, err) + assert.NoError(t, component.UnmarshalConfig(sub, cfg)) + assert.ErrorContains(t, component.ValidateConfig(cfg), test.errorMsg) + }) + } + +} diff --git a/exporter/otlpexporter/doc.go b/exporter/otlpexporter/doc.go index 5fad358a654..3f09a753285 100644 --- a/exporter/otlpexporter/doc.go +++ b/exporter/otlpexporter/doc.go @@ -1,5 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +//go:generate mdatagen metadata.yaml + // Package otlpexporter exports data by using the OTLP format to a gPRC endpoint. package otlpexporter // import "go.opentelemetry.io/collector/exporter/otlpexporter" diff --git a/exporter/otlpexporter/factory.go b/exporter/otlpexporter/factory.go index 3980216331a..8a72aab8cdc 100644 --- a/exporter/otlpexporter/factory.go +++ b/exporter/otlpexporter/factory.go @@ -10,36 +10,33 @@ import ( "go.opentelemetry.io/collector/config/configcompression" "go.opentelemetry.io/collector/config/configgrpc" "go.opentelemetry.io/collector/config/configopaque" + "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exporterhelper" -) - -const ( - // The value of "type" key in configuration. - typeStr = "otlp" + "go.opentelemetry.io/collector/exporter/otlpexporter/internal/metadata" ) // NewFactory creates a factory for OTLP exporter. func NewFactory() exporter.Factory { return exporter.NewFactory( - typeStr, + metadata.Type, createDefaultConfig, - exporter.WithTraces(createTracesExporter, component.StabilityLevelStable), - exporter.WithMetrics(createMetricsExporter, component.StabilityLevelStable), - exporter.WithLogs(createLogsExporter, component.StabilityLevelBeta), + exporter.WithTraces(createTracesExporter, metadata.TracesStability), + exporter.WithMetrics(createMetricsExporter, metadata.MetricsStability), + exporter.WithLogs(createLogsExporter, metadata.LogsStability), ) } func createDefaultConfig() component.Config { return &Config{ TimeoutSettings: exporterhelper.NewDefaultTimeoutSettings(), - RetrySettings: exporterhelper.NewDefaultRetrySettings(), - QueueSettings: exporterhelper.NewDefaultQueueSettings(), - GRPCClientSettings: configgrpc.GRPCClientSettings{ + RetryConfig: configretry.NewDefaultBackOffConfig(), + QueueConfig: exporterhelper.NewDefaultQueueSettings(), + ClientConfig: configgrpc.ClientConfig{ Headers: map[string]configopaque.String{}, // Default to gzip compression - Compression: configcompression.Gzip, + Compression: configcompression.TypeGzip, // We almost read 0 bytes, so no need to tune ReadBufferSize. WriteBufferSize: 512 * 1024, }, @@ -51,17 +48,14 @@ func createTracesExporter( set exporter.CreateSettings, cfg component.Config, ) (exporter.Traces, error) { - oce, err := newExporter(cfg, set) - if err != nil { - return nil, err - } + oce := newExporter(cfg, set) oCfg := cfg.(*Config) return exporterhelper.NewTracesExporter(ctx, set, cfg, oce.pushTraces, exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), exporterhelper.WithTimeout(oCfg.TimeoutSettings), - exporterhelper.WithRetry(oCfg.RetrySettings), - exporterhelper.WithQueue(oCfg.QueueSettings), + exporterhelper.WithRetry(oCfg.RetryConfig), + exporterhelper.WithQueue(oCfg.QueueConfig), exporterhelper.WithStart(oce.start), exporterhelper.WithShutdown(oce.shutdown)) } @@ -71,17 +65,14 @@ func createMetricsExporter( set exporter.CreateSettings, cfg component.Config, ) (exporter.Metrics, error) { - oce, err := newExporter(cfg, set) - if err != nil { - return nil, err - } + oce := newExporter(cfg, set) oCfg := cfg.(*Config) return exporterhelper.NewMetricsExporter(ctx, set, cfg, oce.pushMetrics, exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), exporterhelper.WithTimeout(oCfg.TimeoutSettings), - exporterhelper.WithRetry(oCfg.RetrySettings), - exporterhelper.WithQueue(oCfg.QueueSettings), + exporterhelper.WithRetry(oCfg.RetryConfig), + exporterhelper.WithQueue(oCfg.QueueConfig), exporterhelper.WithStart(oce.start), exporterhelper.WithShutdown(oce.shutdown), ) @@ -92,17 +83,14 @@ func createLogsExporter( set exporter.CreateSettings, cfg component.Config, ) (exporter.Logs, error) { - oce, err := newExporter(cfg, set) - if err != nil { - return nil, err - } + oce := newExporter(cfg, set) oCfg := cfg.(*Config) return exporterhelper.NewLogsExporter(ctx, set, cfg, oce.pushLogs, exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), exporterhelper.WithTimeout(oCfg.TimeoutSettings), - exporterhelper.WithRetry(oCfg.RetrySettings), - exporterhelper.WithQueue(oCfg.QueueSettings), + exporterhelper.WithRetry(oCfg.RetryConfig), + exporterhelper.WithQueue(oCfg.QueueConfig), exporterhelper.WithStart(oce.start), exporterhelper.WithShutdown(oce.shutdown), ) diff --git a/exporter/otlpexporter/factory_test.go b/exporter/otlpexporter/factory_test.go index 4ebb0e283ba..45db95986b4 100644 --- a/exporter/otlpexporter/factory_test.go +++ b/exporter/otlpexporter/factory_test.go @@ -16,6 +16,7 @@ import ( "go.opentelemetry.io/collector/config/configcompression" "go.opentelemetry.io/collector/config/configgrpc" "go.opentelemetry.io/collector/config/configopaque" + "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/config/configtls" "go.opentelemetry.io/collector/exporter/exporterhelper" "go.opentelemetry.io/collector/exporter/exportertest" @@ -29,16 +30,16 @@ func TestCreateDefaultConfig(t *testing.T) { assert.NoError(t, componenttest.CheckConfigStruct(cfg)) ocfg, ok := factory.CreateDefaultConfig().(*Config) assert.True(t, ok) - assert.Equal(t, ocfg.RetrySettings, exporterhelper.NewDefaultRetrySettings()) - assert.Equal(t, ocfg.QueueSettings, exporterhelper.NewDefaultQueueSettings()) + assert.Equal(t, ocfg.RetryConfig, configretry.NewDefaultBackOffConfig()) + assert.Equal(t, ocfg.QueueConfig, exporterhelper.NewDefaultQueueSettings()) assert.Equal(t, ocfg.TimeoutSettings, exporterhelper.NewDefaultTimeoutSettings()) - assert.Equal(t, ocfg.Compression, configcompression.Gzip) + assert.Equal(t, ocfg.Compression, configcompression.TypeGzip) } func TestCreateMetricsExporter(t *testing.T) { factory := NewFactory() cfg := factory.CreateDefaultConfig().(*Config) - cfg.GRPCClientSettings.Endpoint = testutil.GetAvailableLocalAddress(t) + cfg.ClientConfig.Endpoint = testutil.GetAvailableLocalAddress(t) set := exportertest.NewNopCreateSettings() oexp, err := factory.CreateMetricsExporter(context.Background(), set, cfg) @@ -49,26 +50,16 @@ func TestCreateMetricsExporter(t *testing.T) { func TestCreateTracesExporter(t *testing.T) { endpoint := testutil.GetAvailableLocalAddress(t) tests := []struct { - name string - config *Config - mustFailOnCreate bool - mustFailOnStart bool + name string + config *Config + mustFailOnStart bool }{ - { - name: "NoEndpoint", - config: &Config{ - GRPCClientSettings: configgrpc.GRPCClientSettings{ - Endpoint: "", - }, - }, - mustFailOnCreate: true, - }, { name: "UseSecure", config: &Config{ - GRPCClientSettings: configgrpc.GRPCClientSettings{ + ClientConfig: configgrpc.ClientConfig{ Endpoint: endpoint, - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: false, }, }, @@ -77,7 +68,7 @@ func TestCreateTracesExporter(t *testing.T) { { name: "Keepalive", config: &Config{ - GRPCClientSettings: configgrpc.GRPCClientSettings{ + ClientConfig: configgrpc.ClientConfig{ Endpoint: endpoint, Keepalive: &configgrpc.KeepaliveClientConfig{ Time: 30 * time.Second, @@ -90,7 +81,7 @@ func TestCreateTracesExporter(t *testing.T) { { name: "NoneCompression", config: &Config{ - GRPCClientSettings: configgrpc.GRPCClientSettings{ + ClientConfig: configgrpc.ClientConfig{ Endpoint: endpoint, Compression: "none", }, @@ -99,34 +90,34 @@ func TestCreateTracesExporter(t *testing.T) { { name: "GzipCompression", config: &Config{ - GRPCClientSettings: configgrpc.GRPCClientSettings{ + ClientConfig: configgrpc.ClientConfig{ Endpoint: endpoint, - Compression: configcompression.Gzip, + Compression: configcompression.TypeGzip, }, }, }, { name: "SnappyCompression", config: &Config{ - GRPCClientSettings: configgrpc.GRPCClientSettings{ + ClientConfig: configgrpc.ClientConfig{ Endpoint: endpoint, - Compression: configcompression.Snappy, + Compression: configcompression.TypeSnappy, }, }, }, { name: "ZstdCompression", config: &Config{ - GRPCClientSettings: configgrpc.GRPCClientSettings{ + ClientConfig: configgrpc.ClientConfig{ Endpoint: endpoint, - Compression: configcompression.Zstd, + Compression: configcompression.TypeZstd, }, }, }, { name: "Headers", config: &Config{ - GRPCClientSettings: configgrpc.GRPCClientSettings{ + ClientConfig: configgrpc.ClientConfig{ Endpoint: endpoint, Headers: map[string]configopaque.String{ "hdr1": "val1", @@ -138,7 +129,7 @@ func TestCreateTracesExporter(t *testing.T) { { name: "NumConsumers", config: &Config{ - GRPCClientSettings: configgrpc.GRPCClientSettings{ + ClientConfig: configgrpc.ClientConfig{ Endpoint: endpoint, }, }, @@ -146,10 +137,10 @@ func TestCreateTracesExporter(t *testing.T) { { name: "CaCert", config: &Config{ - GRPCClientSettings: configgrpc.GRPCClientSettings{ + ClientConfig: configgrpc.ClientConfig{ Endpoint: endpoint, - TLSSetting: configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "test_cert.pem"), }, }, @@ -159,10 +150,10 @@ func TestCreateTracesExporter(t *testing.T) { { name: "CertPemFileError", config: &Config{ - GRPCClientSettings: configgrpc.GRPCClientSettings{ + ClientConfig: configgrpc.ClientConfig{ Endpoint: endpoint, - TLSSetting: configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: "nosuchfile", }, }, @@ -177,10 +168,6 @@ func TestCreateTracesExporter(t *testing.T) { factory := NewFactory() set := exportertest.NewNopCreateSettings() consumer, err := factory.CreateTracesExporter(context.Background(), set, tt.config) - if tt.mustFailOnCreate { - assert.NotNil(t, err) - return - } assert.NoError(t, err) assert.NotNil(t, consumer) err = consumer.Start(context.Background(), componenttest.NewNopHost()) @@ -203,7 +190,7 @@ func TestCreateTracesExporter(t *testing.T) { func TestCreateLogsExporter(t *testing.T) { factory := NewFactory() cfg := factory.CreateDefaultConfig().(*Config) - cfg.GRPCClientSettings.Endpoint = testutil.GetAvailableLocalAddress(t) + cfg.ClientConfig.Endpoint = testutil.GetAvailableLocalAddress(t) set := exportertest.NewNopCreateSettings() oexp, err := factory.CreateLogsExporter(context.Background(), set, cfg) diff --git a/exporter/otlpexporter/go.mod b/exporter/otlpexporter/go.mod index c0f1eae71a1..8762e4cc0f9 100644 --- a/exporter/otlpexporter/go.mod +++ b/exporter/otlpexporter/go.mod @@ -1,66 +1,82 @@ module go.opentelemetry.io/collector/exporter/otlpexporter -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/configauth v0.85.0 - go.opentelemetry.io/collector/config/configcompression v0.85.0 - go.opentelemetry.io/collector/config/configgrpc v0.85.0 - go.opentelemetry.io/collector/config/configopaque v0.85.0 - go.opentelemetry.io/collector/config/configtls v0.85.0 - go.opentelemetry.io/collector/confmap v0.85.0 - go.opentelemetry.io/collector/consumer v0.85.0 - go.opentelemetry.io/collector/exporter v0.85.0 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 - google.golang.org/grpc v1.58.1 - google.golang.org/protobuf v1.31.0 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/configauth v0.96.0 + go.opentelemetry.io/collector/config/configcompression v0.96.0 + go.opentelemetry.io/collector/config/configgrpc v0.96.0 + go.opentelemetry.io/collector/config/configopaque v1.3.0 + go.opentelemetry.io/collector/config/configretry v0.96.0 + go.opentelemetry.io/collector/config/configtls v0.96.0 + go.opentelemetry.io/collector/confmap v0.96.0 + go.opentelemetry.io/collector/consumer v0.96.0 + go.opentelemetry.io/collector/exporter v0.96.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 + go.uber.org/zap v1.27.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 + google.golang.org/grpc v1.62.0 + google.golang.org/protobuf v1.32.0 ) require ( - cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68 // indirect + github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.0 // indirect + github.com/klauspost/compress v1.17.4 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/mostynb/go-grpc-compression v1.2.1 // indirect + github.com/mostynb/go-grpc-compression v1.2.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/config/confignet v0.85.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 // indirect - go.opentelemetry.io/collector/config/internal v0.85.0 // indirect - go.opentelemetry.io/collector/extension v0.85.0 // indirect - go.opentelemetry.io/collector/extension/auth v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/service v0.0.0-20230915215502-07938f20fcc7 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/sdk v1.18.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector/config/confignet v0.96.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/config/internal v0.96.0 // indirect + go.opentelemetry.io/collector/extension v0.96.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.96.0 // indirect + go.opentelemetry.io/collector/featuregate v1.3.0 // indirect + go.opentelemetry.io/collector/receiver v0.96.0 // indirect + go.opentelemetry.io/contrib/config v0.4.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -94,16 +110,8 @@ replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata -replace go.opentelemetry.io/collector/processor => ../../processor - replace go.opentelemetry.io/collector/receiver => ../../receiver -replace go.opentelemetry.io/collector/semconv => ../../semconv - -replace go.opentelemetry.io/collector/service => ../../service - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension - replace go.opentelemetry.io/collector/consumer => ../../consumer retract ( @@ -111,6 +119,6 @@ retract ( v0.69.0 // Release failed, use v0.69.1 ) -replace go.opentelemetry.io/collector/connector => ../../connector - replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry + +replace go.opentelemetry.io/collector/config/configretry => ../../config/configretry diff --git a/exporter/otlpexporter/go.sum b/exporter/otlpexporter/go.sum index 201aa810ed2..d617159313d 100644 --- a/exporter/otlpexporter/go.sum +++ b/exporter/otlpexporter/go.sum @@ -1,84 +1,62 @@ -cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68 h1:aRVqY1p2IJaBGStWMsQMpkAa83cPkCDLl80eOj0Rbz4= cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68/go.mod h1:1a3eRNYX12fs5UABBIXS8HXVvQbX9hRB/RkEBPORpe8= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -86,91 +64,84 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mostynb/go-grpc-compression v1.2.1 h1:16tdYxBZSD8p9AUmvw4F7Nyc2T4/eE7XsIXrgxSEcJI= -github.com/mostynb/go-grpc-compression v1.2.1/go.mod h1:oidYvYyefMmhcuvU8fLJ8FfZyTyVzJ6SkmD5fIKgRe8= +github.com/mostynb/go-grpc-compression v1.2.2 h1:XaDbnRvt2+1vgr0b/l0qh4mJAfIxE0bKXtz2Znl3GGI= +github.com/mostynb/go-grpc-compression v1.2.2/go.mod h1:GOCr2KBxXcblCuczg3YdLQlcin1/NfyDA348ckuCH6w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/contrib/config v0.4.0 h1:Xb+ncYOqseLroMuBesGNRgVQolXcXOhMj7EhGwJCdHs= +go.opentelemetry.io/contrib/config v0.4.0/go.mod h1:drNk2xRqLWW4/amk6Uh1S+sDAJTc7bcEEN1GfJzj418= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -178,39 +149,22 @@ 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/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/exporter/otlpexporter/internal/metadata/generated_status.go b/exporter/otlpexporter/internal/metadata/generated_status.go new file mode 100644 index 00000000000..4b0d0f0ecd5 --- /dev/null +++ b/exporter/otlpexporter/internal/metadata/generated_status.go @@ -0,0 +1,29 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("otlp") + scopeName = "go.opentelemetry.io/collector/exporter/otlpexporter" +) + +const ( + LogsStability = component.StabilityLevelBeta + TracesStability = component.StabilityLevelStable + MetricsStability = component.StabilityLevelStable +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} diff --git a/exporter/otlpexporter/metadata.yaml b/exporter/otlpexporter/metadata.yaml new file mode 100644 index 00000000000..820930b1dc5 --- /dev/null +++ b/exporter/otlpexporter/metadata.yaml @@ -0,0 +1,8 @@ +type: otlp + +status: + class: exporter + stability: + stable: [traces, metrics] + beta: [logs] + distributions: [core, contrib] diff --git a/exporter/otlpexporter/otlp.go b/exporter/otlpexporter/otlp.go index 2c60c39ee4a..21864d7723a 100644 --- a/exporter/otlpexporter/otlp.go +++ b/exporter/otlpexporter/otlp.go @@ -5,11 +5,11 @@ package otlpexporter // import "go.opentelemetry.io/collector/exporter/otlpexpor import ( "context" - "errors" "fmt" "runtime" "time" + "go.uber.org/zap" "google.golang.org/genproto/googleapis/rpc/errdetails" "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -46,37 +46,31 @@ type baseExporter struct { userAgent string } -// Crete new exporter and start it. The exporter will begin connecting but -// this function may return before the connection is established. -func newExporter(cfg component.Config, set exporter.CreateSettings) (*baseExporter, error) { +func newExporter(cfg component.Config, set exporter.CreateSettings) *baseExporter { oCfg := cfg.(*Config) - if oCfg.Endpoint == "" { - return nil, errors.New("OTLP exporter config requires an Endpoint") - } - userAgent := fmt.Sprintf("%s/%s (%s/%s)", set.BuildInfo.Description, set.BuildInfo.Version, runtime.GOOS, runtime.GOARCH) - return &baseExporter{config: oCfg, settings: set.TelemetrySettings, userAgent: userAgent}, nil + return &baseExporter{config: oCfg, settings: set.TelemetrySettings, userAgent: userAgent} } // start actually creates the gRPC connection. The client construction is deferred till this point as this // is the only place we get hold of Extensions which are required to construct auth round tripper. func (e *baseExporter) start(ctx context.Context, host component.Host) (err error) { - if e.clientConn, err = e.config.GRPCClientSettings.ToClientConn(ctx, host, e.settings, grpc.WithUserAgent(e.userAgent)); err != nil { + if e.clientConn, err = e.config.ClientConfig.ToClientConn(ctx, host, e.settings, grpc.WithUserAgent(e.userAgent)); err != nil { return err } e.traceExporter = ptraceotlp.NewGRPCClient(e.clientConn) e.metricExporter = pmetricotlp.NewGRPCClient(e.clientConn) e.logExporter = plogotlp.NewGRPCClient(e.clientConn) headers := map[string]string{} - for k, v := range e.config.GRPCClientSettings.Headers { + for k, v := range e.config.ClientConfig.Headers { headers[k] = string(v) } e.metadata = metadata.New(headers) e.callOptions = []grpc.CallOption{ - grpc.WaitForReady(e.config.GRPCClientSettings.WaitForReady), + grpc.WaitForReady(e.config.ClientConfig.WaitForReady), } return @@ -97,7 +91,10 @@ func (e *baseExporter) pushTraces(ctx context.Context, td ptrace.Traces) error { } partialSuccess := resp.PartialSuccess() if !(partialSuccess.ErrorMessage() == "" && partialSuccess.RejectedSpans() == 0) { - return consumererror.NewPermanent(fmt.Errorf("OTLP partial success: \"%s\" (%d rejected)", resp.PartialSuccess().ErrorMessage(), resp.PartialSuccess().RejectedSpans())) + e.settings.Logger.Warn("Partial success response", + zap.String("message", resp.PartialSuccess().ErrorMessage()), + zap.Int64("dropped_spans", resp.PartialSuccess().RejectedSpans()), + ) } return nil } @@ -110,7 +107,10 @@ func (e *baseExporter) pushMetrics(ctx context.Context, md pmetric.Metrics) erro } partialSuccess := resp.PartialSuccess() if !(partialSuccess.ErrorMessage() == "" && partialSuccess.RejectedDataPoints() == 0) { - return consumererror.NewPermanent(fmt.Errorf("OTLP partial success: \"%s\" (%d rejected)", resp.PartialSuccess().ErrorMessage(), resp.PartialSuccess().RejectedDataPoints())) + e.settings.Logger.Warn("Partial success response", + zap.String("message", resp.PartialSuccess().ErrorMessage()), + zap.Int64("dropped_data_points", resp.PartialSuccess().RejectedDataPoints()), + ) } return nil } @@ -123,7 +123,10 @@ func (e *baseExporter) pushLogs(ctx context.Context, ld plog.Logs) error { } partialSuccess := resp.PartialSuccess() if !(partialSuccess.ErrorMessage() == "" && partialSuccess.RejectedLogRecords() == 0) { - return consumererror.NewPermanent(fmt.Errorf("OTLP partial success: \"%s\" (%d rejected)", resp.PartialSuccess().ErrorMessage(), resp.PartialSuccess().RejectedLogRecords())) + e.settings.Logger.Warn("Partial success response", + zap.String("message", resp.PartialSuccess().ErrorMessage()), + zap.Int64("dropped_log_records", resp.PartialSuccess().RejectedLogRecords()), + ) } return nil } diff --git a/exporter/otlpexporter/otlp_test.go b/exporter/otlpexporter/otlp_test.go index 3d7d7eef6ff..d1c4f622bc0 100644 --- a/exporter/otlpexporter/otlp_test.go +++ b/exporter/otlpexporter/otlp_test.go @@ -15,6 +15,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.uber.org/zap" + "go.uber.org/zap/zaptest/observer" "google.golang.org/genproto/googleapis/rpc/errdetails" "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -234,10 +236,10 @@ func TestSendTraces(t *testing.T) { cfg := factory.CreateDefaultConfig().(*Config) // Disable queuing to ensure that we execute the request when calling ConsumeTraces // otherwise we will not see any errors. - cfg.QueueSettings.Enabled = false - cfg.GRPCClientSettings = configgrpc.GRPCClientSettings{ + cfg.QueueConfig.Enabled = false + cfg.ClientConfig = configgrpc.ClientConfig{ Endpoint: ln.Addr().String(), - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: true, }, Headers: map[string]configopaque.String{ @@ -247,6 +249,11 @@ func TestSendTraces(t *testing.T) { set := exportertest.NewNopCreateSettings() set.BuildInfo.Description = "Collector" set.BuildInfo.Version = "1.2.3test" + + // For testing the "Partial success" warning. + logger, observed := observer.New(zap.DebugLevel) + set.TelemetrySettings.Logger = zap.New(logger) + exp, err := factory.CreateTracesExporter(context.Background(), set, cfg) require.NoError(t, err) require.NotNil(t, exp) @@ -310,7 +317,9 @@ func TestSendTraces(t *testing.T) { td = testdata.GenerateTraces(2) err = exp.ConsumeTraces(context.Background(), td) - assert.Error(t, err) + assert.NoError(t, err) + assert.Len(t, observed.FilterLevelExact(zap.WarnLevel).All(), 1) + assert.Contains(t, observed.FilterLevelExact(zap.WarnLevel).All()[0].Message, "Partial success") } func TestSendTracesWhenEndpointHasHttpScheme(t *testing.T) { @@ -318,20 +327,20 @@ func TestSendTracesWhenEndpointHasHttpScheme(t *testing.T) { name string useTLS bool scheme string - gRPCClientSettings configgrpc.GRPCClientSettings + gRPCClientSettings configgrpc.ClientConfig }{ { name: "Use https scheme", useTLS: true, scheme: "https://", - gRPCClientSettings: configgrpc.GRPCClientSettings{}, + gRPCClientSettings: configgrpc.ClientConfig{}, }, { name: "Use http scheme", useTLS: false, scheme: "http://", - gRPCClientSettings: configgrpc.GRPCClientSettings{ - TLSSetting: configtls.TLSClientSetting{ + gRPCClientSettings: configgrpc.ClientConfig{ + TLSSetting: configtls.ClientConfig{ Insecure: true, }, }, @@ -351,10 +360,10 @@ func TestSendTracesWhenEndpointHasHttpScheme(t *testing.T) { // Start an OTLP exporter and point to the receiver. factory := NewFactory() cfg := factory.CreateDefaultConfig().(*Config) - cfg.GRPCClientSettings = test.gRPCClientSettings - cfg.GRPCClientSettings.Endpoint = test.scheme + ln.Addr().String() + cfg.ClientConfig = test.gRPCClientSettings + cfg.ClientConfig.Endpoint = test.scheme + ln.Addr().String() if test.useTLS { - cfg.GRPCClientSettings.TLSSetting.InsecureSkipVerify = true + cfg.ClientConfig.TLSSetting.InsecureSkipVerify = true } set := exportertest.NewNopCreateSettings() exp, err := factory.CreateTracesExporter(context.Background(), set, cfg) @@ -399,10 +408,10 @@ func TestSendMetrics(t *testing.T) { cfg := factory.CreateDefaultConfig().(*Config) // Disable queuing to ensure that we execute the request when calling ConsumeMetrics // otherwise we will not see any errors. - cfg.QueueSettings.Enabled = false - cfg.GRPCClientSettings = configgrpc.GRPCClientSettings{ + cfg.QueueConfig.Enabled = false + cfg.ClientConfig = configgrpc.ClientConfig{ Endpoint: ln.Addr().String(), - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: true, }, Headers: map[string]configopaque.String{ @@ -412,6 +421,11 @@ func TestSendMetrics(t *testing.T) { set := exportertest.NewNopCreateSettings() set.BuildInfo.Description = "Collector" set.BuildInfo.Version = "1.2.3test" + + // For testing the "Partial success" warning. + logger, observed := observer.New(zap.DebugLevel) + set.TelemetrySettings.Logger = zap.New(logger) + exp, err := factory.CreateMetricsExporter(context.Background(), set, cfg) require.NoError(t, err) require.NotNil(t, exp) @@ -484,7 +498,9 @@ func TestSendMetrics(t *testing.T) { // Send two metrics. md = testdata.GenerateMetrics(2) - assert.Error(t, exp.ConsumeMetrics(context.Background(), md)) + assert.NoError(t, exp.ConsumeMetrics(context.Background(), md)) + assert.Len(t, observed.FilterLevelExact(zap.WarnLevel).All(), 1) + assert.Contains(t, observed.FilterLevelExact(zap.WarnLevel).All()[0].Message, "Partial success") } func TestSendTraceDataServerDownAndUp(t *testing.T) { @@ -497,10 +513,10 @@ func TestSendTraceDataServerDownAndUp(t *testing.T) { cfg := factory.CreateDefaultConfig().(*Config) // Disable queuing to ensure that we execute the request when calling ConsumeTraces // otherwise we will not see the error. - cfg.QueueSettings.Enabled = false - cfg.GRPCClientSettings = configgrpc.GRPCClientSettings{ + cfg.QueueConfig.Enabled = false + cfg.ClientConfig = configgrpc.ClientConfig{ Endpoint: ln.Addr().String(), - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: true, }, // Need to wait for every request blocking until either request timeouts or succeed. @@ -558,9 +574,9 @@ func TestSendTraceDataServerStartWhileRequest(t *testing.T) { // Start an OTLP exporter and point to the receiver. factory := NewFactory() cfg := factory.CreateDefaultConfig().(*Config) - cfg.GRPCClientSettings = configgrpc.GRPCClientSettings{ + cfg.ClientConfig = configgrpc.ClientConfig{ Endpoint: ln.Addr().String(), - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: true, }, } @@ -608,10 +624,10 @@ func TestSendTracesOnResourceExhaustion(t *testing.T) { factory := NewFactory() cfg := factory.CreateDefaultConfig().(*Config) - cfg.RetrySettings.InitialInterval = 0 - cfg.GRPCClientSettings = configgrpc.GRPCClientSettings{ + cfg.RetryConfig.InitialInterval = 0 + cfg.ClientConfig = configgrpc.ClientConfig{ Endpoint: ln.Addr().String(), - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: true, }, } @@ -689,16 +705,21 @@ func TestSendLogData(t *testing.T) { cfg := factory.CreateDefaultConfig().(*Config) // Disable queuing to ensure that we execute the request when calling ConsumeLogs // otherwise we will not see any errors. - cfg.QueueSettings.Enabled = false - cfg.GRPCClientSettings = configgrpc.GRPCClientSettings{ + cfg.QueueConfig.Enabled = false + cfg.ClientConfig = configgrpc.ClientConfig{ Endpoint: ln.Addr().String(), - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: true, }, } set := exportertest.NewNopCreateSettings() set.BuildInfo.Description = "Collector" set.BuildInfo.Version = "1.2.3test" + + // For testing the "Partial success" warning. + logger, observed := observer.New(zap.DebugLevel) + set.TelemetrySettings.Logger = zap.New(logger) + exp, err := factory.CreateLogsExporter(context.Background(), set, cfg) require.NoError(t, err) require.NotNil(t, exp) @@ -770,5 +791,7 @@ func TestSendLogData(t *testing.T) { ld = testdata.GenerateLogs(2) err = exp.ConsumeLogs(context.Background(), ld) - assert.Error(t, err) + assert.NoError(t, err) + assert.Len(t, observed.FilterLevelExact(zap.WarnLevel).All(), 1) + assert.Contains(t, observed.FilterLevelExact(zap.WarnLevel).All()[0].Message, "Partial success") } diff --git a/exporter/otlpexporter/package_test.go b/exporter/otlpexporter/package_test.go new file mode 100644 index 00000000000..c5fb1007f5b --- /dev/null +++ b/exporter/otlpexporter/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package otlpexporter + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/exporter/otlpexporter/testdata/invalid_configs.yaml b/exporter/otlpexporter/testdata/invalid_configs.yaml new file mode 100644 index 00000000000..73c24e3f13e --- /dev/null +++ b/exporter/otlpexporter/testdata/invalid_configs.yaml @@ -0,0 +1,55 @@ +no_endpoint: + timeout: 10s + sending_queue: + enabled: true + num_consumers: 2 + queue_size: 10 + retry_on_failure: + enabled: true + initial_interval: 10s + randomization_factor: 0.7 + multiplier: 1.3 + max_interval: 60s + max_elapsed_time: 10m +http_endpoint: + endpoint: http:// + timeout: 10s + sending_queue: + enabled: true + num_consumers: 2 + queue_size: 10 + retry_on_failure: + enabled: true + initial_interval: 10s + randomization_factor: 0.7 + multiplier: 1.3 + max_interval: 60s + max_elapsed_time: 10m +invalid_timeout: + endpoint: example.com:443 + timeout: -5s + sending_queue: + enabled: true + num_consumers: 2 + queue_size: 10 + retry_on_failure: + enabled: true + initial_interval: 10s + randomization_factor: 0.7 + multiplier: 1.3 + max_interval: 60s + max_elapsed_time: 10m +invalid_retry: + endpoint: example.com:443 + timeout: 30s + sending_queue: + enabled: true + num_consumers: 2 + queue_size: 10 + retry_on_failure: + enabled: true + initial_interval: 10s + randomization_factor: -5 + multiplier: 1.3 + max_interval: 60s + max_elapsed_time: 10m diff --git a/exporter/otlphttpexporter/README.md b/exporter/otlphttpexporter/README.md index 5dfc1b9874c..fb15c0dab7a 100644 --- a/exporter/otlphttpexporter/README.md +++ b/exporter/otlphttpexporter/README.md @@ -1,12 +1,18 @@ # OTLP/HTTP Exporter -| Status | | -| ------------------------ | --------------------- | -| Stability | traces [stable] | -| | metrics [stable] | -| | logs [beta] | -| Supported pipeline types | traces, metrics, logs | -| Distributions | [core], [contrib] | + +| Status | | +| ------------- |-----------| +| Stability | [beta]: logs | +| | [stable]: traces, metrics | +| Distributions | [core], [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aexporter%2Fotlphttp%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aexporter%2Fotlphttp) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aexporter%2Fotlphttp%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aexporter%2Fotlphttp) | + +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[stable]: https://github.com/open-telemetry/opentelemetry-collector#stable +[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + Export traces and/or metrics via HTTP using [OTLP]( https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md) @@ -31,6 +37,7 @@ The following settings can be optionally configured: - `timeout` (default = 30s): HTTP request time limit. For details see https://golang.org/pkg/net/http/#Client - `read_buffer_size` (default = 0): ReadBufferSize for HTTP client. - `write_buffer_size` (default = 512 * 1024): WriteBufferSize for HTTP client. +- `encoding` (default = proto): The encoding to use for the messages (valid options: `proto`, `json`) Example: @@ -49,10 +56,14 @@ exporters: compression: none ``` +By default `proto` encoding is used, to change the content encoding of the message configure it as follows: + +```yaml +exporters: + otlphttp: + ... + encoding: json +``` + The full list of settings exposed for this exporter are documented [here](./config.go) with detailed sample configurations [here](./testdata/config.yaml). - -[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta -[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib -[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol -[stable]: https://github.com/open-telemetry/opentelemetry-collector#stable diff --git a/exporter/otlphttpexporter/config.go b/exporter/otlphttpexporter/config.go index 692f7e0124b..ef59fc324a0 100644 --- a/exporter/otlphttpexporter/config.go +++ b/exporter/otlphttpexporter/config.go @@ -4,18 +4,50 @@ package otlphttpexporter // import "go.opentelemetry.io/collector/exporter/otlphttpexporter" import ( + "encoding" "errors" + "fmt" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/confighttp" + "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/exporter/exporterhelper" ) +// EncodingType defines the type for content encoding +type EncodingType string + +const ( + EncodingProto EncodingType = "proto" + EncodingJSON EncodingType = "json" +) + +var _ encoding.TextUnmarshaler = (*EncodingType)(nil) + +// UnmarshalText unmarshalls text to an EncodingType. +func (e *EncodingType) UnmarshalText(text []byte) error { + if e == nil { + return errors.New("cannot unmarshal to a nil *EncodingType") + } + + str := string(text) + switch str { + case string(EncodingProto): + *e = EncodingProto + case string(EncodingJSON): + *e = EncodingJSON + default: + return fmt.Errorf("invalid encoding type: %s", str) + } + + return nil +} + // Config defines configuration for OTLP/HTTP exporter. type Config struct { - confighttp.HTTPClientSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. - exporterhelper.QueueSettings `mapstructure:"sending_queue"` - exporterhelper.RetrySettings `mapstructure:"retry_on_failure"` + confighttp.ClientConfig `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. + QueueConfig exporterhelper.QueueSettings `mapstructure:"sending_queue"` + RetryConfig configretry.BackOffConfig `mapstructure:"retry_on_failure"` // The URL to send traces to. If omitted the Endpoint + "/v1/traces" will be used. TracesEndpoint string `mapstructure:"traces_endpoint"` @@ -25,6 +57,9 @@ type Config struct { // The URL to send logs to. If omitted the Endpoint + "/v1/logs" will be used. LogsEndpoint string `mapstructure:"logs_endpoint"` + + // The encoding to export telemetry (default: "proto") + Encoding EncodingType `mapstructure:"encoding"` } var _ component.Config = (*Config)(nil) diff --git a/exporter/otlphttpexporter/config_test.go b/exporter/otlphttpexporter/config_test.go index 35b2d15a160..04bb1041036 100644 --- a/exporter/otlphttpexporter/config_test.go +++ b/exporter/otlphttpexporter/config_test.go @@ -14,6 +14,7 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/confighttp" "go.opentelemetry.io/collector/config/configopaque" + "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/config/configtls" "go.opentelemetry.io/collector/confmap" "go.opentelemetry.io/collector/confmap/confmaptest" @@ -37,7 +38,7 @@ func TestUnmarshalConfig(t *testing.T) { assert.NoError(t, component.UnmarshalConfig(cm, cfg)) assert.Equal(t, &Config{ - RetrySettings: exporterhelper.RetrySettings{ + RetryConfig: configretry.BackOffConfig{ Enabled: true, InitialInterval: 10 * time.Second, RandomizationFactor: 0.7, @@ -45,20 +46,21 @@ func TestUnmarshalConfig(t *testing.T) { MaxInterval: 1 * time.Minute, MaxElapsedTime: 10 * time.Minute, }, - QueueSettings: exporterhelper.QueueSettings{ + QueueConfig: exporterhelper.QueueSettings{ Enabled: true, NumConsumers: 2, QueueSize: 10, }, - HTTPClientSettings: confighttp.HTTPClientSettings{ + Encoding: EncodingProto, + ClientConfig: confighttp.ClientConfig{ Headers: map[string]configopaque.String{ "can you have a . here?": "F0000000-0000-0000-0000-000000000000", "header1": "234", "another": "somevalue", }, Endpoint: "https://1.2.3.4:1234", - TLSSetting: configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: "/var/lib/mycert.pem", CertFile: "certfile", KeyFile: "keyfile", @@ -72,3 +74,57 @@ func TestUnmarshalConfig(t *testing.T) { }, }, cfg) } + +func TestUnmarshalConfigInvalidEncoding(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "bad_invalid_encoding.yaml")) + require.NoError(t, err) + factory := NewFactory() + cfg := factory.CreateDefaultConfig() + assert.Error(t, component.UnmarshalConfig(cm, cfg)) +} + +func TestUnmarshalEncoding(t *testing.T) { + tests := []struct { + name string + encodingBytes []byte + expected EncodingType + shouldError bool + }{ + { + name: "UnmarshalEncodingProto", + encodingBytes: []byte("proto"), + expected: EncodingProto, + shouldError: false, + }, + { + name: "UnmarshalEncodingJson", + encodingBytes: []byte("json"), + expected: EncodingJSON, + shouldError: false, + }, + { + name: "UnmarshalEmptyEncoding", + encodingBytes: []byte(""), + shouldError: true, + }, + { + name: "UnmarshalInvalidEncoding", + encodingBytes: []byte("invalid"), + shouldError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var encoding EncodingType + err := encoding.UnmarshalText(tt.encodingBytes) + + if tt.shouldError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.expected, encoding) + } + }) + } +} diff --git a/exporter/otlphttpexporter/doc.go b/exporter/otlphttpexporter/doc.go index 3e1f11cc5df..16eccd7cbd4 100644 --- a/exporter/otlphttpexporter/doc.go +++ b/exporter/otlphttpexporter/doc.go @@ -1,5 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +//go:generate mdatagen metadata.yaml + // Package otlphttpexporter exports data by using the OTLP format to an HTTP endpoint. package otlphttpexporter // import "go.opentelemetry.io/collector/exporter/otlphttpexporter" diff --git a/exporter/otlphttpexporter/factory.go b/exporter/otlphttpexporter/factory.go index 4bdbcdf40fd..9ebcc01fba1 100644 --- a/exporter/otlphttpexporter/factory.go +++ b/exporter/otlphttpexporter/factory.go @@ -14,37 +14,35 @@ import ( "go.opentelemetry.io/collector/config/configcompression" "go.opentelemetry.io/collector/config/confighttp" "go.opentelemetry.io/collector/config/configopaque" + "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exporterhelper" -) - -const ( - // The value of "type" key in configuration. - typeStr = "otlphttp" + "go.opentelemetry.io/collector/exporter/otlphttpexporter/internal/metadata" ) // NewFactory creates a factory for OTLP exporter. func NewFactory() exporter.Factory { return exporter.NewFactory( - typeStr, + metadata.Type, createDefaultConfig, - exporter.WithTraces(createTracesExporter, component.StabilityLevelStable), - exporter.WithMetrics(createMetricsExporter, component.StabilityLevelStable), - exporter.WithLogs(createLogsExporter, component.StabilityLevelBeta), + exporter.WithTraces(createTracesExporter, metadata.TracesStability), + exporter.WithMetrics(createMetricsExporter, metadata.MetricsStability), + exporter.WithLogs(createLogsExporter, metadata.LogsStability), ) } func createDefaultConfig() component.Config { return &Config{ - RetrySettings: exporterhelper.NewDefaultRetrySettings(), - QueueSettings: exporterhelper.NewDefaultQueueSettings(), - HTTPClientSettings: confighttp.HTTPClientSettings{ + RetryConfig: configretry.NewDefaultBackOffConfig(), + QueueConfig: exporterhelper.NewDefaultQueueSettings(), + Encoding: EncodingProto, + ClientConfig: confighttp.ClientConfig{ Endpoint: "", Timeout: 30 * time.Second, Headers: map[string]configopaque.String{}, // Default to gzip compression - Compression: configcompression.Gzip, + Compression: configcompression.TypeGzip, // We almost read 0 bytes, so no need to tune ReadBufferSize. WriteBufferSize: 512 * 1024, }, @@ -91,8 +89,8 @@ func createTracesExporter( exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), // explicitly disable since we rely on http.Client timeout logic. exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: 0}), - exporterhelper.WithRetry(oCfg.RetrySettings), - exporterhelper.WithQueue(oCfg.QueueSettings)) + exporterhelper.WithRetry(oCfg.RetryConfig), + exporterhelper.WithQueue(oCfg.QueueConfig)) } func createMetricsExporter( @@ -117,8 +115,8 @@ func createMetricsExporter( exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), // explicitly disable since we rely on http.Client timeout logic. exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: 0}), - exporterhelper.WithRetry(oCfg.RetrySettings), - exporterhelper.WithQueue(oCfg.QueueSettings)) + exporterhelper.WithRetry(oCfg.RetryConfig), + exporterhelper.WithQueue(oCfg.QueueConfig)) } func createLogsExporter( @@ -143,6 +141,6 @@ func createLogsExporter( exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), // explicitly disable since we rely on http.Client timeout logic. exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: 0}), - exporterhelper.WithRetry(oCfg.RetrySettings), - exporterhelper.WithQueue(oCfg.QueueSettings)) + exporterhelper.WithRetry(oCfg.RetryConfig), + exporterhelper.WithQueue(oCfg.QueueConfig)) } diff --git a/exporter/otlphttpexporter/factory_test.go b/exporter/otlphttpexporter/factory_test.go index ba6d4d1c835..a36a9548d95 100644 --- a/exporter/otlphttpexporter/factory_test.go +++ b/exporter/otlphttpexporter/factory_test.go @@ -28,20 +28,21 @@ func TestCreateDefaultConfig(t *testing.T) { assert.NoError(t, componenttest.CheckConfigStruct(cfg)) ocfg, ok := factory.CreateDefaultConfig().(*Config) assert.True(t, ok) - assert.Equal(t, ocfg.HTTPClientSettings.Endpoint, "") - assert.Equal(t, ocfg.HTTPClientSettings.Timeout, 30*time.Second, "default timeout is 30 second") - assert.Equal(t, ocfg.RetrySettings.Enabled, true, "default retry is enabled") - assert.Equal(t, ocfg.RetrySettings.MaxElapsedTime, 300*time.Second, "default retry MaxElapsedTime") - assert.Equal(t, ocfg.RetrySettings.InitialInterval, 5*time.Second, "default retry InitialInterval") - assert.Equal(t, ocfg.RetrySettings.MaxInterval, 30*time.Second, "default retry MaxInterval") - assert.Equal(t, ocfg.QueueSettings.Enabled, true, "default sending queue is enabled") - assert.Equal(t, ocfg.Compression, configcompression.Gzip) + assert.Equal(t, ocfg.ClientConfig.Endpoint, "") + assert.Equal(t, ocfg.ClientConfig.Timeout, 30*time.Second, "default timeout is 30 second") + assert.Equal(t, ocfg.RetryConfig.Enabled, true, "default retry is enabled") + assert.Equal(t, ocfg.RetryConfig.MaxElapsedTime, 300*time.Second, "default retry MaxElapsedTime") + assert.Equal(t, ocfg.RetryConfig.InitialInterval, 5*time.Second, "default retry InitialInterval") + assert.Equal(t, ocfg.RetryConfig.MaxInterval, 30*time.Second, "default retry MaxInterval") + assert.Equal(t, ocfg.QueueConfig.Enabled, true, "default sending queue is enabled") + assert.Equal(t, ocfg.Encoding, EncodingProto) + assert.Equal(t, ocfg.Compression, configcompression.TypeGzip) } func TestCreateMetricsExporter(t *testing.T) { factory := NewFactory() cfg := factory.CreateDefaultConfig().(*Config) - cfg.HTTPClientSettings.Endpoint = "http://" + testutil.GetAvailableLocalAddress(t) + cfg.ClientConfig.Endpoint = "http://" + testutil.GetAvailableLocalAddress(t) set := exportertest.NewNopCreateSettings() oexp, err := factory.CreateMetricsExporter(context.Background(), set, cfg) @@ -61,7 +62,7 @@ func TestCreateTracesExporter(t *testing.T) { { name: "NoEndpoint", config: &Config{ - HTTPClientSettings: confighttp.HTTPClientSettings{ + ClientConfig: confighttp.ClientConfig{ Endpoint: "", }, }, @@ -70,9 +71,9 @@ func TestCreateTracesExporter(t *testing.T) { { name: "UseSecure", config: &Config{ - HTTPClientSettings: confighttp.HTTPClientSettings{ + ClientConfig: confighttp.ClientConfig{ Endpoint: endpoint, - TLSSetting: configtls.TLSClientSetting{ + TLSSetting: configtls.ClientConfig{ Insecure: false, }, }, @@ -81,7 +82,7 @@ func TestCreateTracesExporter(t *testing.T) { { name: "Headers", config: &Config{ - HTTPClientSettings: confighttp.HTTPClientSettings{ + ClientConfig: confighttp.ClientConfig{ Endpoint: endpoint, Headers: map[string]configopaque.String{ "hdr1": "val1", @@ -93,10 +94,10 @@ func TestCreateTracesExporter(t *testing.T) { { name: "CaCert", config: &Config{ - HTTPClientSettings: confighttp.HTTPClientSettings{ + ClientConfig: confighttp.ClientConfig{ Endpoint: endpoint, - TLSSetting: configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: filepath.Join("testdata", "test_cert.pem"), }, }, @@ -106,10 +107,10 @@ func TestCreateTracesExporter(t *testing.T) { { name: "CertPemFileError", config: &Config{ - HTTPClientSettings: confighttp.HTTPClientSettings{ + ClientConfig: confighttp.ClientConfig{ Endpoint: endpoint, - TLSSetting: configtls.TLSClientSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: configtls.ClientConfig{ + TLSSetting: configtls.Config{ CAFile: "nosuchfile", }, }, @@ -121,7 +122,7 @@ func TestCreateTracesExporter(t *testing.T) { { name: "NoneCompression", config: &Config{ - HTTPClientSettings: confighttp.HTTPClientSettings{ + ClientConfig: confighttp.ClientConfig{ Endpoint: endpoint, Compression: "none", }, @@ -130,30 +131,44 @@ func TestCreateTracesExporter(t *testing.T) { { name: "GzipCompression", config: &Config{ - HTTPClientSettings: confighttp.HTTPClientSettings{ + ClientConfig: confighttp.ClientConfig{ Endpoint: endpoint, - Compression: configcompression.Gzip, + Compression: configcompression.TypeGzip, }, }, }, { name: "SnappyCompression", config: &Config{ - HTTPClientSettings: confighttp.HTTPClientSettings{ + ClientConfig: confighttp.ClientConfig{ Endpoint: endpoint, - Compression: configcompression.Snappy, + Compression: configcompression.TypeSnappy, }, }, }, { name: "ZstdCompression", config: &Config{ - HTTPClientSettings: confighttp.HTTPClientSettings{ + ClientConfig: confighttp.ClientConfig{ Endpoint: endpoint, - Compression: configcompression.Zstd, + Compression: configcompression.TypeZstd, }, }, }, + { + name: "ProtoEncoding", + config: &Config{ + Encoding: EncodingProto, + ClientConfig: confighttp.ClientConfig{Endpoint: endpoint}, + }, + }, + { + name: "JSONEncoding", + config: &Config{ + Encoding: EncodingJSON, + ClientConfig: confighttp.ClientConfig{Endpoint: endpoint}, + }, + }, } for _, tt := range tests { @@ -186,7 +201,7 @@ func TestCreateTracesExporter(t *testing.T) { func TestCreateLogsExporter(t *testing.T) { factory := NewFactory() cfg := factory.CreateDefaultConfig().(*Config) - cfg.HTTPClientSettings.Endpoint = "http://" + testutil.GetAvailableLocalAddress(t) + cfg.ClientConfig.Endpoint = "http://" + testutil.GetAvailableLocalAddress(t) set := exportertest.NewNopCreateSettings() oexp, err := factory.CreateLogsExporter(context.Background(), set, cfg) @@ -199,13 +214,13 @@ func TestComposeSignalURL(t *testing.T) { cfg := factory.CreateDefaultConfig().(*Config) // Has slash at end - cfg.HTTPClientSettings.Endpoint = "http://localhost:4318/" + cfg.ClientConfig.Endpoint = "http://localhost:4318/" url, err := composeSignalURL(cfg, "", "traces") require.NoError(t, err) assert.Equal(t, "http://localhost:4318/v1/traces", url) // No slash at end - cfg.HTTPClientSettings.Endpoint = "http://localhost:4318" + cfg.ClientConfig.Endpoint = "http://localhost:4318" url, err = composeSignalURL(cfg, "", "traces") require.NoError(t, err) assert.Equal(t, "http://localhost:4318/v1/traces", url) diff --git a/exporter/otlphttpexporter/go.mod b/exporter/otlphttpexporter/go.mod index 0429d675cd3..20043caf0b6 100644 --- a/exporter/otlphttpexporter/go.mod +++ b/exporter/otlphttpexporter/go.mod @@ -1,71 +1,82 @@ module go.opentelemetry.io/collector/exporter/otlphttpexporter -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/configcompression v0.85.0 - go.opentelemetry.io/collector/config/confighttp v0.85.0 - go.opentelemetry.io/collector/config/configopaque v0.85.0 - go.opentelemetry.io/collector/config/configtls v0.85.0 - go.opentelemetry.io/collector/confmap v0.85.0 - go.opentelemetry.io/collector/consumer v0.85.0 - go.opentelemetry.io/collector/exporter v0.85.0 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/collector/receiver v0.85.0 - go.opentelemetry.io/collector/receiver/otlpreceiver v0.85.0 - go.uber.org/zap v1.26.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 - google.golang.org/grpc v1.58.1 - google.golang.org/protobuf v1.31.0 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/configcompression v0.96.0 + go.opentelemetry.io/collector/config/confighttp v0.96.0 + go.opentelemetry.io/collector/config/configopaque v1.3.0 + go.opentelemetry.io/collector/config/configretry v0.96.0 + go.opentelemetry.io/collector/config/configtls v0.96.0 + go.opentelemetry.io/collector/confmap v0.96.0 + go.opentelemetry.io/collector/consumer v0.96.0 + go.opentelemetry.io/collector/exporter v0.96.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 + go.uber.org/zap v1.27.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 + google.golang.org/grpc v1.62.0 + google.golang.org/protobuf v1.32.0 ) require ( + github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/felixge/httpsnoop v1.0.3 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.0 // indirect + github.com/klauspost/compress v1.17.7 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/mostynb/go-grpc-compression v1.2.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rs/cors v1.10.0 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/config/configauth v0.85.0 // indirect - go.opentelemetry.io/collector/config/configgrpc v0.85.0 // indirect - go.opentelemetry.io/collector/config/confignet v0.85.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 // indirect - go.opentelemetry.io/collector/config/internal v0.85.0 // indirect - go.opentelemetry.io/collector/extension v0.85.0 // indirect - go.opentelemetry.io/collector/extension/auth v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/service v0.0.0-20230915215502-07938f20fcc7 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/sdk v1.18.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/rs/cors v1.10.1 // indirect + go.opentelemetry.io/collector/config/configauth v0.96.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/config/internal v0.96.0 // indirect + go.opentelemetry.io/collector/extension v0.96.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.96.0 // indirect + go.opentelemetry.io/collector/featuregate v1.3.0 // indirect + go.opentelemetry.io/collector/receiver v0.96.0 // indirect + go.opentelemetry.io/contrib/config v0.4.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -77,12 +88,8 @@ replace go.opentelemetry.io/collector/config/configauth => ../../config/configau replace go.opentelemetry.io/collector/config/configcompression => ../../config/configcompression -replace go.opentelemetry.io/collector/config/configgrpc => ../../config/configgrpc - replace go.opentelemetry.io/collector/config/confighttp => ../../config/confighttp -replace go.opentelemetry.io/collector/config/confignet => ../../config/confignet - replace go.opentelemetry.io/collector/config/configopaque => ../../config/configopaque replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry @@ -93,8 +100,6 @@ replace go.opentelemetry.io/collector/config/internal => ../../config/internal replace go.opentelemetry.io/collector/confmap => ../../confmap -replace go.opentelemetry.io/collector/connector => ../../connector - replace go.opentelemetry.io/collector/exporter => ../ replace go.opentelemetry.io/collector/extension => ../../extension @@ -105,18 +110,8 @@ replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata -replace go.opentelemetry.io/collector/processor => ../../processor - replace go.opentelemetry.io/collector/receiver => ../../receiver -replace go.opentelemetry.io/collector/receiver/otlpreceiver => ../../receiver/otlpreceiver - -replace go.opentelemetry.io/collector/semconv => ../../semconv - -replace go.opentelemetry.io/collector/service => ../../service - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension - replace go.opentelemetry.io/collector/consumer => ../../consumer retract ( @@ -124,5 +119,4 @@ retract ( v0.69.0 // Release failed, use v0.69.1 ) -// ambiguous import: found package cloud.google.com/go/compute/metadata in multiple modules -replace cloud.google.com/go => cloud.google.com/go v0.110.2 +replace go.opentelemetry.io/collector/config/configretry => ../../config/configretry diff --git a/exporter/otlphttpexporter/go.sum b/exporter/otlphttpexporter/go.sum index 0e10debd90b..9d2b7f63d76 100644 --- a/exporter/otlphttpexporter/go.sum +++ b/exporter/otlphttpexporter/go.sum @@ -1,755 +1,56 @@ -cloud.google.com/go v0.110.2 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA= -cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= -cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= -cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= -cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= -cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= -cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= -cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= -cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= -cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= -cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= -cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= -cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= -cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= -cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= -cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= -cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= -cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= -cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= -cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= -cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= -cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= -cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= -cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= -cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= -cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= -cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= -cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= -cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= -cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= -cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= -cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= -cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= -cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= -cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= -cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= -cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= -cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= -cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= -cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= -cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= -cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= -cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= -cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= -cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= -cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= -cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= -cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= -cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= -cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= -cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= -cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= -cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= -cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= -cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= -cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= -cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= -cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= -cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= -cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= -cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= -cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= -cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= -cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= -cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= -cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= -cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= -cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= -cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= -cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= -cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= -cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= -cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= -cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= -cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= -cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= -cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= -cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= -cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= -cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= -cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= -cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= -cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= -cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= -cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= -cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= -cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= -cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= -cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= -cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= -cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= -cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= -cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= -cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= -cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= -cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= -cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= -cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= -cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= -cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= -cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= -cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= -cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= -cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= -cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= -cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= -cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= -cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= -cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= -cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= -cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= -cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= -cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= -cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= -cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= -cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= -cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= -cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= -cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= -cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= -cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68 h1:aRVqY1p2IJaBGStWMsQMpkAa83cPkCDLl80eOj0Rbz4= -cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= -cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= -cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= -cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= -cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= -cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= -cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= -cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= -cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= -cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= -cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= -cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= -cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= -cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= -cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= -cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= -cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= -cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= -cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= -cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= -cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= -cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= -cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= -cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= -cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= -cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= -cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= -cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= -cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= -cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= -cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= -cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= -cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= -cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= -cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= -cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= -cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= -cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= -cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= -cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= -cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= -cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= -cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= -cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= -cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= -cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= -cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= -cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= -cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= -cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= -cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= -cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= -cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= -cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= -cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= -cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= -cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= -cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= -cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= -cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= -cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= -cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= -cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= -cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= -cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= -cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= -cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= -cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= -cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= -cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= -cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= -cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= -cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= -cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= -cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= -cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= -cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= -cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= -cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= -cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= -cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= -cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= -cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= -cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= -cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= -cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= -cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= -cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= -cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= -cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= -cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= -cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= -cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= -cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= -cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= -cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= -cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= -cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= -cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= -cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= -cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= -cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= -cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= -cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= -cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= -cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= -cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= -cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= -cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= -cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= -cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= -cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= -cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= -cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= -cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= -cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= -cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= -cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= -cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= -cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= -cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= -cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= -cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= -cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= -cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= -cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= -cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= -cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= -cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= -cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= -cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= -cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= -cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= -cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= -cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= -cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= -cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= -cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= -cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= -cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= -cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= -cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= -cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= -cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= -cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= -cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= -cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= -cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= -cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= -cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= -cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= -cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= -cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= -cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= -cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= -cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= -cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= -cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= -cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= -cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= -cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= -cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= -cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= -cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= -cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= -cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= -cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= -cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= -cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= -cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= -cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= -cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= -cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= -cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= -cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= -cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= -cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= -cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= -cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= -cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= -cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= -cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= -cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= -cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= -cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= -cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= -cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= -cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= -cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= -cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= -cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= -cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= -cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= -cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= -cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= -cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= -cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= -cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= -cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= -cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= -cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= -cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= -cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= -cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= -cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= -cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= -cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= -cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= -cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= -cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= -cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= -cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= -cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= -cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= -cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= -cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= -cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= -cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= -cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= -cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= -cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= -cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= -cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= -cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= -cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= -cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= -cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= -cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= -cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= -cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= -cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= -cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= -cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= -cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= -cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= -cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= -cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= -cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= -cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= -cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= -cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= -cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= -cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= -cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= -cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= -cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= -cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= -cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= -cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= -cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= -cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= -cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= -cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= -cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= -cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= -cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= -cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= -cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= -cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= -cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= -cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= -cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= -cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= -cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= -cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= -cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= -cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= -cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= -cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= -cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= -cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= -cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= -cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= -cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= -cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= -cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= -cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= -cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= -cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= -cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= -cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= -cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= -cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= -cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= -cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= -cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= -cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= -cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= -cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= -cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= -cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= -cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= -cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= -cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= -cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= -cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= -cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= -cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= -cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= -cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= -cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= -cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= -cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= -cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= -cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= -cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= -cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= -cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= -cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= -cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= -cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= -cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= -cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= -cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= -cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= -cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= -cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= -cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= -cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= -cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= -cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= -cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= -cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= -cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= -cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= -cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= -cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= -cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= -cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= -cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= -cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= -cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= -cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= -cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= -cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= -cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= -cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= -cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= -cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= -cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= -cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= -cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= -cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= -cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= -cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= -cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= -cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= -cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= -cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= -cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= -cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= -cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= -cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= -cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= -cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= -cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= -cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= -cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= -cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= -cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= -cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= -cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= -cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= -cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= -cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= -cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= -cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= -cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= -cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= -cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= -cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= -cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= -cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= -cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= -cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= -cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= -cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= -cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= -cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= -cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= -cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= -cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= -git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= -github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= -github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= -github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= -github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= -github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= -github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= -github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= -github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= -github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= -github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= -github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= -github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= -github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= -github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -757,566 +58,103 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mostynb/go-grpc-compression v1.2.1 h1:16tdYxBZSD8p9AUmvw4F7Nyc2T4/eE7XsIXrgxSEcJI= -github.com/mostynb/go-grpc-compression v1.2.1/go.mod h1:oidYvYyefMmhcuvU8fLJ8FfZyTyVzJ6SkmD5fIKgRe8= -github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= -github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rs/cors v1.10.0 h1:62NOS1h+r8p1mW6FM0FSB0exioXLhd/sh15KpjWBZ+8= -github.com/rs/cors v1.10.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= -github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/contrib/config v0.4.0 h1:Xb+ncYOqseLroMuBesGNRgVQolXcXOhMj7EhGwJCdHs= +go.opentelemetry.io/contrib/config v0.4.0/go.mod h1:drNk2xRqLWW4/amk6Uh1S+sDAJTc7bcEEN1GfJzj418= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= -golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= -gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= -gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= -google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= -google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= -google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= -google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= -google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= -google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= -google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -google.golang.org/api v0.118.0/go.mod h1:76TtD3vkgmZ66zZzp72bUUklpmQmKlhh6sYtIjYK+5E= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= -google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= -google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= -google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= -google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= -google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= -google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= -google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= -google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= -modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= -modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= -modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= -modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= -modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= -modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= -modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= -modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= -modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= -modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= -modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= -modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= -modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= -modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= -modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/exporter/otlphttpexporter/internal/metadata/generated_status.go b/exporter/otlphttpexporter/internal/metadata/generated_status.go new file mode 100644 index 00000000000..d9f62544a6f --- /dev/null +++ b/exporter/otlphttpexporter/internal/metadata/generated_status.go @@ -0,0 +1,29 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("otlphttp") + scopeName = "go.opentelemetry.io/collector/exporter/otlphttpexporter" +) + +const ( + LogsStability = component.StabilityLevelBeta + TracesStability = component.StabilityLevelStable + MetricsStability = component.StabilityLevelStable +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} diff --git a/exporter/otlphttpexporter/metadata.yaml b/exporter/otlphttpexporter/metadata.yaml new file mode 100644 index 00000000000..14cae78d175 --- /dev/null +++ b/exporter/otlphttpexporter/metadata.yaml @@ -0,0 +1,8 @@ +type: otlphttp + +status: + class: exporter + stability: + stable: [traces, metrics] + beta: [logs] + distributions: [core, contrib] diff --git a/exporter/otlphttpexporter/otlp.go b/exporter/otlphttpexporter/otlp.go index b118b72f2a3..6ebc50e2cc0 100644 --- a/exporter/otlphttpexporter/otlp.go +++ b/exporter/otlphttpexporter/otlp.go @@ -48,6 +48,7 @@ const ( headerRetryAfter = "Retry-After" maxHTTPResponseReadBytes = 64 * 1024 + jsonContentType = "application/json" protobufContentType = "application/x-protobuf" ) @@ -77,7 +78,7 @@ func newExporter(cfg component.Config, set exporter.CreateSettings) (*baseExport // start actually creates the HTTP client. The client construction is deferred till this point as this // is the only place we get hold of Extensions which are required to construct auth round tripper. func (e *baseExporter) start(_ context.Context, host component.Host) error { - client, err := e.config.HTTPClientSettings.ToClient(host, e.settings) + client, err := e.config.ClientConfig.ToClient(host, e.settings) if err != nil { return err } @@ -87,31 +88,64 @@ func (e *baseExporter) start(_ context.Context, host component.Host) error { func (e *baseExporter) pushTraces(ctx context.Context, td ptrace.Traces) error { tr := ptraceotlp.NewExportRequestFromTraces(td) - request, err := tr.MarshalProto() + + var err error + var request []byte + switch e.config.Encoding { + case EncodingJSON: + request, err = tr.MarshalJSON() + case EncodingProto: + request, err = tr.MarshalProto() + default: + err = fmt.Errorf("invalid encoding: %s", e.config.Encoding) + } + if err != nil { return consumererror.NewPermanent(err) } - return e.export(ctx, e.tracesURL, request, tracesPartialSuccessHandler) + return e.export(ctx, e.tracesURL, request, e.tracesPartialSuccessHandler) } func (e *baseExporter) pushMetrics(ctx context.Context, md pmetric.Metrics) error { tr := pmetricotlp.NewExportRequestFromMetrics(md) - request, err := tr.MarshalProto() + + var err error + var request []byte + switch e.config.Encoding { + case EncodingJSON: + request, err = tr.MarshalJSON() + case EncodingProto: + request, err = tr.MarshalProto() + default: + err = fmt.Errorf("invalid encoding: %s", e.config.Encoding) + } + if err != nil { return consumererror.NewPermanent(err) } - return e.export(ctx, e.metricsURL, request, metricsPartialSuccessHandler) + return e.export(ctx, e.metricsURL, request, e.metricsPartialSuccessHandler) } func (e *baseExporter) pushLogs(ctx context.Context, ld plog.Logs) error { tr := plogotlp.NewExportRequestFromLogs(ld) - request, err := tr.MarshalProto() + + var err error + var request []byte + switch e.config.Encoding { + case EncodingJSON: + request, err = tr.MarshalJSON() + case EncodingProto: + request, err = tr.MarshalProto() + default: + err = fmt.Errorf("invalid encoding: %s", e.config.Encoding) + } + if err != nil { return consumererror.NewPermanent(err) } - return e.export(ctx, e.logsURL, request, logsPartialSuccessHandler) + return e.export(ctx, e.logsURL, request, e.logsPartialSuccessHandler) } func (e *baseExporter) export(ctx context.Context, url string, request []byte, partialSuccessHandler partialSuccessHandler) error { @@ -120,7 +154,16 @@ func (e *baseExporter) export(ctx context.Context, url string, request []byte, p if err != nil { return consumererror.NewPermanent(err) } - req.Header.Set("Content-Type", protobufContentType) + + switch e.config.Encoding { + case EncodingJSON: + req.Header.Set("Content-Type", jsonContentType) + case EncodingProto: + req.Header.Set("Content-Type", protobufContentType) + default: + return fmt.Errorf("invalid encoding: %s", e.config.Encoding) + } + req.Header.Set("User-Agent", e.userAgent) resp, err := e.client.Do(req) @@ -231,7 +274,6 @@ func readResponseStatus(resp *http.Response) *status.Status { // "Response body for all HTTP 4xx and HTTP 5xx responses MUST be a // Protobuf-encoded Status message that describes the problem." respBytes, err := readResponseBody(resp) - if err != nil { return nil } @@ -249,7 +291,6 @@ func readResponseStatus(resp *http.Response) *status.Status { func handlePartialSuccessResponse(resp *http.Response, partialSuccessHandler partialSuccessHandler) error { bodyBytes, err := readResponseBody(resp) - if err != nil { return err } @@ -259,50 +300,83 @@ func handlePartialSuccessResponse(resp *http.Response, partialSuccessHandler par type partialSuccessHandler func(bytes []byte, contentType string) error -func tracesPartialSuccessHandler(protoBytes []byte, contentType string) error { - if contentType != protobufContentType { - return nil - } +func (e *baseExporter) tracesPartialSuccessHandler(protoBytes []byte, contentType string) error { exportResponse := ptraceotlp.NewExportResponse() - err := exportResponse.UnmarshalProto(protoBytes) - if err != nil { - return fmt.Errorf("error parsing protobuf response: %w", err) + switch contentType { + case protobufContentType: + err := exportResponse.UnmarshalProto(protoBytes) + if err != nil { + return fmt.Errorf("error parsing protobuf response: %w", err) + } + case jsonContentType: + err := exportResponse.UnmarshalJSON(protoBytes) + if err != nil { + return fmt.Errorf("error parsing json response: %w", err) + } + default: + return nil } + partialSuccess := exportResponse.PartialSuccess() if !(partialSuccess.ErrorMessage() == "" && partialSuccess.RejectedSpans() == 0) { - return consumererror.NewPermanent(fmt.Errorf("OTLP partial success: %s (%d rejected)", partialSuccess.ErrorMessage(), partialSuccess.RejectedSpans())) + e.logger.Warn("Partial success response", + zap.String("message", exportResponse.PartialSuccess().ErrorMessage()), + zap.Int64("dropped_spans", exportResponse.PartialSuccess().RejectedSpans()), + ) } return nil } -func metricsPartialSuccessHandler(protoBytes []byte, contentType string) error { - if contentType != protobufContentType { - return nil - } +func (e *baseExporter) metricsPartialSuccessHandler(protoBytes []byte, contentType string) error { exportResponse := pmetricotlp.NewExportResponse() - err := exportResponse.UnmarshalProto(protoBytes) - if err != nil { - return fmt.Errorf("error parsing protobuf response: %w", err) + switch contentType { + case protobufContentType: + err := exportResponse.UnmarshalProto(protoBytes) + if err != nil { + return fmt.Errorf("error parsing protobuf response: %w", err) + } + case jsonContentType: + err := exportResponse.UnmarshalJSON(protoBytes) + if err != nil { + return fmt.Errorf("error parsing json response: %w", err) + } + default: + return nil } + partialSuccess := exportResponse.PartialSuccess() if !(partialSuccess.ErrorMessage() == "" && partialSuccess.RejectedDataPoints() == 0) { - return consumererror.NewPermanent(fmt.Errorf("OTLP partial success: %s (%d rejected)", partialSuccess.ErrorMessage(), partialSuccess.RejectedDataPoints())) + e.logger.Warn("Partial success response", + zap.String("message", exportResponse.PartialSuccess().ErrorMessage()), + zap.Int64("dropped_data_points", exportResponse.PartialSuccess().RejectedDataPoints()), + ) } return nil } -func logsPartialSuccessHandler(protoBytes []byte, contentType string) error { - if contentType != protobufContentType { - return nil - } +func (e *baseExporter) logsPartialSuccessHandler(protoBytes []byte, contentType string) error { exportResponse := plogotlp.NewExportResponse() - err := exportResponse.UnmarshalProto(protoBytes) - if err != nil { - return fmt.Errorf("error parsing protobuf response: %w", err) + switch contentType { + case protobufContentType: + err := exportResponse.UnmarshalProto(protoBytes) + if err != nil { + return fmt.Errorf("error parsing protobuf response: %w", err) + } + case jsonContentType: + err := exportResponse.UnmarshalJSON(protoBytes) + if err != nil { + return fmt.Errorf("error parsing json response: %w", err) + } + default: + return nil } + partialSuccess := exportResponse.PartialSuccess() if !(partialSuccess.ErrorMessage() == "" && partialSuccess.RejectedLogRecords() == 0) { - return consumererror.NewPermanent(fmt.Errorf("OTLP partial success: %s (%d rejected)", partialSuccess.ErrorMessage(), partialSuccess.RejectedLogRecords())) + e.logger.Warn("Partial success response", + zap.String("message", exportResponse.PartialSuccess().ErrorMessage()), + zap.Int64("dropped_log_records", exportResponse.PartialSuccess().RejectedLogRecords()), + ) } return nil } diff --git a/exporter/otlphttpexporter/otlp_test.go b/exporter/otlphttpexporter/otlp_test.go index daa54d4b7ea..0116803d816 100644 --- a/exporter/otlphttpexporter/otlp_test.go +++ b/exporter/otlphttpexporter/otlp_test.go @@ -5,10 +5,7 @@ package otlphttpexporter import ( "bytes" - "compress/gzip" "context" - "encoding/base64" - "encoding/hex" "errors" "fmt" "io" @@ -20,358 +17,26 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" + "go.uber.org/zap" + "go.uber.org/zap/zaptest/observer" + codes "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" - "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/config/confighttp" "go.opentelemetry.io/collector/config/configopaque" - "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumererror" - "go.opentelemetry.io/collector/consumer/consumertest" - "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exporterhelper" "go.opentelemetry.io/collector/exporter/exportertest" - "go.opentelemetry.io/collector/internal/testdata" - "go.opentelemetry.io/collector/internal/testutil" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/plog/plogotlp" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/pmetric/pmetricotlp" "go.opentelemetry.io/collector/pdata/ptrace" "go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp" - "go.opentelemetry.io/collector/receiver/otlpreceiver" - "go.opentelemetry.io/collector/receiver/receivertest" ) -func TestInvalidConfig(t *testing.T) { - config := &Config{ - HTTPClientSettings: confighttp.HTTPClientSettings{ - Endpoint: "", - }, - } - f := NewFactory() - set := exportertest.NewNopCreateSettings() - _, err := f.CreateTracesExporter(context.Background(), set, config) - require.Error(t, err) - _, err = f.CreateMetricsExporter(context.Background(), set, config) - require.Error(t, err) - _, err = f.CreateLogsExporter(context.Background(), set, config) - require.Error(t, err) -} - -func TestTraceNoBackend(t *testing.T) { - addr := testutil.GetAvailableLocalAddress(t) - exp := startTracesExporter(t, "", fmt.Sprintf("http://%s/v1/traces", addr)) - td := testdata.GenerateTraces(1) - assert.Error(t, exp.ConsumeTraces(context.Background(), td)) -} - -func TestTraceInvalidUrl(t *testing.T) { - exp := startTracesExporter(t, "http:/\\//this_is_an/*/invalid_url", "") - td := testdata.GenerateTraces(1) - assert.Error(t, exp.ConsumeTraces(context.Background(), td)) - - exp = startTracesExporter(t, "", "http:/\\//this_is_an/*/invalid_url") - td = testdata.GenerateTraces(1) - assert.Error(t, exp.ConsumeTraces(context.Background(), td)) -} - -func TestTraceError(t *testing.T) { - addr := testutil.GetAvailableLocalAddress(t) - - startTracesReceiver(t, addr, consumertest.NewErr(errors.New("my_error"))) - exp := startTracesExporter(t, "", fmt.Sprintf("http://%s/v1/traces", addr)) - - td := testdata.GenerateTraces(1) - assert.Error(t, exp.ConsumeTraces(context.Background(), td)) -} - -func TestTraceRoundTrip(t *testing.T) { - addr := testutil.GetAvailableLocalAddress(t) - - tests := []struct { - name string - baseURL string - overrideURL string - }{ - { - name: "wrongbase", - baseURL: "http://wronghostname", - overrideURL: fmt.Sprintf("http://%s/v1/traces", addr), - }, - { - name: "onlybase", - baseURL: fmt.Sprintf("http://%s", addr), - overrideURL: "", - }, - { - name: "override", - baseURL: "", - overrideURL: fmt.Sprintf("http://%s/v1/traces", addr), - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - sink := new(consumertest.TracesSink) - startTracesReceiver(t, addr, sink) - exp := startTracesExporter(t, test.baseURL, test.overrideURL) - - td := testdata.GenerateTraces(1) - assert.NoError(t, exp.ConsumeTraces(context.Background(), td)) - require.Eventually(t, func() bool { - return sink.SpanCount() > 0 - }, 1*time.Second, 10*time.Millisecond) - allTraces := sink.AllTraces() - require.Len(t, allTraces, 1) - assert.EqualValues(t, td, allTraces[0]) - }) - } -} - -func TestMetricsError(t *testing.T) { - addr := testutil.GetAvailableLocalAddress(t) - - startMetricsReceiver(t, addr, consumertest.NewErr(errors.New("my_error"))) - exp := startMetricsExporter(t, "", fmt.Sprintf("http://%s/v1/metrics", addr)) - - md := testdata.GenerateMetrics(1) - assert.Error(t, exp.ConsumeMetrics(context.Background(), md)) -} - -func TestMetricsRoundTrip(t *testing.T) { - addr := testutil.GetAvailableLocalAddress(t) - - tests := []struct { - name string - baseURL string - overrideURL string - }{ - { - name: "wrongbase", - baseURL: "http://wronghostname", - overrideURL: fmt.Sprintf("http://%s/v1/metrics", addr), - }, - { - name: "onlybase", - baseURL: fmt.Sprintf("http://%s", addr), - overrideURL: "", - }, - { - name: "override", - baseURL: "", - overrideURL: fmt.Sprintf("http://%s/v1/metrics", addr), - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - sink := new(consumertest.MetricsSink) - startMetricsReceiver(t, addr, sink) - exp := startMetricsExporter(t, test.baseURL, test.overrideURL) - - md := testdata.GenerateMetrics(1) - assert.NoError(t, exp.ConsumeMetrics(context.Background(), md)) - require.Eventually(t, func() bool { - return sink.DataPointCount() > 0 - }, 1*time.Second, 10*time.Millisecond) - allMetrics := sink.AllMetrics() - require.Len(t, allMetrics, 1) - assert.EqualValues(t, md, allMetrics[0]) - }) - } -} - -func TestLogsError(t *testing.T) { - addr := testutil.GetAvailableLocalAddress(t) - - startLogsReceiver(t, addr, consumertest.NewErr(errors.New("my_error"))) - exp := startLogsExporter(t, "", fmt.Sprintf("http://%s/v1/logs", addr)) - - md := testdata.GenerateLogs(1) - assert.Error(t, exp.ConsumeLogs(context.Background(), md)) -} - -func TestLogsRoundTrip(t *testing.T) { - addr := testutil.GetAvailableLocalAddress(t) - - tests := []struct { - name string - baseURL string - overrideURL string - }{ - { - name: "wrongbase", - baseURL: "http://wronghostname", - overrideURL: fmt.Sprintf("http://%s/v1/logs", addr), - }, - { - name: "onlybase", - baseURL: fmt.Sprintf("http://%s", addr), - overrideURL: "", - }, - { - name: "override", - baseURL: "", - overrideURL: fmt.Sprintf("http://%s/v1/logs", addr), - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - sink := new(consumertest.LogsSink) - startLogsReceiver(t, addr, sink) - exp := startLogsExporter(t, test.baseURL, test.overrideURL) - - md := testdata.GenerateLogs(1) - assert.NoError(t, exp.ConsumeLogs(context.Background(), md)) - require.Eventually(t, func() bool { - return sink.LogRecordCount() > 0 - }, 1*time.Second, 10*time.Millisecond) - allLogs := sink.AllLogs() - require.Len(t, allLogs, 1) - assert.EqualValues(t, md, allLogs[0]) - }) - } -} - -func TestIssue_4221(t *testing.T) { - svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - defer func() { assert.NoError(t, r.Body.Close()) }() - compressedData, err := io.ReadAll(r.Body) - require.NoError(t, err) - gzipReader, err := gzip.NewReader(bytes.NewReader(compressedData)) - require.NoError(t, err) - data, err := io.ReadAll(gzipReader) - require.NoError(t, err) - base64Data := base64.StdEncoding.EncodeToString(data) - // Verify same base64 encoded string is received. - assert.Equal(t, "CscBCkkKIAoMc2VydmljZS5uYW1lEhAKDnVvcC5zdGFnZS1ldS0xCiUKGW91dHN5c3RlbXMubW9kdWxlLnZlcnNpb24SCAoGOTAzMzg2EnoKEQoMdW9wX2NhbmFyaWVzEgExEmUKEEMDhT8Ib0+Mhs8Zi2VR34QSCOVRPDJ5XEG5IgA5QE41aASRrxZBQE41aASRrxZKEAoKc3Bhbl9pbmRleBICGANKHwoNY29kZS5mdW5jdGlvbhIOCgxteUZ1bmN0aW9uMzZ6AA==", base64Data) - unbase64Data, err := base64.StdEncoding.DecodeString(base64Data) - require.NoError(t, err) - tr := ptraceotlp.NewExportRequest() - require.NoError(t, tr.UnmarshalProto(unbase64Data)) - span := tr.Traces().ResourceSpans().At(0).ScopeSpans().At(0).Spans().At(0) - traceID := span.TraceID() - assert.Equal(t, "4303853f086f4f8c86cf198b6551df84", hex.EncodeToString(traceID[:])) - spanID := span.SpanID() - assert.Equal(t, "e5513c32795c41b9", hex.EncodeToString(spanID[:])) - })) - - exp := startTracesExporter(t, "", svr.URL) - - md := ptrace.NewTraces() - rms := md.ResourceSpans().AppendEmpty() - rms.Resource().Attributes().PutStr("service.name", "uop.stage-eu-1") - rms.Resource().Attributes().PutStr("outsystems.module.version", "903386") - ils := rms.ScopeSpans().AppendEmpty() - ils.Scope().SetName("uop_canaries") - ils.Scope().SetVersion("1") - span := ils.Spans().AppendEmpty() - - var traceIDBytes [16]byte - traceIDBytesSlice, err := hex.DecodeString("4303853f086f4f8c86cf198b6551df84") - require.NoError(t, err) - copy(traceIDBytes[:], traceIDBytesSlice) - span.SetTraceID(traceIDBytes) - traceID := span.TraceID() - assert.Equal(t, "4303853f086f4f8c86cf198b6551df84", hex.EncodeToString(traceID[:])) - - var spanIDBytes [8]byte - spanIDBytesSlice, err := hex.DecodeString("e5513c32795c41b9") - require.NoError(t, err) - copy(spanIDBytes[:], spanIDBytesSlice) - span.SetSpanID(spanIDBytes) - spanID := span.SpanID() - assert.Equal(t, "e5513c32795c41b9", hex.EncodeToString(spanID[:])) - - span.SetEndTimestamp(1634684637873000000) - span.Attributes().PutInt("span_index", 3) - span.Attributes().PutStr("code.function", "myFunction36") - span.SetStartTimestamp(1634684637873000000) - - assert.NoError(t, exp.ConsumeTraces(context.Background(), md)) -} - -func startTracesExporter(t *testing.T, baseURL string, overrideURL string) exporter.Traces { - factory := NewFactory() - cfg := createExporterConfig(baseURL, factory.CreateDefaultConfig()) - cfg.TracesEndpoint = overrideURL - exp, err := factory.CreateTracesExporter(context.Background(), exportertest.NewNopCreateSettings(), cfg) - require.NoError(t, err) - startAndCleanup(t, exp) - return exp -} - -func startMetricsExporter(t *testing.T, baseURL string, overrideURL string) exporter.Metrics { - factory := NewFactory() - cfg := createExporterConfig(baseURL, factory.CreateDefaultConfig()) - cfg.MetricsEndpoint = overrideURL - exp, err := factory.CreateMetricsExporter(context.Background(), exportertest.NewNopCreateSettings(), cfg) - require.NoError(t, err) - startAndCleanup(t, exp) - return exp -} - -func startLogsExporter(t *testing.T, baseURL string, overrideURL string) exporter.Logs { - factory := NewFactory() - cfg := createExporterConfig(baseURL, factory.CreateDefaultConfig()) - cfg.LogsEndpoint = overrideURL - exp, err := factory.CreateLogsExporter(context.Background(), exportertest.NewNopCreateSettings(), cfg) - require.NoError(t, err) - startAndCleanup(t, exp) - return exp -} - -func createExporterConfig(baseURL string, defaultCfg component.Config) *Config { - cfg := defaultCfg.(*Config) - cfg.Endpoint = baseURL - cfg.QueueSettings.Enabled = false - cfg.RetrySettings.Enabled = false - return cfg -} - -func startTracesReceiver(t *testing.T, addr string, next consumer.Traces) { - factory := otlpreceiver.NewFactory() - cfg := createReceiverConfig(addr, factory.CreateDefaultConfig()) - recv, err := factory.CreateTracesReceiver(context.Background(), receivertest.NewNopCreateSettings(), cfg, next) - require.NoError(t, err) - startAndCleanup(t, recv) -} - -func startMetricsReceiver(t *testing.T, addr string, next consumer.Metrics) { - factory := otlpreceiver.NewFactory() - cfg := createReceiverConfig(addr, factory.CreateDefaultConfig()) - recv, err := factory.CreateMetricsReceiver(context.Background(), receivertest.NewNopCreateSettings(), cfg, next) - require.NoError(t, err) - startAndCleanup(t, recv) -} - -func startLogsReceiver(t *testing.T, addr string, next consumer.Logs) { - factory := otlpreceiver.NewFactory() - cfg := createReceiverConfig(addr, factory.CreateDefaultConfig()) - recv, err := factory.CreateLogsReceiver(context.Background(), receivertest.NewNopCreateSettings(), cfg, next) - require.NoError(t, err) - startAndCleanup(t, recv) -} - -func createReceiverConfig(addr string, defaultCfg component.Config) *otlpreceiver.Config { - cfg := defaultCfg.(*otlpreceiver.Config) - cfg.HTTP.Endpoint = addr - cfg.GRPC = nil - return cfg -} - -func startAndCleanup(t *testing.T, cmp component.Component) { - require.NoError(t, cmp.Start(context.Background(), componenttest.NewNopHost())) - t.Cleanup(func() { - require.NoError(t, cmp.Shutdown(context.Background())) - }) -} - func TestErrorResponses(t *testing.T) { errMsgPrefix := func(srv *httptest.Server) string { return fmt.Sprintf("error exporting items, request to %s/v1/traces responded with HTTP Status Code ", srv.URL) @@ -498,7 +163,7 @@ func TestErrorResponses(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - srv := createBackend("/v1/traces", func(writer http.ResponseWriter, request *http.Request) { + srv := createBackend("/v1/traces", func(writer http.ResponseWriter, _ *http.Request) { for k, v := range test.headers { writer.Header().Add(k, v) } @@ -513,8 +178,9 @@ func TestErrorResponses(t *testing.T) { defer srv.Close() cfg := &Config{ + Encoding: EncodingProto, TracesEndpoint: fmt.Sprintf("%s/v1/traces", srv.URL), - // Create without QueueSettings and RetrySettings so that ConsumeTraces + // Create without QueueSettings and RetryConfig so that ConsumeTraces // returns the errors that we want to check immediately. } exp, err := createTracesExporter(context.Background(), exportertest.NewNopCreateSettings(), cfg) @@ -587,8 +253,9 @@ func TestUserAgent(t *testing.T) { defer srv.Close() cfg := &Config{ + Encoding: EncodingProto, TracesEndpoint: fmt.Sprintf("%s/v1/traces", srv.URL), - HTTPClientSettings: confighttp.HTTPClientSettings{ + ClientConfig: confighttp.ClientConfig{ Headers: test.headers, }, } @@ -620,8 +287,9 @@ func TestUserAgent(t *testing.T) { defer srv.Close() cfg := &Config{ + Encoding: EncodingProto, MetricsEndpoint: fmt.Sprintf("%s/v1/metrics", srv.URL), - HTTPClientSettings: confighttp.HTTPClientSettings{ + ClientConfig: confighttp.ClientConfig{ Headers: test.headers, }, } @@ -653,8 +321,9 @@ func TestUserAgent(t *testing.T) { defer srv.Close() cfg := &Config{ + Encoding: EncodingProto, LogsEndpoint: fmt.Sprintf("%s/v1/logs", srv.URL), - HTTPClientSettings: confighttp.HTTPClientSettings{ + ClientConfig: confighttp.ClientConfig{ Headers: test.headers, }, } @@ -679,76 +348,79 @@ func TestUserAgent(t *testing.T) { }) } -func TestPartialSuccess_traces(t *testing.T) { - srv := createBackend("/v1/traces", func(writer http.ResponseWriter, request *http.Request) { - response := ptraceotlp.NewExportResponse() - partial := response.PartialSuccess() - partial.SetErrorMessage("hello") - partial.SetRejectedSpans(1) - bytes, err := response.MarshalProto() - require.NoError(t, err) - writer.Header().Set("Content-Type", "application/x-protobuf") - _, err = writer.Write(bytes) - require.NoError(t, err) - }) - defer srv.Close() - - cfg := &Config{ - TracesEndpoint: fmt.Sprintf("%s/v1/traces", srv.URL), - HTTPClientSettings: confighttp.HTTPClientSettings{}, - } - exp, err := createTracesExporter(context.Background(), exportertest.NewNopCreateSettings(), cfg) - require.NoError(t, err) - - // start the exporter - err = exp.Start(context.Background(), componenttest.NewNopHost()) +func TestPartialSuccessInvalidBody(t *testing.T) { + cfg := createDefaultConfig() + set := exportertest.NewNopCreateSettings() + exp, err := newExporter(cfg, set) require.NoError(t, err) - t.Cleanup(func() { - require.NoError(t, exp.Shutdown(context.Background())) - }) - - // generate data - traces := ptrace.NewTraces() - err = exp.ConsumeTraces(context.Background(), traces) - require.Error(t, err) -} - -func TestPartialSuccess_metrics(t *testing.T) { - srv := createBackend("/v1/metrics", func(writer http.ResponseWriter, request *http.Request) { - response := pmetricotlp.NewExportResponse() - partial := response.PartialSuccess() - partial.SetErrorMessage("hello") - partial.SetRejectedDataPoints(1) - bytes, err := response.MarshalProto() - require.NoError(t, err) - writer.Header().Set("Content-Type", "application/x-protobuf") - _, err = writer.Write(bytes) - require.NoError(t, err) - }) - defer srv.Close() - - cfg := &Config{ - MetricsEndpoint: fmt.Sprintf("%s/v1/metrics", srv.URL), - HTTPClientSettings: confighttp.HTTPClientSettings{}, + invalidBodyCases := []struct { + telemetryType string + handler partialSuccessHandler + }{ + { + telemetryType: "traces", + handler: exp.tracesPartialSuccessHandler, + }, + { + telemetryType: "metrics", + handler: exp.metricsPartialSuccessHandler, + }, + { + telemetryType: "logs", + handler: exp.logsPartialSuccessHandler, + }, } - exp, err := createMetricsExporter(context.Background(), exportertest.NewNopCreateSettings(), cfg) - require.NoError(t, err) + for _, tt := range invalidBodyCases { + t.Run("Invalid response body_"+tt.telemetryType, func(t *testing.T) { + err := tt.handler([]byte{1}, "application/x-protobuf") + assert.ErrorContains(t, err, "error parsing protobuf response:") + }) + } +} - // start the exporter - err = exp.Start(context.Background(), componenttest.NewNopHost()) +func TestPartialSuccessUnsupportedContentType(t *testing.T) { + cfg := createDefaultConfig() + set := exportertest.NewNopCreateSettings() + exp, err := newExporter(cfg, set) require.NoError(t, err) - t.Cleanup(func() { - require.NoError(t, exp.Shutdown(context.Background())) - }) - - // generate data - metrics := pmetric.NewMetrics() - err = exp.ConsumeMetrics(context.Background(), metrics) - require.Error(t, err) + unsupportedContentTypeCases := []struct { + contentType string + }{ + { + contentType: "text/plain", + }, + { + contentType: "application/octet-stream", + }, + } + for _, telemetryType := range []string{"logs", "metrics", "traces"} { + for _, tt := range unsupportedContentTypeCases { + t.Run("Unsupported content type "+tt.contentType+" "+telemetryType, func(t *testing.T) { + var handler func(b []byte, contentType string) error + switch telemetryType { + case "logs": + handler = exp.logsPartialSuccessHandler + case "metrics": + handler = exp.metricsPartialSuccessHandler + case "traces": + handler = exp.tracesPartialSuccessHandler + default: + panic(telemetryType) + } + exportResponse := ptraceotlp.NewExportResponse() + exportResponse.PartialSuccess().SetErrorMessage("foo") + exportResponse.PartialSuccess().SetRejectedSpans(42) + b, err := exportResponse.MarshalProto() + require.NoError(t, err) + err = handler(b, tt.contentType) + assert.NoError(t, err) + }) + } + } } func TestPartialSuccess_logs(t *testing.T) { - srv := createBackend("/v1/logs", func(writer http.ResponseWriter, request *http.Request) { + srv := createBackend("/v1/logs", func(writer http.ResponseWriter, _ *http.Request) { response := plogotlp.NewExportResponse() partial := response.PartialSuccess() partial.SetErrorMessage("hello") @@ -762,10 +434,16 @@ func TestPartialSuccess_logs(t *testing.T) { defer srv.Close() cfg := &Config{ - LogsEndpoint: fmt.Sprintf("%s/v1/logs", srv.URL), - HTTPClientSettings: confighttp.HTTPClientSettings{}, + Encoding: EncodingProto, + LogsEndpoint: fmt.Sprintf("%s/v1/logs", srv.URL), + ClientConfig: confighttp.ClientConfig{}, } - exp, err := createLogsExporter(context.Background(), exportertest.NewNopCreateSettings(), cfg) + set := exportertest.NewNopCreateSettings() + + logger, observed := observer.New(zap.DebugLevel) + set.TelemetrySettings.Logger = zap.New(logger) + + exp, err := createLogsExporter(context.Background(), set, cfg) require.NoError(t, err) // start the exporter @@ -778,10 +456,17 @@ func TestPartialSuccess_logs(t *testing.T) { // generate data logs := plog.NewLogs() err = exp.ConsumeLogs(context.Background(), logs) - require.Error(t, err) + require.NoError(t, err) + require.Len(t, observed.FilterLevelExact(zap.WarnLevel).All(), 1) + require.Contains(t, observed.FilterLevelExact(zap.WarnLevel).All()[0].Message, "Partial success") } func TestPartialResponse_missingHeaderButHasBody(t *testing.T) { + cfg := createDefaultConfig() + set := exportertest.NewNopCreateSettings() + exp, err := newExporter(cfg, set) + require.NoError(t, err) + response := ptraceotlp.NewExportResponse() partial := response.PartialSuccess() partial.SetErrorMessage("hello") @@ -796,11 +481,16 @@ func TestPartialResponse_missingHeaderButHasBody(t *testing.T) { "Content-Type": {"application/x-protobuf"}, }, } - err = handlePartialSuccessResponse(resp, tracesPartialSuccessHandler) - assert.True(t, consumererror.IsPermanent(err)) + err = handlePartialSuccessResponse(resp, exp.tracesPartialSuccessHandler) + assert.NoError(t, err) } func TestPartialResponse_missingHeaderAndBody(t *testing.T) { + cfg := createDefaultConfig() + set := exportertest.NewNopCreateSettings() + exp, err := newExporter(cfg, set) + require.NoError(t, err) + resp := &http.Response{ // `-1` indicates a missing Content-Length header in the Go http standard library ContentLength: -1, @@ -809,21 +499,31 @@ func TestPartialResponse_missingHeaderAndBody(t *testing.T) { "Content-Type": {"application/x-protobuf"}, }, } - err := handlePartialSuccessResponse(resp, tracesPartialSuccessHandler) + err = handlePartialSuccessResponse(resp, exp.tracesPartialSuccessHandler) assert.Nil(t, err) } func TestPartialResponse_nonErrUnexpectedEOFError(t *testing.T) { + cfg := createDefaultConfig() + set := exportertest.NewNopCreateSettings() + exp, err := newExporter(cfg, set) + require.NoError(t, err) + resp := &http.Response{ // `-1` indicates a missing Content-Length header in the Go http standard library ContentLength: -1, Body: io.NopCloser(badReader{}), } - err := handlePartialSuccessResponse(resp, tracesPartialSuccessHandler) + err = handlePartialSuccessResponse(resp, exp.tracesPartialSuccessHandler) assert.Error(t, err) } func TestPartialSuccess_shortContentLengthHeader(t *testing.T) { + cfg := createDefaultConfig() + set := exportertest.NewNopCreateSettings() + exp, err := newExporter(cfg, set) + require.NoError(t, err) + response := ptraceotlp.NewExportResponse() partial := response.PartialSuccess() partial.SetErrorMessage("hello") @@ -837,11 +537,21 @@ func TestPartialSuccess_shortContentLengthHeader(t *testing.T) { "Content-Type": {"application/x-protobuf"}, }, } - err = handlePartialSuccessResponse(resp, tracesPartialSuccessHandler) + // For short content-length, a real error happens. + err = handlePartialSuccessResponse(resp, exp.tracesPartialSuccessHandler) assert.Error(t, err) } func TestPartialSuccess_longContentLengthHeader(t *testing.T) { + cfg := createDefaultConfig() + set := exportertest.NewNopCreateSettings() + + logger, observed := observer.New(zap.DebugLevel) + set.TelemetrySettings.Logger = zap.New(logger) + + exp, err := newExporter(cfg, set) + require.NoError(t, err) + response := ptraceotlp.NewExportResponse() partial := response.PartialSuccess() partial.SetErrorMessage("hello") @@ -855,11 +565,20 @@ func TestPartialSuccess_longContentLengthHeader(t *testing.T) { "Content-Type": {"application/x-protobuf"}, }, } - err = handlePartialSuccessResponse(resp, tracesPartialSuccessHandler) - assert.Error(t, err) + // No real error happens for long content length, so the partial + // success is handled as success with a warning. + err = handlePartialSuccessResponse(resp, exp.tracesPartialSuccessHandler) + assert.NoError(t, err) + assert.Len(t, observed.FilterLevelExact(zap.WarnLevel).All(), 1) + assert.Contains(t, observed.FilterLevelExact(zap.WarnLevel).All()[0].Message, "Partial success") } func TestPartialSuccessInvalidResponseBody(t *testing.T) { + cfg := createDefaultConfig() + set := exportertest.NewNopCreateSettings() + exp, err := newExporter(cfg, set) + require.NoError(t, err) + resp := &http.Response{ Body: io.NopCloser(badReader{}), ContentLength: 100, @@ -867,74 +586,206 @@ func TestPartialSuccessInvalidResponseBody(t *testing.T) { "Content-Type": {protobufContentType}, }, } - err := handlePartialSuccessResponse(resp, tracesPartialSuccessHandler) + err = handlePartialSuccessResponse(resp, exp.tracesPartialSuccessHandler) assert.Error(t, err) } -func TestPartialSuccessInvalidBody(t *testing.T) { - invalidBodyCases := []struct { - telemetryType string - handler partialSuccessHandler - }{ - { - telemetryType: "traces", - handler: tracesPartialSuccessHandler, - }, - { - telemetryType: "metrics", - handler: metricsPartialSuccessHandler, - }, - { - telemetryType: "logs", - handler: logsPartialSuccessHandler, - }, +func TestPartialSuccess_traces(t *testing.T) { + srv := createBackend("/v1/traces", func(writer http.ResponseWriter, _ *http.Request) { + response := ptraceotlp.NewExportResponse() + partial := response.PartialSuccess() + partial.SetErrorMessage("hello") + partial.SetRejectedSpans(1) + bytes, err := response.MarshalProto() + require.NoError(t, err) + writer.Header().Set("Content-Type", "application/x-protobuf") + _, err = writer.Write(bytes) + require.NoError(t, err) + }) + defer srv.Close() + + cfg := &Config{ + Encoding: EncodingProto, + TracesEndpoint: fmt.Sprintf("%s/v1/traces", srv.URL), + ClientConfig: confighttp.ClientConfig{}, } - for _, tt := range invalidBodyCases { - t.Run("Invalid response body_"+tt.telemetryType, func(t *testing.T) { - err := tt.handler([]byte{1}, "application/x-protobuf") - assert.ErrorContains(t, err, "error parsing protobuf response:") - }) + set := exportertest.NewNopCreateSettings() + logger, observed := observer.New(zap.DebugLevel) + set.TelemetrySettings.Logger = zap.New(logger) + exp, err := createTracesExporter(context.Background(), set, cfg) + require.NoError(t, err) + + // start the exporter + err = exp.Start(context.Background(), componenttest.NewNopHost()) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, exp.Shutdown(context.Background())) + }) + + // generate data + traces := ptrace.NewTraces() + err = exp.ConsumeTraces(context.Background(), traces) + require.NoError(t, err) + require.Len(t, observed.FilterLevelExact(zap.WarnLevel).All(), 1) + require.Contains(t, observed.FilterLevelExact(zap.WarnLevel).All()[0].Message, "Partial success") +} + +func TestPartialSuccess_metrics(t *testing.T) { + srv := createBackend("/v1/metrics", func(writer http.ResponseWriter, _ *http.Request) { + response := pmetricotlp.NewExportResponse() + partial := response.PartialSuccess() + partial.SetErrorMessage("hello") + partial.SetRejectedDataPoints(1) + bytes, err := response.MarshalProto() + require.NoError(t, err) + writer.Header().Set("Content-Type", "application/x-protobuf") + _, err = writer.Write(bytes) + require.NoError(t, err) + }) + defer srv.Close() + + cfg := &Config{ + Encoding: EncodingProto, + MetricsEndpoint: fmt.Sprintf("%s/v1/metrics", srv.URL), + ClientConfig: confighttp.ClientConfig{}, } + set := exportertest.NewNopCreateSettings() + logger, observed := observer.New(zap.DebugLevel) + set.TelemetrySettings.Logger = zap.New(logger) + exp, err := createMetricsExporter(context.Background(), set, cfg) + require.NoError(t, err) + + // start the exporter + err = exp.Start(context.Background(), componenttest.NewNopHost()) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, exp.Shutdown(context.Background())) + }) + + // generate data + metrics := pmetric.NewMetrics() + err = exp.ConsumeMetrics(context.Background(), metrics) + require.NoError(t, err) + require.Len(t, observed.FilterLevelExact(zap.WarnLevel).All(), 1) + require.Contains(t, observed.FilterLevelExact(zap.WarnLevel).All()[0].Message, "Partial success") } -func TestPartialSuccessUnsupportedContentType(t *testing.T) { - unsupportedContentTypeCases := []struct { - contentType string +func TestEncoding(t *testing.T) { + set := exportertest.NewNopCreateSettings() + set.BuildInfo.Description = "Collector" + set.BuildInfo.Version = "1.2.3test" + + tests := []struct { + name string + encoding EncodingType + expectedEncoding EncodingType }{ { - contentType: "application/json", + name: "proto_encoding", + encoding: EncodingProto, + expectedEncoding: "application/x-protobuf", }, { - contentType: "text/plain", - }, - { - contentType: "application/octet-stream", + name: "json_encoding", + encoding: EncodingJSON, + expectedEncoding: "application/json", }, } - for _, telemetryType := range []string{"logs", "metrics", "traces"} { - for _, tt := range unsupportedContentTypeCases { - t.Run("Unsupported content type "+tt.contentType+" "+telemetryType, func(t *testing.T) { - var handler func(b []byte, contentType string) error - switch telemetryType { - case "logs": - handler = logsPartialSuccessHandler - case "metrics": - handler = metricsPartialSuccessHandler - case "traces": - handler = tracesPartialSuccessHandler - default: - panic(telemetryType) + + t.Run("traces", func(t *testing.T) { + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + srv := createBackend("/v1/traces", func(writer http.ResponseWriter, request *http.Request) { + assert.Contains(t, request.Header.Get("content-type"), test.expectedEncoding) + writer.WriteHeader(200) + }) + defer srv.Close() + + cfg := &Config{ + TracesEndpoint: fmt.Sprintf("%s/v1/traces", srv.URL), + Encoding: test.encoding, } - exportResponse := ptraceotlp.NewExportResponse() - exportResponse.PartialSuccess().SetErrorMessage("foo") - exportResponse.PartialSuccess().SetRejectedSpans(42) - b, err := exportResponse.MarshalProto() + exp, err := createTracesExporter(context.Background(), set, cfg) + require.NoError(t, err) + + // start the exporter + err = exp.Start(context.Background(), componenttest.NewNopHost()) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, exp.Shutdown(context.Background())) + }) + + // generate data + traces := ptrace.NewTraces() + err = exp.ConsumeTraces(context.Background(), traces) require.NoError(t, err) - err = handler(b, tt.contentType) - assert.NoError(t, err) }) } - } + }) + + t.Run("metrics", func(t *testing.T) { + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + srv := createBackend("/v1/metrics", func(writer http.ResponseWriter, request *http.Request) { + assert.Contains(t, request.Header.Get("content-type"), test.expectedEncoding) + writer.WriteHeader(200) + }) + defer srv.Close() + + cfg := &Config{ + MetricsEndpoint: fmt.Sprintf("%s/v1/metrics", srv.URL), + Encoding: test.encoding, + } + exp, err := createMetricsExporter(context.Background(), set, cfg) + require.NoError(t, err) + + // start the exporter + err = exp.Start(context.Background(), componenttest.NewNopHost()) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, exp.Shutdown(context.Background())) + }) + + // generate data + metrics := pmetric.NewMetrics() + err = exp.ConsumeMetrics(context.Background(), metrics) + require.NoError(t, err) + }) + } + }) + + t.Run("logs", func(t *testing.T) { + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + srv := createBackend("/v1/logs", func(writer http.ResponseWriter, request *http.Request) { + assert.Contains(t, request.Header.Get("content-type"), test.expectedEncoding) + writer.WriteHeader(200) + }) + defer srv.Close() + + cfg := &Config{ + LogsEndpoint: fmt.Sprintf("%s/v1/logs", srv.URL), + Encoding: test.encoding, + } + exp, err := createLogsExporter(context.Background(), set, cfg) + require.NoError(t, err) + + // start the exporter + err = exp.Start(context.Background(), componenttest.NewNopHost()) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, exp.Shutdown(context.Background())) + }) + + // generate data + logs := plog.NewLogs() + err = exp.ConsumeLogs(context.Background(), logs) + require.NoError(t, err) + + srv.Close() + }) + } + }) } func createBackend(endpoint string, handler func(writer http.ResponseWriter, request *http.Request)) *httptest.Server { diff --git a/exporter/otlphttpexporter/package_test.go b/exporter/otlphttpexporter/package_test.go new file mode 100644 index 00000000000..07858386cc4 --- /dev/null +++ b/exporter/otlphttpexporter/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package otlphttpexporter + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/exporter/otlphttpexporter/testdata/bad_invalid_encoding.yaml b/exporter/otlphttpexporter/testdata/bad_invalid_encoding.yaml new file mode 100644 index 00000000000..593aee269a5 --- /dev/null +++ b/exporter/otlphttpexporter/testdata/bad_invalid_encoding.yaml @@ -0,0 +1 @@ +encoding: invalid diff --git a/exporter/package_test.go b/exporter/package_test.go new file mode 100644 index 00000000000..cb9a4484dae --- /dev/null +++ b/exporter/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporter + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/extension/auth/authtest/mock_clientauth.go b/extension/auth/authtest/mock_clientauth.go index b9c6b80e8b0..d28546fc4a0 100644 --- a/extension/auth/authtest/mock_clientauth.go +++ b/extension/auth/authtest/mock_clientauth.go @@ -27,18 +27,18 @@ type MockClient struct { } // Start for the MockClient does nothing -func (m *MockClient) Start(_ context.Context, _ component.Host) error { +func (m *MockClient) Start(context.Context, component.Host) error { return nil } // Shutdown for the MockClient does nothing -func (m *MockClient) Shutdown(_ context.Context) error { +func (m *MockClient) Shutdown(context.Context) error { return nil } // RoundTripper for the MockClient either returns error if the mock authenticator is forced to or // returns the supplied resultRoundTripper. -func (m *MockClient) RoundTripper(_ http.RoundTripper) (http.RoundTripper, error) { +func (m *MockClient) RoundTripper(http.RoundTripper) (http.RoundTripper, error) { if m.MustError { return nil, errMockError } diff --git a/extension/auth/authtest/mock_clientauth_test.go b/extension/auth/authtest/mock_clientauth_test.go index 5b0bd18d6b5..873d62e8384 100644 --- a/extension/auth/authtest/mock_clientauth_test.go +++ b/extension/auth/authtest/mock_clientauth_test.go @@ -28,7 +28,7 @@ func TestNilStartAndShutdown(t *testing.T) { type customRoundTripper struct{} -func (c *customRoundTripper) RoundTrip(_ *http.Request) (*http.Response, error) { +func (c *customRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { return nil, nil } diff --git a/extension/auth/authtest/package_test.go b/extension/auth/authtest/package_test.go new file mode 100644 index 00000000000..b503d1f7ce2 --- /dev/null +++ b/extension/auth/authtest/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package authtest + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/extension/auth/client.go b/extension/auth/client.go index cf1bdb55fb8..d1855d8aece 100644 --- a/extension/auth/client.go +++ b/extension/auth/client.go @@ -25,7 +25,7 @@ type Client interface { PerRPCCredentials() (credentials.PerRPCCredentials, error) } -// ClientOption represents the possible options for NewServerAuthenticator. +// ClientOption represents the possible options for NewClient. type ClientOption func(*defaultClient) // ClientRoundTripperFunc specifies the function that returns a RoundTripper that can be used to authenticate HTTP requests. diff --git a/extension/auth/client_test.go b/extension/auth/client_test.go index ea643b2cc14..c3666c229b0 100644 --- a/extension/auth/client_test.go +++ b/extension/auth/client_test.go @@ -45,7 +45,7 @@ func TestClientDefaultValues(t *testing.T) { func TestWithClientStart(t *testing.T) { called := false - e := NewClient(WithClientStart(func(c context.Context, h component.Host) error { + e := NewClient(WithClientStart(func(context.Context, component.Host) error { called = true return nil })) @@ -60,7 +60,7 @@ func TestWithClientStart(t *testing.T) { func TestWithClientShutdown(t *testing.T) { called := false - e := NewClient(WithClientShutdown(func(c context.Context) error { + e := NewClient(WithClientShutdown(func(context.Context) error { called = true return nil })) diff --git a/extension/auth/go.mod b/extension/auth/go.mod index 836e37564c0..8b1b0ba6a45 100644 --- a/extension/auth/go.mod +++ b/extension/auth/go.mod @@ -1,39 +1,50 @@ module go.opentelemetry.io/collector/extension/auth -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/extension v0.85.0 - google.golang.org/grpc v1.58.1 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/extension v0.96.0 + go.uber.org/goleak v1.3.0 + google.golang.org/grpc v1.62.0 ) require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 // indirect - go.opentelemetry.io/collector/confmap v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/confmap v0.96.0 // indirect + go.opentelemetry.io/collector/pdata v1.3.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/protobuf v1.31.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -43,8 +54,6 @@ replace go.opentelemetry.io/collector/confmap => ../../confmap replace go.opentelemetry.io/collector/extension => ../ -replace go.opentelemetry.io/collector/featuregate => ../../featuregate - replace go.opentelemetry.io/collector/pdata => ../../pdata replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry diff --git a/extension/auth/go.sum b/extension/auth/go.sum index e5817058840..2f664245ecd 100644 --- a/extension/auth/go.sum +++ b/extension/auth/go.sum @@ -1,48 +1,74 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -52,20 +78,20 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -74,15 +100,16 @@ 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-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= 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/auth/package_test.go b/extension/auth/package_test.go new file mode 100644 index 00000000000..205e87026a7 --- /dev/null +++ b/extension/auth/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package auth + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/extension/auth/server_test.go b/extension/auth/server_test.go index c99ee6042d1..9e1f7a5b973 100644 --- a/extension/auth/server_test.go +++ b/extension/auth/server_test.go @@ -39,7 +39,7 @@ func TestWithServerAuthenticateFunc(t *testing.T) { // prepare authCalled := false e := NewServer( - WithServerAuthenticate(func(ctx context.Context, headers map[string][]string) (context.Context, error) { + WithServerAuthenticate(func(ctx context.Context, _ map[string][]string) (context.Context, error) { authCalled = true return ctx, nil }), @@ -55,7 +55,7 @@ func TestWithServerAuthenticateFunc(t *testing.T) { func TestWithServerStart(t *testing.T) { called := false - e := NewServer(WithServerStart(func(c context.Context, h component.Host) error { + e := NewServer(WithServerStart(func(context.Context, component.Host) error { called = true return nil })) @@ -70,7 +70,7 @@ func TestWithServerStart(t *testing.T) { func TestWithServerShutdown(t *testing.T) { called := false - e := NewServer(WithServerShutdown(func(c context.Context) error { + e := NewServer(WithServerShutdown(func(context.Context) error { called = true return nil })) diff --git a/extension/ballastextension/README.md b/extension/ballastextension/README.md index a67ab0bbbca..a82e1b7ad39 100644 --- a/extension/ballastextension/README.md +++ b/extension/ballastextension/README.md @@ -1,9 +1,24 @@ +> [!WARNING] +> The memory ballast extension is deprecated in favor of using the `GOMEMLIMIT` environment variable. +> This environment variable is available on any Collector built with Go 1.19 or higher. Official binary releases are built with Go 1.19 since v0.61.0. See [issue 8343](https://github.com/open-telemetry/opentelemetry-collector/issues/8343) for the deprecation timeline. +> +> To migrate to `GOMEMLIMIT`, set its value to 80% of the hard memory limit of your Collector. +> For example, if the Collector hard memory limit is 1GiB, set `GOMEMLIMIT` to `800MiB`. +> Check [the Go documentation](https://pkg.go.dev/runtime#hdr-Environment_Variables) for more information about `GOMEMLIMIT`'s syntax. + # Memory Ballast -| Status | | -| ------------------------ | ----------------- | -| Stability | [beta] | -| Distributions | [core], [contrib] | + +| Status | | +| ------------- |-----------| +| Stability | [deprecated] | +| Distributions | [core], [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aextension%2Fballast%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aextension%2Fballast) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aextension%2Fballast%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aextension%2Fballast) | + +[deprecated]: https://github.com/open-telemetry/opentelemetry-collector#deprecated +[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + Memory Ballast extension enables applications to configure memory ballast for the process. For more details see: - [Go memory ballast blogpost](https://web.archive.org/web/20210929130001/https://blog.twitch.tv/en/2019/04/10/go-memory-ballast-how-i-learnt-to-stop-worrying-and-love-the-heap-26c2462549a2/) @@ -46,7 +61,3 @@ extensions: memory_ballast: size_in_percentage: 20 ``` - -[beta]: https://github.com/open-telemetry/opentelemetry-collector-contrib#beta -[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib -[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol diff --git a/extension/ballastextension/factory.go b/extension/ballastextension/factory.go index 6609111dd80..b1742d9081b 100644 --- a/extension/ballastextension/factory.go +++ b/extension/ballastextension/factory.go @@ -1,6 +1,8 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +//go:generate mdatagen metadata.yaml + package ballastextension // import "go.opentelemetry.io/collector/extension/ballastextension" import ( @@ -8,20 +10,16 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/extension" + "go.opentelemetry.io/collector/extension/ballastextension/internal/metadata" "go.opentelemetry.io/collector/internal/iruntime" ) -const ( - // The value of extension "type" in configuration. - typeStr = "memory_ballast" -) - // memHandler returns the total memory of the target host/vm var memHandler = iruntime.TotalMemory // NewFactory creates a factory for FluentBit extension. func NewFactory() extension.Factory { - return extension.NewFactory(typeStr, createDefaultConfig, createExtension, component.StabilityLevelBeta) + return extension.NewFactory(metadata.Type, createDefaultConfig, createExtension, metadata.ExtensionStability) } func createDefaultConfig() component.Config { diff --git a/extension/ballastextension/go.mod b/extension/ballastextension/go.mod index b7913a24909..a6035aa3fca 100644 --- a/extension/ballastextension/go.mod +++ b/extension/ballastextension/go.mod @@ -1,47 +1,59 @@ +// Deprecated: Use the GOMEMLIMIT environment variable instead. module go.opentelemetry.io/collector/extension/ballastextension -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/confmap v0.85.0 - go.opentelemetry.io/collector/extension v0.85.0 - go.uber.org/zap v1.26.0 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/confmap v0.96.0 + go.opentelemetry.io/collector/extension v0.96.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 + go.uber.org/zap v1.27.0 ) require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/shirou/gopsutil/v3 v3.24.1 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/pdata v1.3.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -51,20 +63,12 @@ replace go.opentelemetry.io/collector/component => ../../component replace go.opentelemetry.io/collector/confmap => ../../confmap -replace go.opentelemetry.io/collector/exporter => ../../exporter - replace go.opentelemetry.io/collector/extension => ../ replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata -replace go.opentelemetry.io/collector/receiver => ../../receiver - -replace go.opentelemetry.io/collector/semconv => ../../semconv - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../zpagesextension - replace go.opentelemetry.io/collector/consumer => ../../consumer retract ( @@ -72,12 +76,4 @@ retract ( v0.69.0 // Release failed, use v0.69.1 ) -replace go.opentelemetry.io/collector/processor => ../../processor - -replace go.opentelemetry.io/collector/connector => ../../connector - -replace go.opentelemetry.io/collector/config/confignet => ../../config/confignet - replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry - -replace go.opentelemetry.io/collector/service => ../../service diff --git a/extension/ballastextension/go.sum b/extension/ballastextension/go.sum index 770757aef0d..9394f812d28 100644 --- a/extension/ballastextension/go.sum +++ b/extension/ballastextension/go.sum @@ -1,10 +1,19 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= @@ -12,33 +21,43 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= -github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= +github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -56,17 +75,24 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -76,8 +102,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -88,12 +114,13 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -102,16 +129,17 @@ 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-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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/ballastextension/internal/metadata/generated_status.go b/extension/ballastextension/internal/metadata/generated_status.go new file mode 100644 index 00000000000..c6407064c52 --- /dev/null +++ b/extension/ballastextension/internal/metadata/generated_status.go @@ -0,0 +1,27 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("memory_ballast") + scopeName = "go.opentelemetry.io/collector/extension/ballastextension" +) + +const ( + ExtensionStability = component.StabilityLevelDeprecated +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} diff --git a/extension/ballastextension/memory_ballast.go b/extension/ballastextension/memory_ballast.go index ba1b1749b6e..afbf6ec6d7d 100644 --- a/extension/ballastextension/memory_ballast.go +++ b/extension/ballastextension/memory_ballast.go @@ -21,7 +21,7 @@ type memoryBallast struct { getTotalMem func() (uint64, error) } -func (m *memoryBallast) Start(_ context.Context, _ component.Host) error { +func (m *memoryBallast) Start(context.Context, component.Host) error { // absolute value supersedes percentage setting if m.cfg.SizeMiB > 0 { m.ballastSizeBytes = m.cfg.SizeMiB * megaBytes @@ -43,7 +43,7 @@ func (m *memoryBallast) Start(_ context.Context, _ component.Host) error { return nil } -func (m *memoryBallast) Shutdown(_ context.Context) error { +func (m *memoryBallast) Shutdown(context.Context) error { m.ballast = nil return nil } diff --git a/extension/ballastextension/metadata.yaml b/extension/ballastextension/metadata.yaml new file mode 100644 index 00000000000..2909cd5cd83 --- /dev/null +++ b/extension/ballastextension/metadata.yaml @@ -0,0 +1,7 @@ +type: memory_ballast + +status: + class: extension + stability: + deprecated: [extension] + distributions: [core, contrib] diff --git a/extension/ballastextension/package_test.go b/extension/ballastextension/package_test.go new file mode 100644 index 00000000000..9035e22edbc --- /dev/null +++ b/extension/ballastextension/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package ballastextension + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/extension/extension.go b/extension/extension.go index 6b8df571b81..292358b33ba 100644 --- a/extension/extension.go +++ b/extension/extension.go @@ -16,6 +16,14 @@ import ( // to the service, examples: health check endpoint, z-pages, etc. type Extension = component.Component +// Dependent is an optional interface that can be implemented by extensions +// that depend on other extensions and must be started only after their dependencies. +// See https://github.com/open-telemetry/opentelemetry-collector/pull/8768 for examples. +type Dependent interface { + Extension + Dependencies() []component.ID +} + // PipelineWatcher is an extra interface for Extension hosted by the OpenTelemetry // Collector that is to be implemented by extensions interested in changes to pipeline // states. Typically this will be used by extensions that change their behavior if data is @@ -37,9 +45,23 @@ type PipelineWatcher interface { // wishes to be notified of the Collector's effective configuration. type ConfigWatcher interface { // NotifyConfig notifies the extension of the Collector's current effective configuration. + // The extension owns the `confmap.Conf`. Callers must ensure that it's safe for + // extensions to store the `conf` pointer and use it concurrently with any other + // instances of `conf`. NotifyConfig(ctx context.Context, conf *confmap.Conf) error } +// StatusWatcher is an extra interface for Extension hosted by the OpenTelemetry +// Collector that is to be implemented by extensions interested in changes to component +// status. +type StatusWatcher interface { + // ComponentStatusChanged notifies about a change in the source component status. + // Extensions that implement this interface must be ready that the ComponentStatusChanged + // may be called before, after or concurrently with calls to Component.Start() and Component.Shutdown(). + // The function may be called concurrently with itself. + ComponentStatusChanged(source *component.InstanceID, event *component.StatusEvent) +} + // CreateSettings is passed to Factory.Create(...) function. type CreateSettings struct { // ID returns the ID of the component that will be created. diff --git a/extension/extension_test.go b/extension/extension_test.go index 23a57d0bcc9..d3dbf80c8c3 100644 --- a/extension/extension_test.go +++ b/extension/extension_test.go @@ -21,18 +21,18 @@ type nopExtension struct { } func TestNewFactory(t *testing.T) { - const typeStr = "test" + var testType = component.MustNewType("test") defaultCfg := struct{}{} nopExtensionInstance := new(nopExtension) factory := NewFactory( - typeStr, + testType, func() component.Config { return &defaultCfg }, - func(ctx context.Context, settings CreateSettings, extension component.Config) (Extension, error) { + func(context.Context, CreateSettings, component.Config) (Extension, error) { return nopExtensionInstance, nil }, component.StabilityLevelDevelopment) - assert.EqualValues(t, typeStr, factory.Type()) + assert.EqualValues(t, testType, factory.Type()) assert.EqualValues(t, &defaultCfg, factory.CreateDefaultConfig()) assert.Equal(t, component.StabilityLevelDevelopment, factory.ExtensionStability()) @@ -48,8 +48,8 @@ func TestMakeFactoryMap(t *testing.T) { out map[component.Type]Factory } - p1 := NewFactory("p1", nil, nil, component.StabilityLevelAlpha) - p2 := NewFactory("p2", nil, nil, component.StabilityLevelAlpha) + p1 := NewFactory(component.MustNewType("p1"), nil, nil, component.StabilityLevelAlpha) + p2 := NewFactory(component.MustNewType("p2"), nil, nil, component.StabilityLevelAlpha) testCases := []testCase{ { name: "different names", @@ -61,7 +61,7 @@ func TestMakeFactoryMap(t *testing.T) { }, { name: "same name", - in: []Factory{p1, p2, NewFactory("p1", nil, nil, component.StabilityLevelAlpha)}, + in: []Factory{p1, p2, NewFactory(component.MustNewType("p1"), nil, nil, component.StabilityLevelAlpha)}, }, } for i := range testCases { @@ -79,16 +79,16 @@ func TestMakeFactoryMap(t *testing.T) { } func TestBuilder(t *testing.T) { - const typeStr = "test" + var testType = component.MustNewType("test") defaultCfg := struct{}{} - testID := component.NewID(typeStr) - unknownID := component.NewID("unknown") + testID := component.NewID(testType) + unknownID := component.MustNewID("unknown") factories, err := MakeFactoryMap([]Factory{ NewFactory( - typeStr, + testType, func() component.Config { return &defaultCfg }, - func(ctx context.Context, settings CreateSettings, extension component.Config) (Extension, error) { + func(_ context.Context, settings CreateSettings, _ component.Config) (Extension, error) { return nopExtension{CreateSettings: settings}, nil }, component.StabilityLevelDevelopment), @@ -111,20 +111,20 @@ func TestBuilder(t *testing.T) { assert.EqualError(t, err, "extension factory not available for: \"unknown\"") assert.Nil(t, missingType) - missingCfg, err := b.Create(context.Background(), createSettings(component.NewIDWithName(typeStr, "foo"))) + missingCfg, err := b.Create(context.Background(), createSettings(component.NewIDWithName(testType, "foo"))) assert.EqualError(t, err, "extension \"test/foo\" is not configured") assert.Nil(t, missingCfg) } func TestBuilderFactory(t *testing.T) { - factories, err := MakeFactoryMap([]Factory{NewFactory("foo", nil, nil, component.StabilityLevelDevelopment)}...) + factories, err := MakeFactoryMap([]Factory{NewFactory(component.MustNewType("foo"), nil, nil, component.StabilityLevelDevelopment)}...) require.NoError(t, err) - cfgs := map[component.ID]component.Config{component.NewID("foo"): struct{}{}} + cfgs := map[component.ID]component.Config{component.MustNewID("foo"): struct{}{}} b := NewBuilder(cfgs, factories) - assert.NotNil(t, b.Factory(component.NewID("foo").Type())) - assert.Nil(t, b.Factory(component.NewID("bar").Type())) + assert.NotNil(t, b.Factory(component.MustNewID("foo").Type())) + assert.Nil(t, b.Factory(component.MustNewID("bar").Type())) } func createSettings(id component.ID) CreateSettings { diff --git a/extension/extensiontest/nop_extension.go b/extension/extensiontest/nop_extension.go index 192650a0442..f92ff388d94 100644 --- a/extension/extensiontest/nop_extension.go +++ b/extension/extensiontest/nop_extension.go @@ -11,11 +11,12 @@ import ( "go.opentelemetry.io/collector/extension" ) -const typeStr = "nop" +var nopType = component.MustNewType("nop") // NewNopCreateSettings returns a new nop settings for extension.Factory Create* functions. func NewNopCreateSettings() extension.CreateSettings { return extension.CreateSettings{ + ID: component.NewID(nopType), TelemetrySettings: componenttest.NewNopTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo(), } @@ -24,7 +25,7 @@ func NewNopCreateSettings() extension.CreateSettings { // NewNopFactory returns an extension.Factory that constructs nop extensions. func NewNopFactory() extension.Factory { return extension.NewFactory( - "nop", + nopType, func() component.Config { return &nopConfig{} }, @@ -38,16 +39,16 @@ type nopConfig struct{} var nopInstance = &nopExtension{} -// nopExtension stores consumed traces and metrics for testing purposes. +// nopExtension acts as an extension for testing purposes. type nopExtension struct { component.StartFunc component.ShutdownFunc } -// NewNopBuilder returns a extension.Builder that constructs nop receivers. +// NewNopBuilder returns a extension.Builder that constructs nop extension. func NewNopBuilder() *extension.Builder { nopFactory := NewNopFactory() return extension.NewBuilder( - map[component.ID]component.Config{component.NewID(typeStr): nopFactory.CreateDefaultConfig()}, - map[component.Type]extension.Factory{typeStr: nopFactory}) + map[component.ID]component.Config{component.NewID(nopType): nopFactory.CreateDefaultConfig()}, + map[component.Type]extension.Factory{nopType: nopFactory}) } diff --git a/extension/extensiontest/nop_extension_test.go b/extension/extensiontest/nop_extension_test.go index c188feecdfc..7ebda6195ae 100644 --- a/extension/extensiontest/nop_extension_test.go +++ b/extension/extensiontest/nop_extension_test.go @@ -17,7 +17,7 @@ import ( func TestNewNopFactory(t *testing.T) { factory := NewNopFactory() require.NotNil(t, factory) - assert.Equal(t, component.Type("nop"), factory.Type()) + assert.Equal(t, component.MustNewType("nop"), factory.Type()) cfg := factory.CreateDefaultConfig() assert.Equal(t, &nopConfig{}, cfg) @@ -34,7 +34,7 @@ func TestNewNopBuilder(t *testing.T) { factory := NewNopFactory() cfg := factory.CreateDefaultConfig() set := NewNopCreateSettings() - set.ID = component.NewID(typeStr) + set.ID = component.NewID(nopType) ext, err := factory.CreateExtension(context.Background(), set, cfg) require.NoError(t, err) diff --git a/extension/extensiontest/package_test.go b/extension/extensiontest/package_test.go new file mode 100644 index 00000000000..22f7af4bd14 --- /dev/null +++ b/extension/extensiontest/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package extensiontest + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/extension/extensiontest/statuswatcher_extension.go b/extension/extensiontest/statuswatcher_extension.go new file mode 100644 index 00000000000..eee0db94165 --- /dev/null +++ b/extension/extensiontest/statuswatcher_extension.go @@ -0,0 +1,47 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package extensiontest // import "go.opentelemetry.io/collector/extension/extensiontest" + +import ( + "context" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/extension" +) + +// NewStatusWatcherExtensionCreateSettings returns a new nop settings for Create*Extension functions. +func NewStatusWatcherExtensionCreateSettings() extension.CreateSettings { + return extension.CreateSettings{ + TelemetrySettings: componenttest.NewNopTelemetrySettings(), + BuildInfo: component.NewDefaultBuildInfo(), + } +} + +// NewStatusWatcherExtensionFactory returns a component.ExtensionFactory to construct a status watcher extension. +func NewStatusWatcherExtensionFactory( + onStatusChanged func(source *component.InstanceID, event *component.StatusEvent), +) extension.Factory { + return extension.NewFactory( + component.MustNewType("statuswatcher"), + func() component.Config { + return &struct{}{} + }, + func(context.Context, extension.CreateSettings, component.Config) (component.Component, error) { + return &statusWatcherExtension{onStatusChanged: onStatusChanged}, nil + }, + component.StabilityLevelStable) +} + +// statusWatcherExtension receives status events reported via component status reporting for testing +// purposes. +type statusWatcherExtension struct { + component.StartFunc + component.ShutdownFunc + onStatusChanged func(source *component.InstanceID, event *component.StatusEvent) +} + +func (e statusWatcherExtension) ComponentStatusChanged(source *component.InstanceID, event *component.StatusEvent) { + e.onStatusChanged(source, event) +} diff --git a/extension/extensiontest/statuswatcher_extension_test.go b/extension/extensiontest/statuswatcher_extension_test.go new file mode 100644 index 00000000000..14f9859e354 --- /dev/null +++ b/extension/extensiontest/statuswatcher_extension_test.go @@ -0,0 +1,39 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package extensiontest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/extension" +) + +func TestStatusWatcherExtension(t *testing.T) { + statusChanged := false + factory := NewStatusWatcherExtensionFactory( + func(*component.InstanceID, *component.StatusEvent) { + statusChanged = true + }, + ) + require.NotNil(t, factory) + assert.Equal(t, component.MustNewType("statuswatcher"), factory.Type()) + cfg := factory.CreateDefaultConfig() + assert.Equal(t, &struct{}{}, cfg) + + ext, err := factory.CreateExtension(context.Background(), NewStatusWatcherExtensionCreateSettings(), cfg) + require.NoError(t, err) + assert.NoError(t, ext.Start(context.Background(), componenttest.NewNopHost())) + assert.False(t, statusChanged) + + ext.(extension.StatusWatcher).ComponentStatusChanged(&component.InstanceID{}, &component.StatusEvent{}) + + assert.True(t, statusChanged) + assert.NoError(t, ext.Shutdown(context.Background())) +} diff --git a/extension/go.mod b/extension/go.mod index 7ca2a872e6a..61adfe39b85 100644 --- a/extension/go.mod +++ b/extension/go.mod @@ -1,38 +1,49 @@ module go.opentelemetry.io/collector/extension -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/confmap v0.85.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/confmap v0.96.0 + go.uber.org/goleak v1.3.0 ) require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/pdata v1.3.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -40,8 +51,6 @@ replace go.opentelemetry.io/collector/component => ../component replace go.opentelemetry.io/collector/confmap => ../confmap -replace go.opentelemetry.io/collector/featuregate => ../featuregate - replace go.opentelemetry.io/collector/pdata => ../pdata replace go.opentelemetry.io/collector/config/configtelemetry => ../config/configtelemetry diff --git a/extension/go.sum b/extension/go.sum index e5817058840..2f664245ecd 100644 --- a/extension/go.sum +++ b/extension/go.sum @@ -1,48 +1,74 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -52,20 +78,20 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -74,15 +100,16 @@ 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-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= 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/memorylimiterextension/Makefile b/extension/memorylimiterextension/Makefile new file mode 100644 index 00000000000..ded7a36092d --- /dev/null +++ b/extension/memorylimiterextension/Makefile @@ -0,0 +1 @@ +include ../../Makefile.Common diff --git a/extension/memorylimiterextension/README.md b/extension/memorylimiterextension/README.md new file mode 100644 index 00000000000..90f19a78a07 --- /dev/null +++ b/extension/memorylimiterextension/README.md @@ -0,0 +1,22 @@ +# Memory Limiter Extension + +> [!WARNING] +> The memory_limiter extension cannot be used if the deprecated memory_ballast extension is enabled. + + +| Status | | +| ------------- |-----------| +| Stability | [development] | +| Distributions | [] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aextension%2Fmemorylimiter%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aextension%2Fmemorylimiter) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aextension%2Fmemorylimiter%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aextension%2Fmemorylimiter) | + +[development]: https://github.com/open-telemetry/opentelemetry-collector#development + + +The memory limiter extension is used to prevent out of memory situations on +the collector. The extension will potentially replace the Memory Limiter Processor. +It provides better guarantees from running out of memory as it will be used by the +receivers to reject requests before converting them into OTLP. All the configurations +are the same as Memory Limiter Processor. The extension is under development and does nothing. + +see [memorylimiterprocessor](../../processor/memorylimiterprocessor/README.md) for additional details diff --git a/extension/memorylimiterextension/config.go b/extension/memorylimiterextension/config.go new file mode 100644 index 00000000000..1e5df4fe813 --- /dev/null +++ b/extension/memorylimiterextension/config.go @@ -0,0 +1,10 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package memorylimiterextension // import "go.opentelemetry.io/collector/extension/memorylimiterextension" + +import ( + "go.opentelemetry.io/collector/internal/memorylimiter" +) + +type Config = memorylimiter.Config diff --git a/extension/memorylimiterextension/factory.go b/extension/memorylimiterextension/factory.go new file mode 100644 index 00000000000..55b8efec5ea --- /dev/null +++ b/extension/memorylimiterextension/factory.go @@ -0,0 +1,33 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package memorylimiterextension // import "go.opentelemetry.io/collector/extension/memorylimiterextension" + +//go:generate mdatagen metadata.yaml + +import ( + "context" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/extension" + "go.opentelemetry.io/collector/extension/memorylimiterextension/internal/metadata" +) + +// NewFactory returns a new factory for the Memory Limiter extension. +func NewFactory() extension.Factory { + return extension.NewFactory( + metadata.Type, + createDefaultConfig, + createExtension, + metadata.ExtensionStability) +} + +// CreateDefaultConfig creates the default configuration for extension. Notice +// that the default configuration is expected to fail for this extension. +func createDefaultConfig() component.Config { + return &Config{} +} + +func createExtension(_ context.Context, set extension.CreateSettings, cfg component.Config) (extension.Extension, error) { + return newMemoryLimiter(cfg.(*Config), set.TelemetrySettings.Logger) +} diff --git a/extension/memorylimiterextension/factory_test.go b/extension/memorylimiterextension/factory_test.go new file mode 100644 index 00000000000..21bae72ee6d --- /dev/null +++ b/extension/memorylimiterextension/factory_test.go @@ -0,0 +1,50 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package memorylimiterextension + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/extension/extensiontest" + "go.opentelemetry.io/collector/internal/memorylimiter" +) + +func TestCreateDefaultConfig(t *testing.T) { + factory := NewFactory() + require.NotNil(t, factory) + + cfg := factory.CreateDefaultConfig() + assert.NotNil(t, cfg, "failed to create default config") + assert.NoError(t, componenttest.CheckConfigStruct(cfg)) +} + +func TestCreateExtension(t *testing.T) { + factory := NewFactory() + require.NotNil(t, factory) + + cfg := factory.CreateDefaultConfig() + + // Create extension with a valid config. + pCfg := cfg.(*Config) + pCfg.MemoryLimitMiB = 5722 + pCfg.MemorySpikeLimitMiB = 1907 + pCfg.CheckInterval = 100 * time.Millisecond + + tp, err := factory.CreateExtension(context.Background(), extensiontest.NewNopCreateSettings(), cfg) + assert.NoError(t, err) + assert.NotNil(t, tp) + // test if we can shutdown a monitoring routine that has not started + assert.ErrorIs(t, tp.Shutdown(context.Background()), memorylimiter.ErrShutdownNotStarted) + assert.NoError(t, tp.Start(context.Background(), componenttest.NewNopHost())) + + assert.NoError(t, tp.Shutdown(context.Background())) + // verify that no monitoring routine is running + assert.ErrorIs(t, tp.Shutdown(context.Background()), memorylimiter.ErrShutdownNotStarted) +} diff --git a/extension/memorylimiterextension/go.mod b/extension/memorylimiterextension/go.mod new file mode 100644 index 00000000000..b44b779bdc9 --- /dev/null +++ b/extension/memorylimiterextension/go.mod @@ -0,0 +1,72 @@ +module go.opentelemetry.io/collector/extension/memorylimiterextension + +go 1.21 + +require ( + github.com/stretchr/testify v1.8.4 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/extension v0.96.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/zap v1.27.0 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // 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.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/shirou/gopsutil/v3 v3.24.1 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/confmap v0.96.0 // indirect + go.opentelemetry.io/collector/pdata v1.3.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace go.opentelemetry.io/collector => ../../ + +replace go.opentelemetry.io/collector/component => ../../component + +replace go.opentelemetry.io/collector/confmap => ../../confmap + +replace go.opentelemetry.io/collector/extension => ../../extension + +replace go.opentelemetry.io/collector/featuregate => ../../featuregate + +replace go.opentelemetry.io/collector/pdata => ../../pdata + +replace go.opentelemetry.io/collector/consumer => ../../consumer + +replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry diff --git a/extension/memorylimiterextension/go.sum b/extension/memorylimiterextension/go.sum new file mode 100644 index 00000000000..9394f812d28 --- /dev/null +++ b/extension/memorylimiterextension/go.sum @@ -0,0 +1,145 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= +github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +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= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +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/memorylimiterextension/internal/metadata/generated_status.go b/extension/memorylimiterextension/internal/metadata/generated_status.go new file mode 100644 index 00000000000..5f0f98ec044 --- /dev/null +++ b/extension/memorylimiterextension/internal/metadata/generated_status.go @@ -0,0 +1,27 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("memory_limiter") + scopeName = "go.opentelemetry.io/collector/extension/memorylimiterextension" +) + +const ( + ExtensionStability = component.StabilityLevelDevelopment +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} diff --git a/extension/memorylimiterextension/memorylimiter.go b/extension/memorylimiterextension/memorylimiter.go new file mode 100644 index 00000000000..4986243ce10 --- /dev/null +++ b/extension/memorylimiterextension/memorylimiter.go @@ -0,0 +1,40 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package memorylimiterextension // import "go.opentelemetry.io/collector/extension/memorylimiterextension" + +import ( + "context" + + "go.uber.org/zap" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/internal/memorylimiter" +) + +type memoryLimiterExtension struct { + memLimiter *memorylimiter.MemoryLimiter +} + +// newMemoryLimiter returns a new memorylimiter extension. +func newMemoryLimiter(cfg *Config, logger *zap.Logger) (*memoryLimiterExtension, error) { + ml, err := memorylimiter.NewMemoryLimiter(cfg, logger) + if err != nil { + return nil, err + } + + return &memoryLimiterExtension{memLimiter: ml}, nil +} + +func (ml *memoryLimiterExtension) Start(ctx context.Context, host component.Host) error { + return ml.memLimiter.Start(ctx, host) +} + +func (ml *memoryLimiterExtension) Shutdown(ctx context.Context) error { + return ml.memLimiter.Shutdown(ctx) +} + +// MustRefuse returns if the caller should deny because memory has reached it's configured limits +func (ml *memoryLimiterExtension) MustRefuse() bool { + return ml.memLimiter.MustRefuse() +} diff --git a/extension/memorylimiterextension/memorylimiter_test.go b/extension/memorylimiterextension/memorylimiter_test.go new file mode 100644 index 00000000000..2a63a497b08 --- /dev/null +++ b/extension/memorylimiterextension/memorylimiter_test.go @@ -0,0 +1,106 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package memorylimiterextension + +import ( + "context" + "runtime" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "go.uber.org/zap" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/internal/iruntime" + "go.opentelemetry.io/collector/internal/memorylimiter" +) + +func TestMemoryPressureResponse(t *testing.T) { + ctx := context.Background() + + tests := []struct { + name string + mlCfg *Config + memAlloc uint64 + expectError bool + }{ + { + name: "Below memAllocLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 1, + }, + memAlloc: 800, + expectError: false, + }, + { + name: "Above memAllocLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 1, + }, + memAlloc: 1800, + expectError: true, + }, + { + name: "Below memSpikeLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 10, + }, + memAlloc: 800, + expectError: false, + }, + { + name: "Above memSpikeLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 11, + }, + memAlloc: 800, + expectError: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + memorylimiter.GetMemoryFn = totalMemory + memorylimiter.ReadMemStatsFn = func(ms *runtime.MemStats) { + ms.Alloc = tt.memAlloc + } + ml, err := newMemoryLimiter(tt.mlCfg, zap.NewNop()) + assert.NoError(t, err) + + assert.NoError(t, ml.Start(ctx, &mockHost{})) + ml.memLimiter.CheckMemLimits() + mustRefuse := ml.MustRefuse() + if tt.expectError { + assert.True(t, mustRefuse) + } else { + assert.NoError(t, err) + } + assert.NoError(t, ml.Shutdown(ctx)) + }) + } + t.Cleanup(func() { + memorylimiter.GetMemoryFn = iruntime.TotalMemory + memorylimiter.ReadMemStatsFn = runtime.ReadMemStats + }) +} + +type mockHost struct { + component.Host +} + +func (h *mockHost) GetExtensions() map[component.ID]component.Component { + return make(map[component.ID]component.Component) +} + +func totalMemory() (uint64, error) { + return uint64(2048), nil +} diff --git a/extension/memorylimiterextension/metadata.yaml b/extension/memorylimiterextension/metadata.yaml new file mode 100644 index 00000000000..75f16b8f750 --- /dev/null +++ b/extension/memorylimiterextension/metadata.yaml @@ -0,0 +1,7 @@ +type: memory_limiter + +status: + class: extension + stability: + development: [extension] + distributions: [] diff --git a/extension/memorylimiterextension/testdata/config.yaml b/extension/memorylimiterextension/testdata/config.yaml new file mode 100644 index 00000000000..4aa0385c000 --- /dev/null +++ b/extension/memorylimiterextension/testdata/config.yaml @@ -0,0 +1,19 @@ +# check_interval is the time between measurements of memory usage for the +# purposes of avoiding going over the limits. Defaults to zero, so no +# checks will be performed. Values below 1 second are not recommended since +# it can result in unnecessary CPU consumption. +check_interval: 5s + +# Maximum amount of memory, in MiB, targeted to be allocated by the process heap. +# Note that typically the total memory usage of process will be about 50MiB higher +# than this value. +limit_mib: 4000 + +# The maximum, in MiB, spike expected between the measurements of memory usage. +spike_limit_mib: 500 + +# the maximum amount of memory, in %, targeted to be allocated by the process +limit_percentage: 0 + +# the maximum, in percents against the total memory, spike expected between the measurements of memory usage. +spike_limit_percentage: 0 \ No newline at end of file diff --git a/extension/package_test.go b/extension/package_test.go new file mode 100644 index 00000000000..8a71f79db26 --- /dev/null +++ b/extension/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package extension + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/extension/zpagesextension/README.md b/extension/zpagesextension/README.md index 4af9999c3f8..bdae98913ef 100644 --- a/extension/zpagesextension/README.md +++ b/extension/zpagesextension/README.md @@ -1,9 +1,16 @@ # zPages -| Status | | -| ------------------------ | ----------------- | -| Stability | [beta] | -| Distributions | [core], [contrib] | + +| Status | | +| ------------- |-----------| +| Stability | [beta] | +| Distributions | [core], [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aextension%2Fzpages%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aextension%2Fzpages) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aextension%2Fzpages%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aextension%2Fzpages) | + +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + Enables an extension that serves zPages, an HTTP endpoint that provides live data for debugging different components that were properly instrumented for such. @@ -68,13 +75,3 @@ example They also allow you to quickly examine error samples Example URL: http://localhost:55679/debug/tracez - -### RpcZ -The Rpcz route is available to help examine statistics of remote procedure calls (RPCs) -that are properly instrumented. For example when using gRPC - -Example URL: http://localhost:55679/debug/rpcz - -[beta]: https://github.com/open-telemetry/opentelemetry-collector-contrib#beta -[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib -[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol diff --git a/extension/zpagesextension/config.go b/extension/zpagesextension/config.go index 090dbfd6e1a..6702491ad0d 100644 --- a/extension/zpagesextension/config.go +++ b/extension/zpagesextension/config.go @@ -15,7 +15,7 @@ type Config struct { // TCPAddr is the address and port in which the zPages will be listening to. // Use localhost: to make it available only locally, or ":" to // make it available on all network interfaces. - TCPAddr confignet.TCPAddr `mapstructure:",squash"` + TCPAddr confignet.TCPAddrConfig `mapstructure:",squash"` } var _ component.Config = (*Config)(nil) diff --git a/extension/zpagesextension/config_test.go b/extension/zpagesextension/config_test.go index 7aa2b55706f..f79e74d25c9 100644 --- a/extension/zpagesextension/config_test.go +++ b/extension/zpagesextension/config_test.go @@ -31,7 +31,7 @@ func TestUnmarshalConfig(t *testing.T) { assert.NoError(t, component.UnmarshalConfig(cm, cfg)) assert.Equal(t, &Config{ - TCPAddr: confignet.TCPAddr{ + TCPAddr: confignet.TCPAddrConfig{ Endpoint: "localhost:56888", }, }, cfg) diff --git a/extension/zpagesextension/doc.go b/extension/zpagesextension/doc.go index 8cb9684f42a..8f6d1cc6b11 100644 --- a/extension/zpagesextension/doc.go +++ b/extension/zpagesextension/doc.go @@ -1,6 +1,8 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +//go:generate mdatagen metadata.yaml + // Package zpagesextension implements an extension that exposes zPages of // properly instrumented components. package zpagesextension // import "go.opentelemetry.io/collector/extension/zpagesextension" diff --git a/extension/zpagesextension/factory.go b/extension/zpagesextension/factory.go index dae6eb57f0b..ecb94cc0f97 100644 --- a/extension/zpagesextension/factory.go +++ b/extension/zpagesextension/factory.go @@ -9,23 +9,21 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/confignet" "go.opentelemetry.io/collector/extension" + "go.opentelemetry.io/collector/extension/zpagesextension/internal/metadata" ) const ( - // The value of extension "type" in configuration. - typeStr = "zpages" - defaultEndpoint = "localhost:55679" ) // NewFactory creates a factory for Z-Pages extension. func NewFactory() extension.Factory { - return extension.NewFactory(typeStr, createDefaultConfig, createExtension, component.StabilityLevelBeta) + return extension.NewFactory(metadata.Type, createDefaultConfig, createExtension, metadata.ExtensionStability) } func createDefaultConfig() component.Config { return &Config{ - TCPAddr: confignet.TCPAddr{ + TCPAddr: confignet.TCPAddrConfig{ Endpoint: defaultEndpoint, }, } diff --git a/extension/zpagesextension/factory_test.go b/extension/zpagesextension/factory_test.go index b2e9a056dbf..fc1bcc512a1 100644 --- a/extension/zpagesextension/factory_test.go +++ b/extension/zpagesextension/factory_test.go @@ -19,7 +19,7 @@ import ( func TestFactory_CreateDefaultConfig(t *testing.T) { cfg := createDefaultConfig() assert.Equal(t, &Config{ - TCPAddr: confignet.TCPAddr{ + TCPAddr: confignet.TCPAddrConfig{ Endpoint: "localhost:55679", }, }, diff --git a/extension/zpagesextension/go.mod b/extension/zpagesextension/go.mod index 3036a69b7bd..4e795a8d6ac 100644 --- a/extension/zpagesextension/go.mod +++ b/extension/zpagesextension/go.mod @@ -1,47 +1,62 @@ module go.opentelemetry.io/collector/extension/zpagesextension -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/confignet v0.85.0 - go.opentelemetry.io/collector/confmap v0.85.0 - go.opentelemetry.io/collector/extension v0.85.0 - go.opentelemetry.io/contrib/zpages v0.44.0 - go.opentelemetry.io/otel/sdk v1.18.0 - go.opentelemetry.io/otel/trace v1.18.0 - go.uber.org/zap v1.26.0 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/confignet v0.96.0 + go.opentelemetry.io/collector/confmap v0.96.0 + go.opentelemetry.io/collector/extension v0.96.0 + go.opentelemetry.io/contrib/zpages v0.49.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 + go.uber.org/zap v1.27.0 ) require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/service v0.0.0-20230915215502-07938f20fcc7 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/pdata v1.3.0 // indirect + go.opentelemetry.io/contrib/config v0.4.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -53,22 +68,12 @@ replace go.opentelemetry.io/collector/config/confignet => ../../config/confignet replace go.opentelemetry.io/collector/confmap => ../../confmap -replace go.opentelemetry.io/collector/exporter => ../../exporter - replace go.opentelemetry.io/collector/extension => ../ replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata -replace go.opentelemetry.io/collector/processor => ../../processor - -replace go.opentelemetry.io/collector/receiver => ../../receiver - -replace go.opentelemetry.io/collector/semconv => ../../semconv - -replace go.opentelemetry.io/collector/service => ../../service - replace go.opentelemetry.io/collector/consumer => ../../consumer retract ( @@ -76,6 +81,4 @@ retract ( v0.69.0 // Release failed, use v0.69.1 ) -replace go.opentelemetry.io/collector/connector => ../../connector - replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry diff --git a/extension/zpagesextension/go.sum b/extension/zpagesextension/go.sum index a8d1d11a064..1210952ad72 100644 --- a/extension/zpagesextension/go.sum +++ b/extension/zpagesextension/go.sum @@ -1,135 +1,116 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/zpages v0.44.0 h1:9J/cxTTWhM6kzgdaBt6NiXS2HUreXn/eW2M+vzHgDAQ= -go.opentelemetry.io/contrib/zpages v0.44.0/go.mod h1:G3eNCGhodjn2wIdM+i6GneZb1Cqg6dNRBlm1cpNEElg= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/contrib/config v0.4.0 h1:Xb+ncYOqseLroMuBesGNRgVQolXcXOhMj7EhGwJCdHs= +go.opentelemetry.io/contrib/config v0.4.0/go.mod h1:drNk2xRqLWW4/amk6Uh1S+sDAJTc7bcEEN1GfJzj418= +go.opentelemetry.io/contrib/zpages v0.49.0 h1:Wk217PkNBxcKWnIQpwtbZZE286K4ZY9uajnM5woSeLU= +go.opentelemetry.io/contrib/zpages v0.49.0/go.mod h1:6alLi5mmkZWbAtZMRPd1ffIgkTcsU9OTHQF2NbSOhrQ= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -137,37 +118,20 @@ 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/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/extension/zpagesextension/internal/metadata/generated_status.go b/extension/zpagesextension/internal/metadata/generated_status.go new file mode 100644 index 00000000000..21ba9b8e88e --- /dev/null +++ b/extension/zpagesextension/internal/metadata/generated_status.go @@ -0,0 +1,27 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("zpages") + scopeName = "go.opentelemetry.io/collector/extension/zpagesextension" +) + +const ( + ExtensionStability = component.StabilityLevelBeta +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} diff --git a/extension/zpagesextension/metadata.yaml b/extension/zpagesextension/metadata.yaml new file mode 100644 index 00000000000..558eec8fccd --- /dev/null +++ b/extension/zpagesextension/metadata.yaml @@ -0,0 +1,7 @@ +type: zpages + +status: + class: extension + stability: + beta: [extension] + distributions: [core, contrib] diff --git a/extension/zpagesextension/package_test.go b/extension/zpagesextension/package_test.go new file mode 100644 index 00000000000..40ce0f11cc4 --- /dev/null +++ b/extension/zpagesextension/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package zpagesextension + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/extension/zpagesextension/zpagesextension.go b/extension/zpagesextension/zpagesextension.go index 84c321d4221..5e331966b01 100644 --- a/extension/zpagesextension/zpagesextension.go +++ b/extension/zpagesextension/zpagesextension.go @@ -67,7 +67,7 @@ func (zpe *zpagesExtension) Start(_ context.Context, host component.Host) error // Start the listener here so we can have earlier failure if port is // already in use. - ln, err := zpe.config.TCPAddr.Listen() + ln, err := zpe.config.TCPAddr.Listen(context.Background()) if err != nil { return err } @@ -79,7 +79,7 @@ func (zpe *zpagesExtension) Start(_ context.Context, host component.Host) error defer close(zpe.stopCh) if errHTTP := zpe.server.Serve(ln); errHTTP != nil && !errors.Is(errHTTP, http.ErrServerClosed) { - host.ReportFatalError(errHTTP) + zpe.telemetry.ReportStatus(component.NewFatalErrorEvent(errHTTP)) } }() diff --git a/extension/zpagesextension/zpagesextension_test.go b/extension/zpagesextension/zpagesextension_test.go index b61c12129a1..462ca58cf07 100644 --- a/extension/zpagesextension/zpagesextension_test.go +++ b/extension/zpagesextension/zpagesextension_test.go @@ -28,7 +28,7 @@ func newZPagesHost() *zpagesHost { return &zpagesHost{Host: componenttest.NewNopHost()} } -func (*zpagesHost) RegisterZPages(_ *http.ServeMux, _ string) {} +func (*zpagesHost) RegisterZPages(*http.ServeMux, string) {} var _ registerableTracerProvider = (*registerableProvider)(nil) var _ registerableTracerProvider = sdktrace.NewTracerProvider() @@ -48,7 +48,7 @@ func newZpagesTelemetrySettings() component.TelemetrySettings { func TestZPagesExtensionUsage(t *testing.T) { cfg := &Config{ - TCPAddr: confignet.TCPAddr{ + TCPAddr: confignet.TCPAddrConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), }, } @@ -80,7 +80,7 @@ func TestZPagesExtensionPortAlreadyInUse(t *testing.T) { defer ln.Close() cfg := &Config{ - TCPAddr: confignet.TCPAddr{ + TCPAddr: confignet.TCPAddrConfig{ Endpoint: endpoint, }, } @@ -92,7 +92,7 @@ func TestZPagesExtensionPortAlreadyInUse(t *testing.T) { func TestZPagesMultipleStarts(t *testing.T) { cfg := &Config{ - TCPAddr: confignet.TCPAddr{ + TCPAddr: confignet.TCPAddrConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), }, } @@ -109,7 +109,7 @@ func TestZPagesMultipleStarts(t *testing.T) { func TestZPagesMultipleShutdowns(t *testing.T) { cfg := &Config{ - TCPAddr: confignet.TCPAddr{ + TCPAddr: confignet.TCPAddrConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), }, } @@ -124,7 +124,7 @@ func TestZPagesMultipleShutdowns(t *testing.T) { func TestZPagesShutdownWithoutStart(t *testing.T) { cfg := &Config{ - TCPAddr: confignet.TCPAddr{ + TCPAddr: confignet.TCPAddrConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), }, } diff --git a/featuregate/flag.go b/featuregate/flag.go index 3ff105d3e69..95012968126 100644 --- a/featuregate/flag.go +++ b/featuregate/flag.go @@ -10,9 +10,19 @@ import ( "go.uber.org/multierr" ) -// NewFlag returns a flag.Value that directly applies feature gate statuses to a Registry. -func NewFlag(reg *Registry) flag.Value { - return &flagValue{reg: reg} +const ( + featureGatesFlag = "feature-gates" + featureGatesFlagDescription = "Comma-delimited list of feature gate identifiers. Prefix with '-' to disable the feature. '+' or no prefix will enable the feature." +) + +// RegisterFlagsOption is an option for RegisterFlags. +type RegisterFlagsOption interface { + private() +} + +// RegisterFlags that directly applies feature gate statuses to a Registry. +func (r *Registry) RegisterFlags(flagSet *flag.FlagSet, _ ...RegisterFlagsOption) { + flagSet.Var(&flagValue{reg: r}, featureGatesFlag, featureGatesFlagDescription) } // flagValue implements the flag.Value interface and directly applies feature gate statuses to a Registry. diff --git a/featuregate/flag_test.go b/featuregate/flag_test.go index b7ee5fc433c..0eb60330794 100644 --- a/featuregate/flag_test.go +++ b/featuregate/flag_test.go @@ -4,6 +4,7 @@ package featuregate import ( + "flag" "testing" "github.com/stretchr/testify/assert" @@ -113,18 +114,21 @@ func TestNewFlag(t *testing.T) { reg.MustRegister("beta", StageBeta) reg.MustRegister("deprecated", StageDeprecated, WithRegisterToVersion("1.0.0")) reg.MustRegister("stable", StageStable, WithRegisterToVersion("1.0.0")) - v := NewFlag(reg) + fs := flag.NewFlagSet("test", flag.ContinueOnError) + reg.RegisterFlags(fs) + registrationFlag := fs.Lookup(featureGatesFlag) + require.NotNil(t, registrationFlag) if tt.expectedSetErr { - require.Error(t, v.Set(tt.input)) + require.Error(t, registrationFlag.Value.Set(tt.input)) } else { - require.NoError(t, v.Set(tt.input)) + require.NoError(t, registrationFlag.Value.Set(tt.input)) } got := map[string]bool{} reg.VisitAll(func(g *Gate) { got[g.ID()] = g.IsEnabled() }) assert.Equal(t, tt.expected, got) - assert.Equal(t, tt.expectedStr, v.String()) + assert.Equal(t, tt.expectedStr, registrationFlag.Value.String()) }) } } diff --git a/featuregate/gate.go b/featuregate/gate.go index 2b6cae31e85..a250ceb9a86 100644 --- a/featuregate/gate.go +++ b/featuregate/gate.go @@ -3,7 +3,12 @@ package featuregate // import "go.opentelemetry.io/collector/featuregate" -import "sync/atomic" +import ( + "fmt" + "sync/atomic" + + "github.com/hashicorp/go-version" +) // Gate is an immutable object that is owned by the Registry and represents an individual feature that // may be enabled or disabled based on the lifecycle state of the feature and CLI flags specified by the user. @@ -11,8 +16,8 @@ type Gate struct { id string description string referenceURL string - fromVersion string - toVersion string + fromVersion *version.Version + toVersion *version.Version stage Stage enabled *atomic.Bool } @@ -44,10 +49,10 @@ func (g *Gate) ReferenceURL() string { // FromVersion returns the version information when the Gate's was added. func (g *Gate) FromVersion() string { - return g.fromVersion + return fmt.Sprintf("v%s", g.fromVersion) } // ToVersion returns the version information when Gate's in StageStable. func (g *Gate) ToVersion() string { - return g.toVersion + return fmt.Sprintf("v%s", g.toVersion) } diff --git a/featuregate/gate_test.go b/featuregate/gate_test.go index ece1494eecb..be111b4e687 100644 --- a/featuregate/gate_test.go +++ b/featuregate/gate_test.go @@ -7,20 +7,27 @@ import ( "sync/atomic" "testing" + "github.com/hashicorp/go-version" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestGate(t *testing.T) { enabled := &atomic.Bool{} enabled.Store(true) + from, err := version.NewVersion("v0.61.0") + require.NoError(t, err) + to, err := version.NewVersion("v0.64.0") + require.NoError(t, err) + g := &Gate{ id: "test", description: "test gate", enabled: enabled, stage: StageAlpha, referenceURL: "http://example.com", - fromVersion: "v0.61.0", - toVersion: "v0.64.0", + fromVersion: from, + toVersion: to, } assert.Equal(t, "test", g.ID()) diff --git a/featuregate/go.mod b/featuregate/go.mod index 1597ac80cc6..4382445ec39 100644 --- a/featuregate/go.mod +++ b/featuregate/go.mod @@ -1,9 +1,11 @@ module go.opentelemetry.io/collector/featuregate -go 1.20 +go 1.21 require ( + github.com/hashicorp/go-version v1.6.0 github.com/stretchr/testify v1.8.4 + go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 ) diff --git a/featuregate/go.sum b/featuregate/go.sum index 3a025c4981e..f198f93ff2e 100644 --- a/featuregate/go.sum +++ b/featuregate/go.sum @@ -1,6 +1,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -16,6 +18,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/featuregate/package_test.go b/featuregate/package_test.go new file mode 100644 index 00000000000..77d7a03b5d0 --- /dev/null +++ b/featuregate/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package featuregate + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/featuregate/registry.go b/featuregate/registry.go index e734711082e..69486d623ee 100644 --- a/featuregate/registry.go +++ b/featuregate/registry.go @@ -4,13 +4,29 @@ package featuregate // import "go.opentelemetry.io/collector/featuregate" import ( + "errors" "fmt" + "net/url" + "regexp" "sort" "sync" "sync/atomic" + + "github.com/hashicorp/go-version" +) + +var ( + globalRegistry = NewRegistry() + + // idRegexp is used to validate the ID of a Gate. + // IDs' characters must be alphanumeric or dots. + idRegexp = regexp.MustCompile(`^[0-9a-zA-Z\.]*$`) ) -var globalRegistry = NewRegistry() +var ( + // ErrAlreadyRegistered is returned when adding a Gate that is already registered. + ErrAlreadyRegistered = errors.New("gate is already registered") +) // GlobalRegistry returns the global Registry. func GlobalRegistry() *Registry { @@ -28,43 +44,66 @@ func NewRegistry() *Registry { // RegisterOption allows to configure additional information about a Gate during registration. type RegisterOption interface { - apply(g *Gate) + apply(g *Gate) error } -type registerOptionFunc func(g *Gate) +type registerOptionFunc func(g *Gate) error -func (ro registerOptionFunc) apply(g *Gate) { - ro(g) +func (ro registerOptionFunc) apply(g *Gate) error { + return ro(g) } // WithRegisterDescription adds description for the Gate. func WithRegisterDescription(description string) RegisterOption { - return registerOptionFunc(func(g *Gate) { + return registerOptionFunc(func(g *Gate) error { g.description = description + return nil }) } // WithRegisterReferenceURL adds a URL that has all the contextual information about the Gate. -func WithRegisterReferenceURL(url string) RegisterOption { - return registerOptionFunc(func(g *Gate) { - g.referenceURL = url +// referenceURL must be a valid URL as defined by `net/url.Parse`. +func WithRegisterReferenceURL(referenceURL string) RegisterOption { + return registerOptionFunc(func(g *Gate) error { + if _, err := url.Parse(referenceURL); err != nil { + return fmt.Errorf("WithRegisterReferenceURL: invalid reference URL %q: %w", referenceURL, err) + } + + g.referenceURL = referenceURL + return nil }) } // WithRegisterFromVersion is used to set the Gate "FromVersion". // The "FromVersion" contains the Collector release when a feature is introduced. +// fromVersion must be a valid version string: it may start with 'v' and must be in the format Major.Minor.Patch[-PreRelease]. +// PreRelease is optional and may have dashes, tildes and ASCII alphanumeric characters. func WithRegisterFromVersion(fromVersion string) RegisterOption { - return registerOptionFunc(func(g *Gate) { - g.fromVersion = fromVersion + return registerOptionFunc(func(g *Gate) error { + from, err := version.NewVersion(fromVersion) + if err != nil { + return fmt.Errorf("WithRegisterFromVersion: invalid version %q: %w", fromVersion, err) + } + + g.fromVersion = from + return nil }) } // WithRegisterToVersion is used to set the Gate "ToVersion". // The "ToVersion", if not empty, contains the last Collector release in which you can still use a feature gate. // If the feature stage is either "Deprecated" or "Stable", the "ToVersion" is the Collector release when the feature is removed. +// toVersion must be a valid version string: it may start with 'v' and must be in the format Major.Minor.Patch[-PreRelease]. +// PreRelease is optional and may have dashes, tildes and ASCII alphanumeric characters. func WithRegisterToVersion(toVersion string) RegisterOption { - return registerOptionFunc(func(g *Gate) { - g.toVersion = toVersion + return registerOptionFunc(func(g *Gate) error { + to, err := version.NewVersion(toVersion) + if err != nil { + return fmt.Errorf("WithRegisterToVersion: invalid version %q: %w", toVersion, err) + } + + g.toVersion = to + return nil }) } @@ -77,14 +116,33 @@ func (r *Registry) MustRegister(id string, stage Stage, opts ...RegisterOption) return g } +func validateID(id string) error { + if id == "" { + return fmt.Errorf("empty ID") + } + + if !idRegexp.MatchString(id) { + return fmt.Errorf("invalid character(s) in ID") + } + return nil +} + // Register a Gate and return it. The returned Gate can be used to check if is enabled or not. +// id must be an ASCII alphanumeric nonempty string. Dots are allowed for namespacing. func (r *Registry) Register(id string, stage Stage, opts ...RegisterOption) (*Gate, error) { + if err := validateID(id); err != nil { + return nil, fmt.Errorf("invalid ID %q: %w", id, err) + } + g := &Gate{ id: id, stage: stage, } for _, opt := range opts { - opt.apply(g) + err := opt.apply(g) + if err != nil { + return nil, fmt.Errorf("failed to apply option: %w", err) + } } switch g.stage { case StageAlpha, StageDeprecated: @@ -96,11 +154,16 @@ func (r *Registry) Register(id string, stage Stage, opts ...RegisterOption) (*Ga default: return nil, fmt.Errorf("unknown stage value %q for gate %q", stage, id) } - if (g.stage == StageStable || g.stage == StageDeprecated) && g.toVersion == "" { + if (g.stage == StageStable || g.stage == StageDeprecated) && g.toVersion == nil { return nil, fmt.Errorf("no removal version set for %v gate %q", g.stage.String(), id) } + + if g.fromVersion != nil && g.toVersion != nil && g.toVersion.LessThan(g.fromVersion) { + return nil, fmt.Errorf("toVersion %q is before fromVersion %q", g.toVersion, g.fromVersion) + } + if _, loaded := r.gates.LoadOrStore(id, g); loaded { - return nil, fmt.Errorf("attempted to add pre-existing gate %q", id) + return nil, fmt.Errorf("failed to register %q: %w", id, ErrAlreadyRegistered) } return g, nil } @@ -137,7 +200,7 @@ func (r *Registry) Set(id string, enabled bool) error { // VisitAll visits all the gates in lexicographical order, calling fn for each. func (r *Registry) VisitAll(fn func(*Gate)) { var gates []*Gate - r.gates.Range(func(key, value any) bool { + r.gates.Range(func(_, value any) bool { gates = append(gates, value.(*Gate)) return true }) diff --git a/featuregate/registry_test.go b/featuregate/registry_test.go index 7bc304d1ec4..47646721857 100644 --- a/featuregate/registry_test.go +++ b/featuregate/registry_test.go @@ -17,7 +17,7 @@ func TestGlobalRegistry(t *testing.T) { func TestRegistry(t *testing.T) { r := NewRegistry() // Expect that no gates to visit. - r.VisitAll(func(gate *Gate) { + r.VisitAll(func(*Gate) { t.FailNow() }) @@ -33,7 +33,7 @@ func TestRegistry(t *testing.T) { assert.False(t, g.IsEnabled()) _, err = r.Register(id, StageBeta) - assert.Error(t, err) + assert.ErrorIs(t, err, ErrAlreadyRegistered) assert.Panics(t, func() { r.MustRegister(id, StageBeta) }) @@ -48,14 +48,14 @@ func TestRegistryApplyError(t *testing.T) { _, err := r.Register("foo", StageStable) assert.Error(t, err) assert.Error(t, r.Set("foo", true)) - r.MustRegister("foo", StageStable, WithRegisterToVersion("next")) + r.MustRegister("foo", StageStable, WithRegisterToVersion("v1.0.0")) assert.Error(t, r.Set("foo", false)) assert.Error(t, r.Set("deprecated", true)) _, err = r.Register("deprecated", StageDeprecated) assert.Error(t, err) assert.Error(t, r.Set("deprecated", true)) - r.MustRegister("deprecated", StageDeprecated, WithRegisterToVersion("next")) + r.MustRegister("deprecated", StageDeprecated, WithRegisterToVersion("v1.0.0")) assert.Error(t, r.Set("deprecated", true)) } @@ -78,78 +78,121 @@ func TestRegisterGateLifecycle(t *testing.T) { }{ { name: "StageAlpha Flag", - id: "test-gate", + id: "test.gate", stage: StageAlpha, enabled: false, shouldErr: false, }, { name: "StageAlpha Flag with all options", - id: "test-gate", + id: "test.gate", stage: StageAlpha, opts: []RegisterOption{ - WithRegisterDescription("test-gate"), + WithRegisterDescription("test.gate"), WithRegisterReferenceURL("http://example.com/issue/1"), - WithRegisterToVersion(""), + WithRegisterToVersion("v0.88.0"), }, enabled: false, shouldErr: false, }, { name: "StageBeta Flag", - id: "test-gate", + id: "test.gate", stage: StageBeta, enabled: true, shouldErr: false, }, { name: "StageStable Flag", - id: "test-gate", + id: "test.gate", stage: StageStable, opts: []RegisterOption{ - WithRegisterToVersion("next"), + WithRegisterToVersion("v1.0.0-rcv.0014"), }, enabled: true, shouldErr: false, }, { name: "StageDeprecated Flag", - id: "test-gate", + id: "test.gate", stage: StageDeprecated, opts: []RegisterOption{ - WithRegisterToVersion("next"), + WithRegisterToVersion("v0.89.0"), }, enabled: false, shouldErr: false, }, { name: "Invalid stage", - id: "test-gate", + id: "test.gate", stage: Stage(-1), shouldErr: true, }, { name: "StageStable gate missing removal version", - id: "test-gate", + id: "test.gate", stage: StageStable, shouldErr: true, }, { name: "StageDeprecated gate missing removal version", - id: "test-gate", + id: "test.gate", stage: StageDeprecated, shouldErr: true, }, { name: "Duplicate gate", - id: "existing-gate", + id: "existing.gate", stage: StageStable, shouldErr: true, }, + { + name: "Invalid gate name", + id: "+invalid.gate.name", + stage: StageAlpha, + shouldErr: true, + }, + { + name: "Invalid empty gate", + id: "", + stage: StageAlpha, + shouldErr: true, + }, + { + name: "Invalid gate to version", + id: "invalid.gate.to.version", + stage: StageAlpha, + opts: []RegisterOption{WithRegisterToVersion("invalid-version")}, + shouldErr: true, + }, + { + name: "Invalid gate from version", + id: "invalid.gate.from.version", + stage: StageAlpha, + opts: []RegisterOption{WithRegisterFromVersion("invalid-version")}, + shouldErr: true, + }, + { + name: "Invalid gate reference URL", + id: "invalid.gate.reference.URL", + stage: StageAlpha, + opts: []RegisterOption{WithRegisterReferenceURL(":invalid-url")}, + shouldErr: true, + }, + { + name: "Empty version range", + id: "invalid.gate.version.range", + stage: StageAlpha, + opts: []RegisterOption{ + WithRegisterFromVersion("v0.88.0"), + WithRegisterToVersion("v0.87.0"), + }, + shouldErr: true, + }, } { t.Run(tc.name, func(t *testing.T) { r := NewRegistry() - r.MustRegister("existing-gate", StageBeta) + r.MustRegister("existing.gate", StageBeta) if tc.shouldErr { _, err := r.Register(tc.id, tc.stage, tc.opts...) assert.Error(t, err) diff --git a/go.mod b/go.mod index 8be7b8a441d..79c836ef8ef 100644 --- a/go.mod +++ b/go.mod @@ -1,30 +1,19 @@ module go.opentelemetry.io/collector -go 1.20 +go 1.21 require ( - contrib.go.opencensus.io/exporter/prometheus v0.4.2 - github.com/prometheus/client_golang v1.16.0 - github.com/prometheus/client_model v0.4.0 - github.com/prometheus/common v0.44.0 - github.com/shirou/gopsutil/v3 v3.23.8 + github.com/shirou/gopsutil/v3 v3.24.1 github.com/stretchr/testify v1.8.4 - go.opencensus.io v0.24.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 - go.opentelemetry.io/collector/connector v0.85.0 - go.opentelemetry.io/collector/consumer v0.85.0 - go.opentelemetry.io/collector/exporter v0.85.0 - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/collector/processor v0.85.0 - go.opentelemetry.io/collector/receiver v0.85.0 - go.opentelemetry.io/collector/service v0.0.0-20230915215502-07938f20fcc7 - go.opentelemetry.io/otel v1.18.0 - go.opentelemetry.io/otel/exporters/prometheus v0.41.0 - go.opentelemetry.io/otel/sdk v1.18.0 - go.opentelemetry.io/otel/sdk/metric v0.41.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/confmap v0.96.0 + go.opentelemetry.io/collector/consumer v0.96.0 + go.opentelemetry.io/collector/featuregate v1.3.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/contrib/config v0.4.0 + go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 + go.uber.org/zap v1.27.0 ) require ( @@ -32,45 +21,51 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/prometheus/procfs v0.10.1 // indirect - github.com/prometheus/statsd_exporter v0.22.7 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - go.opentelemetry.io/collector/confmap v0.85.0 // indirect - go.opentelemetry.io/collector/extension v0.85.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect - go.uber.org/goleak v1.2.1 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -78,32 +73,14 @@ replace go.opentelemetry.io/collector/component => ./component replace go.opentelemetry.io/collector/confmap => ./confmap -replace go.opentelemetry.io/collector/config/confignet => ./config/confignet - replace go.opentelemetry.io/collector/config/configtelemetry => ./config/configtelemetry -replace go.opentelemetry.io/collector/connector => ./connector - replace go.opentelemetry.io/collector/consumer => ./consumer -replace go.opentelemetry.io/collector/exporter => ./exporter - -replace go.opentelemetry.io/collector/extension => ./extension - replace go.opentelemetry.io/collector/featuregate => ./featuregate -replace go.opentelemetry.io/collector/semconv => ./semconv - replace go.opentelemetry.io/collector/pdata => ./pdata -replace go.opentelemetry.io/collector/processor => ./processor - -replace go.opentelemetry.io/collector/receiver => ./receiver - -replace go.opentelemetry.io/collector/service => ./service - -replace go.opentelemetry.io/collector/extension/zpagesextension => ./extension/zpagesextension - retract ( v0.76.0 // Depends on retracted pdata v1.0.0-rc10 module, use v0.76.1 v0.69.0 // Release failed, use v0.69.1 diff --git a/go.sum b/go.sum index c8cdbad3e4d..f060cc531e2 100644 --- a/go.sum +++ b/go.sum @@ -1,606 +1,176 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= -github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= +github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.opentelemetry.io/contrib/config v0.4.0 h1:Xb+ncYOqseLroMuBesGNRgVQolXcXOhMj7EhGwJCdHs= +go.opentelemetry.io/contrib/config v0.4.0/go.mod h1:drNk2xRqLWW4/amk6Uh1S+sDAJTc7bcEEN1GfJzj418= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/internal/cgroups/cgroup.go b/internal/cgroups/cgroup.go index 7848b0a8b1b..74ef31254d7 100644 --- a/internal/cgroups/cgroup.go +++ b/internal/cgroups/cgroup.go @@ -24,7 +24,6 @@ // THE SOFTWARE. //go:build linux -// +build linux package cgroups // import "go.opentelemetry.io/collector/internal/cgroups" diff --git a/internal/cgroups/cgroup_test.go b/internal/cgroups/cgroup_test.go index a268de10c95..f359c7c6f37 100644 --- a/internal/cgroups/cgroup_test.go +++ b/internal/cgroups/cgroup_test.go @@ -24,7 +24,6 @@ // THE SOFTWARE. //go:build linux -// +build linux package cgroups diff --git a/internal/cgroups/cgroups.go b/internal/cgroups/cgroups.go index 1e928480c1d..0b04709c199 100644 --- a/internal/cgroups/cgroups.go +++ b/internal/cgroups/cgroups.go @@ -24,7 +24,6 @@ // THE SOFTWARE. //go:build linux -// +build linux package cgroups // import "go.opentelemetry.io/collector/internal/cgroups" import ( diff --git a/internal/cgroups/cgroups_test.go b/internal/cgroups/cgroups_test.go index 960d1417ecc..3c4c0996695 100644 --- a/internal/cgroups/cgroups_test.go +++ b/internal/cgroups/cgroups_test.go @@ -24,7 +24,6 @@ // THE SOFTWARE. //go:build linux -// +build linux package cgroups diff --git a/internal/cgroups/errors.go b/internal/cgroups/errors.go index bfa1737f79c..815d01d5704 100644 --- a/internal/cgroups/errors.go +++ b/internal/cgroups/errors.go @@ -24,7 +24,6 @@ // THE SOFTWARE. //go:build linux -// +build linux package cgroups // import "go.opentelemetry.io/collector/internal/cgroups" diff --git a/internal/cgroups/mountpoint.go b/internal/cgroups/mountpoint.go index d4a6a4f97a0..69582b35aa5 100644 --- a/internal/cgroups/mountpoint.go +++ b/internal/cgroups/mountpoint.go @@ -24,7 +24,6 @@ // THE SOFTWARE. //go:build linux -// +build linux package cgroups // import "go.opentelemetry.io/collector/internal/cgroups" diff --git a/internal/cgroups/mountpoint_test.go b/internal/cgroups/mountpoint_test.go index ec13238b4c2..8ce2810f89f 100644 --- a/internal/cgroups/mountpoint_test.go +++ b/internal/cgroups/mountpoint_test.go @@ -24,7 +24,6 @@ // THE SOFTWARE. //go:build linux -// +build linux package cgroups diff --git a/internal/cgroups/package_test.go b/internal/cgroups/package_test.go new file mode 100644 index 00000000000..04c6820d3a2 --- /dev/null +++ b/internal/cgroups/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package cgroups + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/internal/cgroups/subsys.go b/internal/cgroups/subsys.go index 7e72a73add8..dfe60779a31 100644 --- a/internal/cgroups/subsys.go +++ b/internal/cgroups/subsys.go @@ -24,7 +24,6 @@ // THE SOFTWARE. //go:build linux -// +build linux package cgroups // import "go.opentelemetry.io/collector/internal/cgroups" diff --git a/internal/cgroups/subsys_test.go b/internal/cgroups/subsys_test.go index 404195618b5..18adcc835fc 100644 --- a/internal/cgroups/subsys_test.go +++ b/internal/cgroups/subsys_test.go @@ -24,7 +24,6 @@ // THE SOFTWARE. //go:build linux -// +build linux package cgroups diff --git a/internal/cgroups/util_test.go b/internal/cgroups/util_test.go index 4b254d7c41a..9babdc7802e 100644 --- a/internal/cgroups/util_test.go +++ b/internal/cgroups/util_test.go @@ -24,7 +24,6 @@ // THE SOFTWARE. //go:build linux -// +build linux package cgroups diff --git a/internal/e2e/Makefile b/internal/e2e/Makefile new file mode 100644 index 00000000000..ded7a36092d --- /dev/null +++ b/internal/e2e/Makefile @@ -0,0 +1 @@ +include ../../Makefile.Common diff --git a/internal/e2e/consume_contract_test.go b/internal/e2e/consume_contract_test.go new file mode 100644 index 00000000000..efda43101f3 --- /dev/null +++ b/internal/e2e/consume_contract_test.go @@ -0,0 +1,82 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package e2e + +import ( + "testing" + "time" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/configgrpc" + "go.opentelemetry.io/collector/config/configretry" + "go.opentelemetry.io/collector/config/configtls" + "go.opentelemetry.io/collector/exporter/exporterhelper" + "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/exporter/otlpexporter" + "go.opentelemetry.io/collector/internal/testutil" + "go.opentelemetry.io/collector/receiver/otlpreceiver" +) + +func testExporterConfig(endpoint string) component.Config { + retryConfig := configretry.NewDefaultBackOffConfig() + retryConfig.InitialInterval = time.Millisecond // interval is short for the test purposes + return &otlpexporter.Config{ + QueueConfig: exporterhelper.QueueSettings{Enabled: false}, + RetryConfig: retryConfig, + ClientConfig: configgrpc.ClientConfig{ + Endpoint: endpoint, + TLSSetting: configtls.ClientConfig{ + Insecure: true, + }, + }, + } +} + +func testReceiverConfig(endpoint string) component.Config { + cfg := otlpreceiver.NewFactory().CreateDefaultConfig() + cfg.(*otlpreceiver.Config).HTTP = nil + cfg.(*otlpreceiver.Config).GRPC.NetAddr.Endpoint = endpoint + return cfg +} + +// TestConsumeContract is an example of testing of the exporter for the contract between the +// exporter and the receiver. +func TestConsumeContractOtlpLogs(t *testing.T) { + addr := testutil.GetAvailableLocalAddress(t) + exportertest.CheckConsumeContract(exportertest.CheckConsumeContractParams{ + T: t, + NumberOfTestElements: 10, + ExporterFactory: otlpexporter.NewFactory(), + DataType: component.DataTypeLogs, + ExporterConfig: testExporterConfig(addr), + ReceiverFactory: otlpreceiver.NewFactory(), + ReceiverConfig: testReceiverConfig(addr), + }) +} + +func TestConsumeContractOtlpTraces(t *testing.T) { + addr := testutil.GetAvailableLocalAddress(t) + exportertest.CheckConsumeContract(exportertest.CheckConsumeContractParams{ + T: t, + NumberOfTestElements: 10, + DataType: component.DataTypeTraces, + ExporterFactory: otlpexporter.NewFactory(), + ExporterConfig: testExporterConfig(addr), + ReceiverFactory: otlpreceiver.NewFactory(), + ReceiverConfig: testReceiverConfig(addr), + }) +} + +func TestConsumeContractOtlpMetrics(t *testing.T) { + addr := testutil.GetAvailableLocalAddress(t) + exportertest.CheckConsumeContract(exportertest.CheckConsumeContractParams{ + T: t, + NumberOfTestElements: 10, + ExporterFactory: otlpexporter.NewFactory(), + DataType: component.DataTypeMetrics, + ExporterConfig: testExporterConfig(addr), + ReceiverFactory: otlpreceiver.NewFactory(), + ReceiverConfig: testReceiverConfig(addr), + }) +} diff --git a/internal/e2e/go.mod b/internal/e2e/go.mod new file mode 100644 index 00000000000..70e5da18f40 --- /dev/null +++ b/internal/e2e/go.mod @@ -0,0 +1,134 @@ +module go.opentelemetry.io/collector/internal/e2e + +go 1.21 + +require ( + github.com/stretchr/testify v1.8.4 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/configgrpc v0.96.0 + go.opentelemetry.io/collector/config/confighttp v0.96.0 + go.opentelemetry.io/collector/config/configretry v0.96.0 + go.opentelemetry.io/collector/config/configtls v0.96.0 + go.opentelemetry.io/collector/consumer v0.96.0 + go.opentelemetry.io/collector/exporter v0.96.0 + go.opentelemetry.io/collector/exporter/otlpexporter v0.95.0 + go.opentelemetry.io/collector/exporter/otlphttpexporter v0.95.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/collector/receiver v0.96.0 + go.opentelemetry.io/collector/receiver/otlpreceiver v0.95.0 + go.uber.org/goleak v1.3.0 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mostynb/go-grpc-compression v1.2.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/rs/cors v1.10.1 // indirect + go.opentelemetry.io/collector/config/configauth v0.96.0 // indirect + go.opentelemetry.io/collector/config/configcompression v0.96.0 // indirect + go.opentelemetry.io/collector/config/confignet v0.96.0 // indirect + go.opentelemetry.io/collector/config/configopaque v1.3.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/config/internal v0.96.0 // indirect + go.opentelemetry.io/collector/confmap v0.96.0 // indirect + go.opentelemetry.io/collector/extension v0.96.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.96.0 // indirect + go.opentelemetry.io/collector/featuregate v1.3.0 // indirect + go.opentelemetry.io/contrib/config v0.4.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace go.opentelemetry.io/collector => ../.. + +replace go.opentelemetry.io/collector/config/configopaque => ../../config/configopaque + +replace go.opentelemetry.io/collector/config/configgrpc => ../../config/configgrpc + +replace go.opentelemetry.io/collector/config/internal => ../../config/internal + +replace go.opentelemetry.io/collector/config/confignet => ../../config/confignet + +replace go.opentelemetry.io/collector/config/confighttp => ../../config/confighttp + +replace go.opentelemetry.io/collector/config/configauth => ../../config/configauth + +replace go.opentelemetry.io/collector/config/configretry => ../../config/configretry + +replace go.opentelemetry.io/collector/config/configtls => ../../config/configtls + +replace go.opentelemetry.io/collector/extension/auth => ../../extension/auth + +replace go.opentelemetry.io/collector/exporter/otlpexporter => ../../exporter/otlpexporter + +replace go.opentelemetry.io/collector/config/configcompression => ../../config/configcompression + +replace go.opentelemetry.io/collector/exporter/otlphttpexporter => ../../exporter/otlphttpexporter + +replace go.opentelemetry.io/collector/pdata => ../../pdata + +replace go.opentelemetry.io/collector/consumer => ../../consumer + +replace go.opentelemetry.io/collector/receiver/otlpreceiver => ../../receiver/otlpreceiver + +replace go.opentelemetry.io/collector/receiver => ../../receiver + +replace go.opentelemetry.io/collector/extension => ../../extension + +replace go.opentelemetry.io/collector/confmap => ../../confmap + +replace go.opentelemetry.io/collector/component => ../../component + +replace go.opentelemetry.io/collector/exporter => ../../exporter + +replace go.opentelemetry.io/collector/featuregate => ../../featuregate + +replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry diff --git a/internal/e2e/go.sum b/internal/e2e/go.sum new file mode 100644 index 00000000000..6dc69bb0e99 --- /dev/null +++ b/internal/e2e/go.sum @@ -0,0 +1,176 @@ +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68 h1:aRVqY1p2IJaBGStWMsQMpkAa83cPkCDLl80eOj0Rbz4= +cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68/go.mod h1:1a3eRNYX12fs5UABBIXS8HXVvQbX9hRB/RkEBPORpe8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mostynb/go-grpc-compression v1.2.2 h1:XaDbnRvt2+1vgr0b/l0qh4mJAfIxE0bKXtz2Znl3GGI= +github.com/mostynb/go-grpc-compression v1.2.2/go.mod h1:GOCr2KBxXcblCuczg3YdLQlcin1/NfyDA348ckuCH6w= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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/contrib/config v0.4.0 h1:Xb+ncYOqseLroMuBesGNRgVQolXcXOhMj7EhGwJCdHs= +go.opentelemetry.io/contrib/config v0.4.0/go.mod h1:drNk2xRqLWW4/amk6Uh1S+sDAJTc7bcEEN1GfJzj418= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +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= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +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= +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/internal/e2e/otlphttp_test.go b/internal/e2e/otlphttp_test.go new file mode 100644 index 00000000000..59627ab4b17 --- /dev/null +++ b/internal/e2e/otlphttp_test.go @@ -0,0 +1,364 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package e2e + +import ( + "bytes" + "compress/gzip" + "context" + "encoding/base64" + "encoding/hex" + "errors" + "fmt" + "io" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/confighttp" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/exporter/otlphttpexporter" + "go.opentelemetry.io/collector/internal/testdata" + "go.opentelemetry.io/collector/internal/testutil" + "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp" + "go.opentelemetry.io/collector/receiver/otlpreceiver" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +func TestInvalidConfig(t *testing.T) { + config := &otlphttpexporter.Config{ + ClientConfig: confighttp.ClientConfig{ + Endpoint: "", + }, + } + f := otlphttpexporter.NewFactory() + set := exportertest.NewNopCreateSettings() + _, err := f.CreateTracesExporter(context.Background(), set, config) + require.Error(t, err) + _, err = f.CreateMetricsExporter(context.Background(), set, config) + require.Error(t, err) + _, err = f.CreateLogsExporter(context.Background(), set, config) + require.Error(t, err) +} + +func TestTraceNoBackend(t *testing.T) { + addr := testutil.GetAvailableLocalAddress(t) + exp := startTracesExporter(t, "", fmt.Sprintf("http://%s/v1/traces", addr)) + td := testdata.GenerateTraces(1) + assert.Error(t, exp.ConsumeTraces(context.Background(), td)) +} + +func TestTraceInvalidUrl(t *testing.T) { + exp := startTracesExporter(t, "http:/\\//this_is_an/*/invalid_url", "") + td := testdata.GenerateTraces(1) + assert.Error(t, exp.ConsumeTraces(context.Background(), td)) + + exp = startTracesExporter(t, "", "http:/\\//this_is_an/*/invalid_url") + td = testdata.GenerateTraces(1) + assert.Error(t, exp.ConsumeTraces(context.Background(), td)) +} + +func TestTraceError(t *testing.T) { + addr := testutil.GetAvailableLocalAddress(t) + + startTracesReceiver(t, addr, consumertest.NewErr(errors.New("my_error"))) + exp := startTracesExporter(t, "", fmt.Sprintf("http://%s/v1/traces", addr)) + + td := testdata.GenerateTraces(1) + assert.Error(t, exp.ConsumeTraces(context.Background(), td)) +} + +func TestTraceRoundTrip(t *testing.T) { + addr := testutil.GetAvailableLocalAddress(t) + + tests := []struct { + name string + baseURL string + overrideURL string + }{ + { + name: "wrongbase", + baseURL: "http://wronghostname", + overrideURL: fmt.Sprintf("http://%s/v1/traces", addr), + }, + { + name: "onlybase", + baseURL: fmt.Sprintf("http://%s", addr), + overrideURL: "", + }, + { + name: "override", + baseURL: "", + overrideURL: fmt.Sprintf("http://%s/v1/traces", addr), + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + sink := new(consumertest.TracesSink) + startTracesReceiver(t, addr, sink) + exp := startTracesExporter(t, test.baseURL, test.overrideURL) + + td := testdata.GenerateTraces(1) + assert.NoError(t, exp.ConsumeTraces(context.Background(), td)) + require.Eventually(t, func() bool { + return sink.SpanCount() > 0 + }, 1*time.Second, 10*time.Millisecond) + allTraces := sink.AllTraces() + require.Len(t, allTraces, 1) + assert.EqualValues(t, td, allTraces[0]) + }) + } +} + +func TestMetricsError(t *testing.T) { + addr := testutil.GetAvailableLocalAddress(t) + + startMetricsReceiver(t, addr, consumertest.NewErr(errors.New("my_error"))) + exp := startMetricsExporter(t, "", fmt.Sprintf("http://%s/v1/metrics", addr)) + + md := testdata.GenerateMetrics(1) + assert.Error(t, exp.ConsumeMetrics(context.Background(), md)) +} + +func TestMetricsRoundTrip(t *testing.T) { + addr := testutil.GetAvailableLocalAddress(t) + + tests := []struct { + name string + baseURL string + overrideURL string + }{ + { + name: "wrongbase", + baseURL: "http://wronghostname", + overrideURL: fmt.Sprintf("http://%s/v1/metrics", addr), + }, + { + name: "onlybase", + baseURL: fmt.Sprintf("http://%s", addr), + overrideURL: "", + }, + { + name: "override", + baseURL: "", + overrideURL: fmt.Sprintf("http://%s/v1/metrics", addr), + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + sink := new(consumertest.MetricsSink) + startMetricsReceiver(t, addr, sink) + exp := startMetricsExporter(t, test.baseURL, test.overrideURL) + + md := testdata.GenerateMetrics(1) + assert.NoError(t, exp.ConsumeMetrics(context.Background(), md)) + require.Eventually(t, func() bool { + return sink.DataPointCount() > 0 + }, 1*time.Second, 10*time.Millisecond) + allMetrics := sink.AllMetrics() + require.Len(t, allMetrics, 1) + assert.EqualValues(t, md, allMetrics[0]) + }) + } +} + +func TestLogsError(t *testing.T) { + addr := testutil.GetAvailableLocalAddress(t) + + startLogsReceiver(t, addr, consumertest.NewErr(errors.New("my_error"))) + exp := startLogsExporter(t, "", fmt.Sprintf("http://%s/v1/logs", addr)) + + md := testdata.GenerateLogs(1) + assert.Error(t, exp.ConsumeLogs(context.Background(), md)) +} + +func TestLogsRoundTrip(t *testing.T) { + addr := testutil.GetAvailableLocalAddress(t) + + tests := []struct { + name string + baseURL string + overrideURL string + }{ + { + name: "wrongbase", + baseURL: "http://wronghostname", + overrideURL: fmt.Sprintf("http://%s/v1/logs", addr), + }, + { + name: "onlybase", + baseURL: fmt.Sprintf("http://%s", addr), + overrideURL: "", + }, + { + name: "override", + baseURL: "", + overrideURL: fmt.Sprintf("http://%s/v1/logs", addr), + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + sink := new(consumertest.LogsSink) + startLogsReceiver(t, addr, sink) + exp := startLogsExporter(t, test.baseURL, test.overrideURL) + + md := testdata.GenerateLogs(1) + assert.NoError(t, exp.ConsumeLogs(context.Background(), md)) + require.Eventually(t, func() bool { + return sink.LogRecordCount() > 0 + }, 1*time.Second, 10*time.Millisecond) + allLogs := sink.AllLogs() + require.Len(t, allLogs, 1) + assert.EqualValues(t, md, allLogs[0]) + }) + } +} + +func TestIssue_4221(t *testing.T) { + svr := httptest.NewServer(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { + defer func() { assert.NoError(t, r.Body.Close()) }() + compressedData, err := io.ReadAll(r.Body) + require.NoError(t, err) + gzipReader, err := gzip.NewReader(bytes.NewReader(compressedData)) + require.NoError(t, err) + data, err := io.ReadAll(gzipReader) + require.NoError(t, err) + base64Data := base64.StdEncoding.EncodeToString(data) + // Verify same base64 encoded string is received. + assert.Equal(t, "CscBCkkKIAoMc2VydmljZS5uYW1lEhAKDnVvcC5zdGFnZS1ldS0xCiUKGW91dHN5c3RlbXMubW9kdWxlLnZlcnNpb24SCAoGOTAzMzg2EnoKEQoMdW9wX2NhbmFyaWVzEgExEmUKEEMDhT8Ib0+Mhs8Zi2VR34QSCOVRPDJ5XEG5IgA5QE41aASRrxZBQE41aASRrxZKEAoKc3Bhbl9pbmRleBICGANKHwoNY29kZS5mdW5jdGlvbhIOCgxteUZ1bmN0aW9uMzZ6AA==", base64Data) + unbase64Data, err := base64.StdEncoding.DecodeString(base64Data) + require.NoError(t, err) + tr := ptraceotlp.NewExportRequest() + require.NoError(t, tr.UnmarshalProto(unbase64Data)) + span := tr.Traces().ResourceSpans().At(0).ScopeSpans().At(0).Spans().At(0) + traceID := span.TraceID() + assert.Equal(t, "4303853f086f4f8c86cf198b6551df84", hex.EncodeToString(traceID[:])) + spanID := span.SpanID() + assert.Equal(t, "e5513c32795c41b9", hex.EncodeToString(spanID[:])) + })) + defer func() { svr.Close() }() + + exp := startTracesExporter(t, "", svr.URL) + + md := ptrace.NewTraces() + rms := md.ResourceSpans().AppendEmpty() + rms.Resource().Attributes().PutStr("service.name", "uop.stage-eu-1") + rms.Resource().Attributes().PutStr("outsystems.module.version", "903386") + ils := rms.ScopeSpans().AppendEmpty() + ils.Scope().SetName("uop_canaries") + ils.Scope().SetVersion("1") + span := ils.Spans().AppendEmpty() + + var traceIDBytes [16]byte + traceIDBytesSlice, err := hex.DecodeString("4303853f086f4f8c86cf198b6551df84") + require.NoError(t, err) + copy(traceIDBytes[:], traceIDBytesSlice) + span.SetTraceID(traceIDBytes) + traceID := span.TraceID() + assert.Equal(t, "4303853f086f4f8c86cf198b6551df84", hex.EncodeToString(traceID[:])) + + var spanIDBytes [8]byte + spanIDBytesSlice, err := hex.DecodeString("e5513c32795c41b9") + require.NoError(t, err) + copy(spanIDBytes[:], spanIDBytesSlice) + span.SetSpanID(spanIDBytes) + spanID := span.SpanID() + assert.Equal(t, "e5513c32795c41b9", hex.EncodeToString(spanID[:])) + + span.SetEndTimestamp(1634684637873000000) + span.Attributes().PutInt("span_index", 3) + span.Attributes().PutStr("code.function", "myFunction36") + span.SetStartTimestamp(1634684637873000000) + + assert.NoError(t, exp.ConsumeTraces(context.Background(), md)) +} + +func startTracesExporter(t *testing.T, baseURL string, overrideURL string) exporter.Traces { + factory := otlphttpexporter.NewFactory() + cfg := createExporterConfig(baseURL, factory.CreateDefaultConfig()) + cfg.TracesEndpoint = overrideURL + exp, err := factory.CreateTracesExporter(context.Background(), exportertest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + startAndCleanup(t, exp) + return exp +} + +func startMetricsExporter(t *testing.T, baseURL string, overrideURL string) exporter.Metrics { + factory := otlphttpexporter.NewFactory() + cfg := createExporterConfig(baseURL, factory.CreateDefaultConfig()) + cfg.MetricsEndpoint = overrideURL + exp, err := factory.CreateMetricsExporter(context.Background(), exportertest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + startAndCleanup(t, exp) + return exp +} + +func startLogsExporter(t *testing.T, baseURL string, overrideURL string) exporter.Logs { + factory := otlphttpexporter.NewFactory() + cfg := createExporterConfig(baseURL, factory.CreateDefaultConfig()) + cfg.LogsEndpoint = overrideURL + exp, err := factory.CreateLogsExporter(context.Background(), exportertest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + startAndCleanup(t, exp) + return exp +} + +func createExporterConfig(baseURL string, defaultCfg component.Config) *otlphttpexporter.Config { + cfg := defaultCfg.(*otlphttpexporter.Config) + cfg.Endpoint = baseURL + cfg.QueueConfig.Enabled = false + cfg.RetryConfig.Enabled = false + return cfg +} + +func startTracesReceiver(t *testing.T, addr string, next consumer.Traces) { + factory := otlpreceiver.NewFactory() + cfg := createReceiverConfig(addr, factory.CreateDefaultConfig()) + recv, err := factory.CreateTracesReceiver(context.Background(), receivertest.NewNopCreateSettings(), cfg, next) + require.NoError(t, err) + startAndCleanup(t, recv) +} + +func startMetricsReceiver(t *testing.T, addr string, next consumer.Metrics) { + factory := otlpreceiver.NewFactory() + cfg := createReceiverConfig(addr, factory.CreateDefaultConfig()) + recv, err := factory.CreateMetricsReceiver(context.Background(), receivertest.NewNopCreateSettings(), cfg, next) + require.NoError(t, err) + startAndCleanup(t, recv) +} + +func startLogsReceiver(t *testing.T, addr string, next consumer.Logs) { + factory := otlpreceiver.NewFactory() + cfg := createReceiverConfig(addr, factory.CreateDefaultConfig()) + recv, err := factory.CreateLogsReceiver(context.Background(), receivertest.NewNopCreateSettings(), cfg, next) + require.NoError(t, err) + startAndCleanup(t, recv) +} + +func createReceiverConfig(addr string, defaultCfg component.Config) *otlpreceiver.Config { + cfg := defaultCfg.(*otlpreceiver.Config) + cfg.HTTP.Endpoint = addr + cfg.GRPC = nil + return cfg +} + +func startAndCleanup(t *testing.T, cmp component.Component) { + require.NoError(t, cmp.Start(context.Background(), componenttest.NewNopHost())) + t.Cleanup(func() { + require.NoError(t, cmp.Shutdown(context.Background())) + }) +} diff --git a/internal/e2e/package_test.go b/internal/e2e/package_test.go new file mode 100644 index 00000000000..73da050f0da --- /dev/null +++ b/internal/e2e/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package e2e + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/internal/fanoutconsumer/logs.go b/internal/fanoutconsumer/logs.go index 9b07bbc6377..bff5c1a897e 100644 --- a/internal/fanoutconsumer/logs.go +++ b/internal/fanoutconsumer/logs.go @@ -7,12 +7,9 @@ package fanoutconsumer // import "go.opentelemetry.io/collector/internal/fanoutc import ( "context" - "fmt" "go.uber.org/multierr" - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/connector" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/pdata/plog" ) @@ -20,102 +17,67 @@ import ( // NewLogs wraps multiple log consumers in a single one. // It fanouts the incoming data to all the consumers, and does smart routing: // - Clones only to the consumer that needs to mutate the data. -// - If all consumers needs to mutate the data one will get the original data. +// - If all consumers needs to mutate the data one will get the original mutable data. func NewLogs(lcs []consumer.Logs) consumer.Logs { - if len(lcs) == 1 { - // Don't wrap if no need to do it. + // Don't wrap if there is only one non-mutating consumer. + if len(lcs) == 1 && !lcs[0].Capabilities().MutatesData { return lcs[0] } - var pass []consumer.Logs - var clone []consumer.Logs - for i := 0; i < len(lcs)-1; i++ { - if !lcs[i].Capabilities().MutatesData { - pass = append(pass, lcs[i]) + + lc := &logsConsumer{} + for i := 0; i < len(lcs); i++ { + if lcs[i].Capabilities().MutatesData { + lc.mutable = append(lc.mutable, lcs[i]) } else { - clone = append(clone, lcs[i]) + lc.readonly = append(lc.readonly, lcs[i]) } } - // Give the original data to the last consumer if no other read-only consumer, - // otherwise put it in the right bucket. Never share the same data between - // a mutating and a non-mutating consumer since the non-mutating consumer may process - // data async and the mutating consumer may change the data before that. - if len(pass) == 0 || !lcs[len(lcs)-1].Capabilities().MutatesData { - pass = append(pass, lcs[len(lcs)-1]) - } else { - clone = append(clone, lcs[len(lcs)-1]) - } - return &logsConsumer{pass: pass, clone: clone} + return lc } type logsConsumer struct { - pass []consumer.Logs - clone []consumer.Logs + mutable []consumer.Logs + readonly []consumer.Logs } func (lsc *logsConsumer) Capabilities() consumer.Capabilities { - return consumer.Capabilities{MutatesData: false} + // If all consumers are mutating, then the original data will be passed to one of them. + return consumer.Capabilities{MutatesData: len(lsc.mutable) > 0 && len(lsc.readonly) == 0} } // ConsumeLogs exports the plog.Logs to all consumers wrapped by the current one. func (lsc *logsConsumer) ConsumeLogs(ctx context.Context, ld plog.Logs) error { var errs error - // Initially pass to clone exporter to avoid the case where the optimization of sending - // the incoming data to a mutating consumer is used that may change the incoming data before - // cloning. - for _, lc := range lsc.clone { - clonedLogs := plog.NewLogs() - ld.CopyTo(clonedLogs) - errs = multierr.Append(errs, lc.ConsumeLogs(ctx, clonedLogs)) - } - for _, lc := range lsc.pass { - errs = multierr.Append(errs, lc.ConsumeLogs(ctx, ld)) - } - return errs -} - -var _ connector.LogsRouter = (*logsRouter)(nil) -type logsRouter struct { - consumer.Logs - consumers map[component.ID]consumer.Logs -} + if len(lsc.mutable) > 0 { + // Clone the data before sending to all mutating consumers except the last one. + for i := 0; i < len(lsc.mutable)-1; i++ { + errs = multierr.Append(errs, lsc.mutable[i].ConsumeLogs(ctx, cloneLogs(ld))) + } + // Send data as is to the last mutating consumer only if there are no other non-mutating consumers and the + // data is mutable. Never share the same data between a mutating and a non-mutating consumer since the + // non-mutating consumer may process data async and the mutating consumer may change the data before that. + lastConsumer := lsc.mutable[len(lsc.mutable)-1] + if len(lsc.readonly) == 0 && !ld.IsReadOnly() { + errs = multierr.Append(errs, lastConsumer.ConsumeLogs(ctx, ld)) + } else { + errs = multierr.Append(errs, lastConsumer.ConsumeLogs(ctx, cloneLogs(ld))) + } + } -func NewLogsRouter(cm map[component.ID]consumer.Logs) consumer.Logs { - consumers := make([]consumer.Logs, 0, len(cm)) - for _, consumer := range cm { - consumers = append(consumers, consumer) + // Mark the data as read-only if it will be sent to more than one read-only consumer. + if len(lsc.readonly) > 1 && !ld.IsReadOnly() { + ld.MarkReadOnly() } - return &logsRouter{ - Logs: NewLogs(consumers), - consumers: cm, + for _, lc := range lsc.readonly { + errs = multierr.Append(errs, lc.ConsumeLogs(ctx, ld)) } -} -func (r *logsRouter) PipelineIDs() []component.ID { - ids := make([]component.ID, 0, len(r.consumers)) - for id := range r.consumers { - ids = append(ids, id) - } - return ids + return errs } -func (r *logsRouter) Consumer(pipelineIDs ...component.ID) (consumer.Logs, error) { - if len(pipelineIDs) == 0 { - return nil, fmt.Errorf("missing consumers") - } - consumers := make([]consumer.Logs, 0, len(pipelineIDs)) - var errors error - for _, pipelineID := range pipelineIDs { - c, ok := r.consumers[pipelineID] - if ok { - consumers = append(consumers, c) - } else { - errors = multierr.Append(errors, fmt.Errorf("missing consumer: %q", pipelineID)) - } - } - if errors != nil { - // TODO potentially this could return a NewLogs with the valid consumers - return nil, errors - } - return NewLogs(consumers), nil +func cloneLogs(ld plog.Logs) plog.Logs { + clonedLogs := plog.NewLogs() + ld.CopyTo(clonedLogs) + return clonedLogs } diff --git a/internal/fanoutconsumer/logs_test.go b/internal/fanoutconsumer/logs_test.go index 1db046b854d..8c247cb1232 100644 --- a/internal/fanoutconsumer/logs_test.go +++ b/internal/fanoutconsumer/logs_test.go @@ -6,18 +6,13 @@ package fanoutconsumer import ( "context" "errors" - "fmt" - "strconv" "testing" "github.com/stretchr/testify/assert" - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/connector" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/internal/testdata" - "go.opentelemetry.io/collector/pdata/plog" ) func TestLogsNotMultiplexing(t *testing.T) { @@ -26,6 +21,12 @@ func TestLogsNotMultiplexing(t *testing.T) { assert.Same(t, nop, lfc) } +func TestLogsNotMultiplexingMutating(t *testing.T) { + p := &mutatingLogsSink{LogsSink: new(consumertest.LogsSink)} + lfc := NewLogs([]consumer.Logs{p}) + assert.True(t, lfc.Capabilities().MutatesData) +} + func TestLogsMultiplexingNonMutating(t *testing.T) { p1 := new(consumertest.LogsSink) p2 := new(consumertest.LogsSink) @@ -57,6 +58,9 @@ func TestLogsMultiplexingNonMutating(t *testing.T) { assert.True(t, ld == p3.AllLogs()[1]) assert.EqualValues(t, ld, p3.AllLogs()[0]) assert.EqualValues(t, ld, p3.AllLogs()[1]) + + // The data should be marked as read only. + assert.True(t, ld.IsReadOnly()) } func TestLogsMultiplexingMutating(t *testing.T) { @@ -65,7 +69,7 @@ func TestLogsMultiplexingMutating(t *testing.T) { p3 := &mutatingLogsSink{LogsSink: new(consumertest.LogsSink)} lfc := NewLogs([]consumer.Logs{p1, p2, p3}) - assert.False(t, lfc.Capabilities().MutatesData) + assert.True(t, lfc.Capabilities().MutatesData) ld := testdata.GenerateLogs(1) for i := 0; i < 2; i++ { @@ -91,6 +95,46 @@ func TestLogsMultiplexingMutating(t *testing.T) { assert.True(t, ld == p3.AllLogs()[1]) assert.EqualValues(t, ld, p3.AllLogs()[0]) assert.EqualValues(t, ld, p3.AllLogs()[1]) + + // The data should not be marked as read only. + assert.False(t, ld.IsReadOnly()) +} + +func TestReadOnlyLogsMultiplexingMutating(t *testing.T) { + p1 := &mutatingLogsSink{LogsSink: new(consumertest.LogsSink)} + p2 := &mutatingLogsSink{LogsSink: new(consumertest.LogsSink)} + p3 := &mutatingLogsSink{LogsSink: new(consumertest.LogsSink)} + + lfc := NewLogs([]consumer.Logs{p1, p2, p3}) + assert.True(t, lfc.Capabilities().MutatesData) + ldOrig := testdata.GenerateLogs(1) + ld := testdata.GenerateLogs(1) + ld.MarkReadOnly() + + for i := 0; i < 2; i++ { + err := lfc.ConsumeLogs(context.Background(), ld) + if err != nil { + t.Errorf("Wanted nil got error") + return + } + } + + // All consumers should receive the cloned data. + + assert.True(t, ld != p1.AllLogs()[0]) + assert.True(t, ld != p1.AllLogs()[1]) + assert.EqualValues(t, ldOrig, p1.AllLogs()[0]) + assert.EqualValues(t, ldOrig, p1.AllLogs()[1]) + + assert.True(t, ld != p2.AllLogs()[0]) + assert.True(t, ld != p2.AllLogs()[1]) + assert.EqualValues(t, ldOrig, p2.AllLogs()[0]) + assert.EqualValues(t, ldOrig, p2.AllLogs()[1]) + + assert.True(t, ld != p3.AllLogs()[0]) + assert.True(t, ld != p3.AllLogs()[1]) + assert.EqualValues(t, ldOrig, p3.AllLogs()[0]) + assert.EqualValues(t, ldOrig, p3.AllLogs()[1]) } func TestLogsMultiplexingMixLastMutating(t *testing.T) { @@ -126,6 +170,9 @@ func TestLogsMultiplexingMixLastMutating(t *testing.T) { assert.True(t, ld != p3.AllLogs()[1]) assert.EqualValues(t, ld, p3.AllLogs()[0]) assert.EqualValues(t, ld, p3.AllLogs()[1]) + + // The data should not be marked as read only. + assert.False(t, ld.IsReadOnly()) } func TestLogsMultiplexingMixLastNonMutating(t *testing.T) { @@ -160,6 +207,9 @@ func TestLogsMultiplexingMixLastNonMutating(t *testing.T) { assert.True(t, ld == p3.AllLogs()[1]) assert.EqualValues(t, ld, p3.AllLogs()[0]) assert.EqualValues(t, ld, p3.AllLogs()[1]) + + // The data should not be marked as read only. + assert.False(t, ld.IsReadOnly()) } func TestLogsWhenErrors(t *testing.T) { @@ -195,132 +245,3 @@ type mutatingErr struct { func (mts mutatingErr) Capabilities() consumer.Capabilities { return consumer.Capabilities{MutatesData: true} } - -func TestLogsRouterMultiplexing(t *testing.T) { - var max = 20 - for numIDs := 1; numIDs < max; numIDs++ { - for numCons := 1; numCons < max; numCons++ { - for numLogs := 1; numLogs < max; numLogs++ { - t.Run( - fmt.Sprintf("%d-ids/%d-cons/%d-logs", numIDs, numCons, numLogs), - fuzzLogsRouter(numIDs, numCons, numLogs), - ) - } - } - } -} - -func fuzzLogsRouter(numIDs, numCons, numLogs int) func(*testing.T) { - return func(t *testing.T) { - allIDs := make([]component.ID, 0, numCons) - allCons := make([]consumer.Logs, 0, numCons) - allConsMap := make(map[component.ID]consumer.Logs) - - // If any consumer is mutating, the router must report mutating - for i := 0; i < numCons; i++ { - allIDs = append(allIDs, component.NewIDWithName("sink", strconv.Itoa(numCons))) - // Random chance for each consumer to be mutating - if (numCons+numLogs+i)%4 == 0 { - allCons = append(allCons, &mutatingLogsSink{LogsSink: new(consumertest.LogsSink)}) - } else { - allCons = append(allCons, new(consumertest.LogsSink)) - } - allConsMap[allIDs[i]] = allCons[i] - } - - r := NewLogsRouter(allConsMap).(connector.LogsRouter) - ld := testdata.GenerateLogs(1) - - // Keep track of how many logs each consumer should receive. - // This will be validated after every call to RouteLogs. - expected := make(map[component.ID]int, numCons) - - for i := 0; i < numLogs; i++ { - // Build a random set of ids (no duplicates) - randCons := make(map[component.ID]bool, numIDs) - for j := 0; j < numIDs; j++ { - // This number should be pretty random and less than numCons - conNum := (numCons + numIDs + i + j) % numCons - randCons[allIDs[conNum]] = true - } - - // Convert to slice, update expectations - conIDs := make([]component.ID, 0, len(randCons)) - for id := range randCons { - conIDs = append(conIDs, id) - expected[id]++ - } - - // Route to list of consumers - fanout, err := r.Consumer(conIDs...) - assert.NoError(t, err) - assert.NoError(t, fanout.ConsumeLogs(context.Background(), ld)) - - // Validate expectations for all consumers - for id := range expected { - logs := []plog.Logs{} - switch con := allConsMap[id].(type) { - case *consumertest.LogsSink: - logs = con.AllLogs() - case *mutatingLogsSink: - logs = con.AllLogs() - } - assert.Len(t, logs, expected[id]) - for n := 0; n < len(logs); n++ { - assert.EqualValues(t, ld, logs[n]) - } - } - } - } -} - -func TestLogsRouterGetConsumers(t *testing.T) { - ctx := context.Background() - ld := testdata.GenerateLogs(1) - - fooID := component.NewID("foo") - barID := component.NewID("bar") - - foo := new(consumertest.LogsSink) - bar := new(consumertest.LogsSink) - r := NewLogsRouter(map[component.ID]consumer.Logs{fooID: foo, barID: bar}).(connector.LogsRouter) - - rcs := r.PipelineIDs() - assert.Len(t, rcs, 2) - assert.ElementsMatch(t, []component.ID{fooID, barID}, rcs) - - assert.Len(t, foo.AllLogs(), 0) - assert.Len(t, bar.AllLogs(), 0) - - both, err := r.Consumer(fooID, barID) - assert.NotNil(t, both) - assert.NoError(t, err) - - assert.NoError(t, both.ConsumeLogs(ctx, ld)) - assert.Len(t, foo.AllLogs(), 1) - assert.Len(t, bar.AllLogs(), 1) - - fooOnly, err := r.Consumer(fooID) - assert.NotNil(t, fooOnly) - assert.NoError(t, err) - - assert.NoError(t, fooOnly.ConsumeLogs(ctx, ld)) - assert.Len(t, foo.AllLogs(), 2) - assert.Len(t, bar.AllLogs(), 1) - - barOnly, err := r.Consumer(barID) - assert.NotNil(t, barOnly) - assert.NoError(t, err) - - assert.NoError(t, barOnly.ConsumeLogs(ctx, ld)) - assert.Len(t, foo.AllLogs(), 2) - assert.Len(t, bar.AllLogs(), 2) - - none, err := r.Consumer() - assert.Nil(t, none) - assert.Error(t, err) - - fake, err := r.Consumer(component.NewID("fake")) - assert.Nil(t, fake) - assert.Error(t, err) -} diff --git a/internal/fanoutconsumer/metrics.go b/internal/fanoutconsumer/metrics.go index f1c1280e4c3..32d9514561d 100644 --- a/internal/fanoutconsumer/metrics.go +++ b/internal/fanoutconsumer/metrics.go @@ -5,12 +5,9 @@ package fanoutconsumer // import "go.opentelemetry.io/collector/internal/fanoutc import ( "context" - "fmt" "go.uber.org/multierr" - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/connector" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/pdata/pmetric" ) @@ -18,102 +15,67 @@ import ( // NewMetrics wraps multiple metrics consumers in a single one. // It fanouts the incoming data to all the consumers, and does smart routing: // - Clones only to the consumer that needs to mutate the data. -// - If all consumers needs to mutate the data one will get the original data. +// - If all consumers needs to mutate the data one will get the original mutable data. func NewMetrics(mcs []consumer.Metrics) consumer.Metrics { - if len(mcs) == 1 { - // Don't wrap if no need to do it. + // Don't wrap if there is only one non-mutating consumer. + if len(mcs) == 1 && !mcs[0].Capabilities().MutatesData { return mcs[0] } - var pass []consumer.Metrics - var clone []consumer.Metrics - for i := 0; i < len(mcs)-1; i++ { - if !mcs[i].Capabilities().MutatesData { - pass = append(pass, mcs[i]) + + mc := &metricsConsumer{} + for i := 0; i < len(mcs); i++ { + if mcs[i].Capabilities().MutatesData { + mc.mutable = append(mc.mutable, mcs[i]) } else { - clone = append(clone, mcs[i]) + mc.readonly = append(mc.readonly, mcs[i]) } } - // Give the original data to the last consumer if no other read-only consumer, - // otherwise put it in the right bucket. Never share the same data between - // a mutating and a non-mutating consumer since the non-mutating consumer may process - // data async and the mutating consumer may change the data before that. - if len(pass) == 0 || !mcs[len(mcs)-1].Capabilities().MutatesData { - pass = append(pass, mcs[len(mcs)-1]) - } else { - clone = append(clone, mcs[len(mcs)-1]) - } - return &metricsConsumer{pass: pass, clone: clone} + return mc } type metricsConsumer struct { - pass []consumer.Metrics - clone []consumer.Metrics + mutable []consumer.Metrics + readonly []consumer.Metrics } func (msc *metricsConsumer) Capabilities() consumer.Capabilities { - return consumer.Capabilities{MutatesData: false} + // If all consumers are mutating, then the original data will be passed to one of them. + return consumer.Capabilities{MutatesData: len(msc.mutable) > 0 && len(msc.readonly) == 0} } // ConsumeMetrics exports the pmetric.Metrics to all consumers wrapped by the current one. func (msc *metricsConsumer) ConsumeMetrics(ctx context.Context, md pmetric.Metrics) error { var errs error - // Initially pass to clone exporter to avoid the case where the optimization of sending - // the incoming data to a mutating consumer is used that may change the incoming data before - // cloning. - for _, mc := range msc.clone { - clonedMetrics := pmetric.NewMetrics() - md.CopyTo(clonedMetrics) - errs = multierr.Append(errs, mc.ConsumeMetrics(ctx, clonedMetrics)) - } - for _, mc := range msc.pass { - errs = multierr.Append(errs, mc.ConsumeMetrics(ctx, md)) - } - return errs -} - -var _ connector.MetricsRouter = (*metricsRouter)(nil) -type metricsRouter struct { - consumer.Metrics - consumers map[component.ID]consumer.Metrics -} + if len(msc.mutable) > 0 { + // Clone the data before sending to all mutating consumers except the last one. + for i := 0; i < len(msc.mutable)-1; i++ { + errs = multierr.Append(errs, msc.mutable[i].ConsumeMetrics(ctx, cloneMetrics(md))) + } + // Send data as is to the last mutating consumer only if there are no other non-mutating consumers and the + // data is mutable. Never share the same data between a mutating and a non-mutating consumer since the + // non-mutating consumer may process data async and the mutating consumer may change the data before that. + lastConsumer := msc.mutable[len(msc.mutable)-1] + if len(msc.readonly) == 0 && !md.IsReadOnly() { + errs = multierr.Append(errs, lastConsumer.ConsumeMetrics(ctx, md)) + } else { + errs = multierr.Append(errs, lastConsumer.ConsumeMetrics(ctx, cloneMetrics(md))) + } + } -func NewMetricsRouter(cm map[component.ID]consumer.Metrics) consumer.Metrics { - consumers := make([]consumer.Metrics, 0, len(cm)) - for _, consumer := range cm { - consumers = append(consumers, consumer) + // Mark the data as read-only if it will be sent to more than one read-only consumer. + if len(msc.readonly) > 1 && !md.IsReadOnly() { + md.MarkReadOnly() } - return &metricsRouter{ - Metrics: NewMetrics(consumers), - consumers: cm, + for _, mc := range msc.readonly { + errs = multierr.Append(errs, mc.ConsumeMetrics(ctx, md)) } -} -func (r *metricsRouter) PipelineIDs() []component.ID { - ids := make([]component.ID, 0, len(r.consumers)) - for id := range r.consumers { - ids = append(ids, id) - } - return ids + return errs } -func (r *metricsRouter) Consumer(pipelineIDs ...component.ID) (consumer.Metrics, error) { - if len(pipelineIDs) == 0 { - return nil, fmt.Errorf("missing consumers") - } - consumers := make([]consumer.Metrics, 0, len(pipelineIDs)) - var errors error - for _, pipelineID := range pipelineIDs { - c, ok := r.consumers[pipelineID] - if ok { - consumers = append(consumers, c) - } else { - errors = multierr.Append(errors, fmt.Errorf("missing consumer: %q", pipelineID)) - } - } - if errors != nil { - // TODO potentially this could return a NewMetrics with the valid consumers - return nil, errors - } - return NewMetrics(consumers), nil +func cloneMetrics(md pmetric.Metrics) pmetric.Metrics { + clonedMetrics := pmetric.NewMetrics() + md.CopyTo(clonedMetrics) + return clonedMetrics } diff --git a/internal/fanoutconsumer/metrics_test.go b/internal/fanoutconsumer/metrics_test.go index 8cdfeeb51fa..efb39ec552a 100644 --- a/internal/fanoutconsumer/metrics_test.go +++ b/internal/fanoutconsumer/metrics_test.go @@ -6,18 +6,13 @@ package fanoutconsumer import ( "context" "errors" - "fmt" - "strconv" "testing" "github.com/stretchr/testify/assert" - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/connector" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/internal/testdata" - "go.opentelemetry.io/collector/pdata/pmetric" ) func TestMetricsNotMultiplexing(t *testing.T) { @@ -26,6 +21,12 @@ func TestMetricsNotMultiplexing(t *testing.T) { assert.Same(t, nop, mfc) } +func TestMetricssNotMultiplexingMutating(t *testing.T) { + p := &mutatingMetricsSink{MetricsSink: new(consumertest.MetricsSink)} + lfc := NewMetrics([]consumer.Metrics{p}) + assert.True(t, lfc.Capabilities().MutatesData) +} + func TestMetricsMultiplexingNonMutating(t *testing.T) { p1 := new(consumertest.MetricsSink) p2 := new(consumertest.MetricsSink) @@ -57,6 +58,9 @@ func TestMetricsMultiplexingNonMutating(t *testing.T) { assert.True(t, md == p3.AllMetrics()[1]) assert.EqualValues(t, md, p3.AllMetrics()[0]) assert.EqualValues(t, md, p3.AllMetrics()[1]) + + // The data should be marked as read only. + assert.True(t, md.IsReadOnly()) } func TestMetricsMultiplexingMutating(t *testing.T) { @@ -65,7 +69,7 @@ func TestMetricsMultiplexingMutating(t *testing.T) { p3 := &mutatingMetricsSink{MetricsSink: new(consumertest.MetricsSink)} mfc := NewMetrics([]consumer.Metrics{p1, p2, p3}) - assert.False(t, mfc.Capabilities().MutatesData) + assert.True(t, mfc.Capabilities().MutatesData) md := testdata.GenerateMetrics(1) for i := 0; i < 2; i++ { @@ -91,6 +95,46 @@ func TestMetricsMultiplexingMutating(t *testing.T) { assert.True(t, md == p3.AllMetrics()[1]) assert.EqualValues(t, md, p3.AllMetrics()[0]) assert.EqualValues(t, md, p3.AllMetrics()[1]) + + // The data should not be marked as read only. + assert.False(t, md.IsReadOnly()) +} + +func TestReadOnlyMetricsMultiplexingMixFirstMutating(t *testing.T) { + p1 := &mutatingMetricsSink{MetricsSink: new(consumertest.MetricsSink)} + p2 := &mutatingMetricsSink{MetricsSink: new(consumertest.MetricsSink)} + p3 := &mutatingMetricsSink{MetricsSink: new(consumertest.MetricsSink)} + + mfc := NewMetrics([]consumer.Metrics{p1, p2, p3}) + assert.True(t, mfc.Capabilities().MutatesData) + mdOrig := testdata.GenerateMetrics(1) + md := testdata.GenerateMetrics(1) + md.MarkReadOnly() + + for i := 0; i < 2; i++ { + err := mfc.ConsumeMetrics(context.Background(), md) + if err != nil { + t.Errorf("Wanted nil got error") + return + } + } + + // All consumers should receive the cloned data. + + assert.True(t, md != p1.AllMetrics()[0]) + assert.True(t, md != p1.AllMetrics()[1]) + assert.EqualValues(t, mdOrig, p1.AllMetrics()[0]) + assert.EqualValues(t, mdOrig, p1.AllMetrics()[1]) + + assert.True(t, md != p2.AllMetrics()[0]) + assert.True(t, md != p2.AllMetrics()[1]) + assert.EqualValues(t, mdOrig, p2.AllMetrics()[0]) + assert.EqualValues(t, mdOrig, p2.AllMetrics()[1]) + + assert.True(t, md != p3.AllMetrics()[0]) + assert.True(t, md != p3.AllMetrics()[1]) + assert.EqualValues(t, mdOrig, p3.AllMetrics()[0]) + assert.EqualValues(t, mdOrig, p3.AllMetrics()[1]) } func TestMetricsMultiplexingMixLastMutating(t *testing.T) { @@ -126,6 +170,9 @@ func TestMetricsMultiplexingMixLastMutating(t *testing.T) { assert.True(t, md != p3.AllMetrics()[1]) assert.EqualValues(t, md, p3.AllMetrics()[0]) assert.EqualValues(t, md, p3.AllMetrics()[1]) + + // The data should not be marked as read only. + assert.False(t, md.IsReadOnly()) } func TestMetricsMultiplexingMixLastNonMutating(t *testing.T) { @@ -160,6 +207,9 @@ func TestMetricsMultiplexingMixLastNonMutating(t *testing.T) { assert.True(t, md == p3.AllMetrics()[1]) assert.EqualValues(t, md, p3.AllMetrics()[0]) assert.EqualValues(t, md, p3.AllMetrics()[1]) + + // The data should not be marked as read only. + assert.False(t, md.IsReadOnly()) } func TestMetricsWhenErrors(t *testing.T) { @@ -187,132 +237,3 @@ type mutatingMetricsSink struct { func (mts *mutatingMetricsSink) Capabilities() consumer.Capabilities { return consumer.Capabilities{MutatesData: true} } - -func TestMetricsRouterMultiplexing(t *testing.T) { - var max = 20 - for numIDs := 1; numIDs < max; numIDs++ { - for numCons := 1; numCons < max; numCons++ { - for numMetrics := 1; numMetrics < max; numMetrics++ { - t.Run( - fmt.Sprintf("%d-ids/%d-cons/%d-logs", numIDs, numCons, numMetrics), - fuzzMetricsRouter(numIDs, numCons, numMetrics), - ) - } - } - } -} - -func fuzzMetricsRouter(numIDs, numCons, numMetrics int) func(*testing.T) { - return func(t *testing.T) { - allIDs := make([]component.ID, 0, numCons) - allCons := make([]consumer.Metrics, 0, numCons) - allConsMap := make(map[component.ID]consumer.Metrics) - - // If any consumer is mutating, the router must report mutating - for i := 0; i < numCons; i++ { - allIDs = append(allIDs, component.NewIDWithName("sink", strconv.Itoa(numCons))) - // Random chance for each consumer to be mutating - if (numCons+numMetrics+i)%4 == 0 { - allCons = append(allCons, &mutatingMetricsSink{MetricsSink: new(consumertest.MetricsSink)}) - } else { - allCons = append(allCons, new(consumertest.MetricsSink)) - } - allConsMap[allIDs[i]] = allCons[i] - } - - r := NewMetricsRouter(allConsMap).(connector.MetricsRouter) - md := testdata.GenerateMetrics(1) - - // Keep track of how many logs each consumer should receive. - // This will be validated after every call to RouteMetrics. - expected := make(map[component.ID]int, numCons) - - for i := 0; i < numMetrics; i++ { - // Build a random set of ids (no duplicates) - randCons := make(map[component.ID]bool, numIDs) - for j := 0; j < numIDs; j++ { - // This number should be pretty random and less than numCons - conNum := (numCons + numIDs + i + j) % numCons - randCons[allIDs[conNum]] = true - } - - // Convert to slice, update expectations - conIDs := make([]component.ID, 0, len(randCons)) - for id := range randCons { - conIDs = append(conIDs, id) - expected[id]++ - } - - // Route to list of consumers - fanout, err := r.Consumer(conIDs...) - assert.NoError(t, err) - assert.NoError(t, fanout.ConsumeMetrics(context.Background(), md)) - - // Validate expectations for all consumers - for id := range expected { - metrics := []pmetric.Metrics{} - switch con := allConsMap[id].(type) { - case *consumertest.MetricsSink: - metrics = con.AllMetrics() - case *mutatingMetricsSink: - metrics = con.AllMetrics() - } - assert.Len(t, metrics, expected[id]) - for n := 0; n < len(metrics); n++ { - assert.EqualValues(t, md, metrics[n]) - } - } - } - } -} - -func TestMetricsRouterGetConsumers(t *testing.T) { - ctx := context.Background() - md := testdata.GenerateMetrics(1) - - fooID := component.NewID("foo") - barID := component.NewID("bar") - - foo := new(consumertest.MetricsSink) - bar := new(consumertest.MetricsSink) - r := NewMetricsRouter(map[component.ID]consumer.Metrics{fooID: foo, barID: bar}).(connector.MetricsRouter) - - rcs := r.PipelineIDs() - assert.Len(t, rcs, 2) - assert.ElementsMatch(t, []component.ID{fooID, barID}, rcs) - - assert.Len(t, foo.AllMetrics(), 0) - assert.Len(t, bar.AllMetrics(), 0) - - both, err := r.Consumer(fooID, barID) - assert.NotNil(t, both) - assert.NoError(t, err) - - assert.NoError(t, both.ConsumeMetrics(ctx, md)) - assert.Len(t, foo.AllMetrics(), 1) - assert.Len(t, bar.AllMetrics(), 1) - - fooOnly, err := r.Consumer(fooID) - assert.NotNil(t, fooOnly) - assert.NoError(t, err) - - assert.NoError(t, fooOnly.ConsumeMetrics(ctx, md)) - assert.Len(t, foo.AllMetrics(), 2) - assert.Len(t, bar.AllMetrics(), 1) - - barOnly, err := r.Consumer(barID) - assert.NotNil(t, barOnly) - assert.NoError(t, err) - - assert.NoError(t, barOnly.ConsumeMetrics(ctx, md)) - assert.Len(t, foo.AllMetrics(), 2) - assert.Len(t, bar.AllMetrics(), 2) - - none, err := r.Consumer() - assert.Nil(t, none) - assert.Error(t, err) - - fake, err := r.Consumer(component.NewID("fake")) - assert.Nil(t, fake) - assert.Error(t, err) -} diff --git a/internal/fanoutconsumer/package_test.go b/internal/fanoutconsumer/package_test.go new file mode 100644 index 00000000000..b2da7cedcee --- /dev/null +++ b/internal/fanoutconsumer/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package fanoutconsumer + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/internal/fanoutconsumer/traces.go b/internal/fanoutconsumer/traces.go index 89ecb166ec5..f9a34027017 100644 --- a/internal/fanoutconsumer/traces.go +++ b/internal/fanoutconsumer/traces.go @@ -5,12 +5,9 @@ package fanoutconsumer // import "go.opentelemetry.io/collector/internal/fanoutc import ( "context" - "fmt" "go.uber.org/multierr" - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/connector" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/pdata/ptrace" ) @@ -18,102 +15,67 @@ import ( // NewTraces wraps multiple trace consumers in a single one. // It fanouts the incoming data to all the consumers, and does smart routing: // - Clones only to the consumer that needs to mutate the data. -// - If all consumers needs to mutate the data one will get the original data. +// - If all consumers needs to mutate the data one will get the original mutable data. func NewTraces(tcs []consumer.Traces) consumer.Traces { - if len(tcs) == 1 { - // Don't wrap if no need to do it. + // Don't wrap if there is only one non-mutating consumer. + if len(tcs) == 1 && !tcs[0].Capabilities().MutatesData { return tcs[0] } - var pass []consumer.Traces - var clone []consumer.Traces - for i := 0; i < len(tcs)-1; i++ { - if !tcs[i].Capabilities().MutatesData { - pass = append(pass, tcs[i]) + + tc := &tracesConsumer{} + for i := 0; i < len(tcs); i++ { + if tcs[i].Capabilities().MutatesData { + tc.mutable = append(tc.mutable, tcs[i]) } else { - clone = append(clone, tcs[i]) + tc.readonly = append(tc.readonly, tcs[i]) } } - // Give the original data to the last consumer if no other read-only consumer, - // otherwise put it in the right bucket. Never share the same data between - // a mutating and a non-mutating consumer since the non-mutating consumer may process - // data async and the mutating consumer may change the data before that. - if len(pass) == 0 || !tcs[len(tcs)-1].Capabilities().MutatesData { - pass = append(pass, tcs[len(tcs)-1]) - } else { - clone = append(clone, tcs[len(tcs)-1]) - } - return &tracesConsumer{pass: pass, clone: clone} + return tc } type tracesConsumer struct { - pass []consumer.Traces - clone []consumer.Traces + mutable []consumer.Traces + readonly []consumer.Traces } func (tsc *tracesConsumer) Capabilities() consumer.Capabilities { - return consumer.Capabilities{MutatesData: false} + // If all consumers are mutating, then the original data will be passed to one of them. + return consumer.Capabilities{MutatesData: len(tsc.mutable) > 0 && len(tsc.readonly) == 0} } // ConsumeTraces exports the ptrace.Traces to all consumers wrapped by the current one. func (tsc *tracesConsumer) ConsumeTraces(ctx context.Context, td ptrace.Traces) error { var errs error - // Initially pass to clone exporter to avoid the case where the optimization of sending - // the incoming data to a mutating consumer is used that may change the incoming data before - // cloning. - for _, tc := range tsc.clone { - clonedTraces := ptrace.NewTraces() - td.CopyTo(clonedTraces) - errs = multierr.Append(errs, tc.ConsumeTraces(ctx, clonedTraces)) - } - for _, tc := range tsc.pass { - errs = multierr.Append(errs, tc.ConsumeTraces(ctx, td)) - } - return errs -} - -var _ connector.TracesRouter = (*tracesRouter)(nil) -type tracesRouter struct { - consumer.Traces - consumers map[component.ID]consumer.Traces -} + if len(tsc.mutable) > 0 { + // Clone the data before sending to all mutating consumers except the last one. + for i := 0; i < len(tsc.mutable)-1; i++ { + errs = multierr.Append(errs, tsc.mutable[i].ConsumeTraces(ctx, cloneTraces(td))) + } + // Send data as is to the last mutating consumer only if there are no other non-mutating consumers and the + // data is mutable. Never share the same data between a mutating and a non-mutating consumer since the + // non-mutating consumer may process data async and the mutating consumer may change the data before that. + lastConsumer := tsc.mutable[len(tsc.mutable)-1] + if len(tsc.readonly) == 0 && !td.IsReadOnly() { + errs = multierr.Append(errs, lastConsumer.ConsumeTraces(ctx, td)) + } else { + errs = multierr.Append(errs, lastConsumer.ConsumeTraces(ctx, cloneTraces(td))) + } + } -func NewTracesRouter(cm map[component.ID]consumer.Traces) consumer.Traces { - consumers := make([]consumer.Traces, 0, len(cm)) - for _, consumer := range cm { - consumers = append(consumers, consumer) + // Mark the data as read-only if it will be sent to more than one read-only consumer. + if len(tsc.readonly) > 1 && !td.IsReadOnly() { + td.MarkReadOnly() } - return &tracesRouter{ - Traces: NewTraces(consumers), - consumers: cm, + for _, tc := range tsc.readonly { + errs = multierr.Append(errs, tc.ConsumeTraces(ctx, td)) } -} -func (r *tracesRouter) PipelineIDs() []component.ID { - ids := make([]component.ID, 0, len(r.consumers)) - for id := range r.consumers { - ids = append(ids, id) - } - return ids + return errs } -func (r *tracesRouter) Consumer(pipelineIDs ...component.ID) (consumer.Traces, error) { - if len(pipelineIDs) == 0 { - return nil, fmt.Errorf("missing consumers") - } - consumers := make([]consumer.Traces, 0, len(pipelineIDs)) - var errors error - for _, pipelineID := range pipelineIDs { - c, ok := r.consumers[pipelineID] - if ok { - consumers = append(consumers, c) - } else { - errors = multierr.Append(errors, fmt.Errorf("missing consumer: %q", pipelineID)) - } - } - if errors != nil { - // TODO potentially this could return a NewTraces with the valid consumers - return nil, errors - } - return NewTraces(consumers), nil +func cloneTraces(td ptrace.Traces) ptrace.Traces { + clonedTraces := ptrace.NewTraces() + td.CopyTo(clonedTraces) + return clonedTraces } diff --git a/internal/fanoutconsumer/traces_test.go b/internal/fanoutconsumer/traces_test.go index d2147b36167..120c6524715 100644 --- a/internal/fanoutconsumer/traces_test.go +++ b/internal/fanoutconsumer/traces_test.go @@ -6,18 +6,13 @@ package fanoutconsumer import ( "context" "errors" - "fmt" - "strconv" "testing" "github.com/stretchr/testify/assert" - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/connector" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/internal/testdata" - "go.opentelemetry.io/collector/pdata/ptrace" ) func TestTracesNotMultiplexing(t *testing.T) { @@ -26,6 +21,12 @@ func TestTracesNotMultiplexing(t *testing.T) { assert.Same(t, nop, tfc) } +func TestTracesNotMultiplexingMutating(t *testing.T) { + p := &mutatingTracesSink{TracesSink: new(consumertest.TracesSink)} + lfc := NewTraces([]consumer.Traces{p}) + assert.True(t, lfc.Capabilities().MutatesData) +} + func TestTracesMultiplexingNonMutating(t *testing.T) { p1 := new(consumertest.TracesSink) p2 := new(consumertest.TracesSink) @@ -57,6 +58,9 @@ func TestTracesMultiplexingNonMutating(t *testing.T) { assert.True(t, td == p3.AllTraces()[1]) assert.EqualValues(t, td, p3.AllTraces()[0]) assert.EqualValues(t, td, p3.AllTraces()[1]) + + // The data should be marked as read only. + assert.True(t, td.IsReadOnly()) } func TestTracesMultiplexingMutating(t *testing.T) { @@ -65,7 +69,7 @@ func TestTracesMultiplexingMutating(t *testing.T) { p3 := &mutatingTracesSink{TracesSink: new(consumertest.TracesSink)} tfc := NewTraces([]consumer.Traces{p1, p2, p3}) - assert.False(t, tfc.Capabilities().MutatesData) + assert.True(t, tfc.Capabilities().MutatesData) td := testdata.GenerateTraces(1) for i := 0; i < 2; i++ { @@ -91,6 +95,47 @@ func TestTracesMultiplexingMutating(t *testing.T) { assert.True(t, td == p3.AllTraces()[1]) assert.EqualValues(t, td, p3.AllTraces()[0]) assert.EqualValues(t, td, p3.AllTraces()[1]) + + // The data should not be marked as read only. + assert.False(t, td.IsReadOnly()) +} + +func TestReadOnlyTracesMultiplexingMutating(t *testing.T) { + p1 := &mutatingTracesSink{TracesSink: new(consumertest.TracesSink)} + p2 := &mutatingTracesSink{TracesSink: new(consumertest.TracesSink)} + p3 := &mutatingTracesSink{TracesSink: new(consumertest.TracesSink)} + + tfc := NewTraces([]consumer.Traces{p1, p2, p3}) + assert.True(t, tfc.Capabilities().MutatesData) + + tdOrig := testdata.GenerateTraces(1) + td := testdata.GenerateTraces(1) + td.MarkReadOnly() + + for i := 0; i < 2; i++ { + err := tfc.ConsumeTraces(context.Background(), td) + if err != nil { + t.Errorf("Wanted nil got error") + return + } + } + + // All consumers should receive the cloned data. + + assert.True(t, td != p1.AllTraces()[0]) + assert.True(t, td != p1.AllTraces()[1]) + assert.EqualValues(t, tdOrig, p1.AllTraces()[0]) + assert.EqualValues(t, tdOrig, p1.AllTraces()[1]) + + assert.True(t, td != p2.AllTraces()[0]) + assert.True(t, td != p2.AllTraces()[1]) + assert.EqualValues(t, tdOrig, p2.AllTraces()[0]) + assert.EqualValues(t, tdOrig, p2.AllTraces()[1]) + + assert.True(t, td != p3.AllTraces()[0]) + assert.True(t, td != p3.AllTraces()[1]) + assert.EqualValues(t, tdOrig, p3.AllTraces()[0]) + assert.EqualValues(t, tdOrig, p3.AllTraces()[1]) } func TestTracesMultiplexingMixLastMutating(t *testing.T) { @@ -126,6 +171,9 @@ func TestTracesMultiplexingMixLastMutating(t *testing.T) { assert.True(t, td != p3.AllTraces()[1]) assert.EqualValues(t, td, p3.AllTraces()[0]) assert.EqualValues(t, td, p3.AllTraces()[1]) + + // The data should not be marked as read only. + assert.False(t, td.IsReadOnly()) } func TestTracesMultiplexingMixLastNonMutating(t *testing.T) { @@ -160,6 +208,9 @@ func TestTracesMultiplexingMixLastNonMutating(t *testing.T) { assert.True(t, td == p3.AllTraces()[1]) assert.EqualValues(t, td, p3.AllTraces()[0]) assert.EqualValues(t, td, p3.AllTraces()[1]) + + // The data should not be marked as read only. + assert.False(t, td.IsReadOnly()) } func TestTracesWhenErrors(t *testing.T) { @@ -187,132 +238,3 @@ type mutatingTracesSink struct { func (mts *mutatingTracesSink) Capabilities() consumer.Capabilities { return consumer.Capabilities{MutatesData: true} } - -func TestTracesRouterMultiplexing(t *testing.T) { - var max = 20 - for numIDs := 1; numIDs < max; numIDs++ { - for numCons := 1; numCons < max; numCons++ { - for numTraces := 1; numTraces < max; numTraces++ { - t.Run( - fmt.Sprintf("%d-ids/%d-cons/%d-logs", numIDs, numCons, numTraces), - fuzzTracesRouter(numIDs, numCons, numTraces), - ) - } - } - } -} - -func fuzzTracesRouter(numIDs, numCons, numTraces int) func(*testing.T) { - return func(t *testing.T) { - allIDs := make([]component.ID, 0, numCons) - allCons := make([]consumer.Traces, 0, numCons) - allConsMap := make(map[component.ID]consumer.Traces) - - // If any consumer is mutating, the router must report mutating - for i := 0; i < numCons; i++ { - allIDs = append(allIDs, component.NewIDWithName("sink", strconv.Itoa(numCons))) - // Random chance for each consumer to be mutating - if (numCons+numTraces+i)%4 == 0 { - allCons = append(allCons, &mutatingTracesSink{TracesSink: new(consumertest.TracesSink)}) - } else { - allCons = append(allCons, new(consumertest.TracesSink)) - } - allConsMap[allIDs[i]] = allCons[i] - } - - r := NewTracesRouter(allConsMap).(connector.TracesRouter) - td := testdata.GenerateTraces(1) - - // Keep track of how many logs each consumer should receive. - // This will be validated after every call to RouteTraces. - expected := make(map[component.ID]int, numCons) - - for i := 0; i < numTraces; i++ { - // Build a random set of ids (no duplicates) - randCons := make(map[component.ID]bool, numIDs) - for j := 0; j < numIDs; j++ { - // This number should be pretty random and less than numCons - conNum := (numCons + numIDs + i + j) % numCons - randCons[allIDs[conNum]] = true - } - - // Convert to slice, update expectations - conIDs := make([]component.ID, 0, len(randCons)) - for id := range randCons { - conIDs = append(conIDs, id) - expected[id]++ - } - - // Route to list of consumers - fanout, err := r.Consumer(conIDs...) - assert.NoError(t, err) - assert.NoError(t, fanout.ConsumeTraces(context.Background(), td)) - - // Validate expectations for all consumers - for id := range expected { - traces := []ptrace.Traces{} - switch con := allConsMap[id].(type) { - case *consumertest.TracesSink: - traces = con.AllTraces() - case *mutatingTracesSink: - traces = con.AllTraces() - } - assert.Len(t, traces, expected[id]) - for n := 0; n < len(traces); n++ { - assert.EqualValues(t, td, traces[n]) - } - } - } - } -} - -func TestTracesRouterGetConsumer(t *testing.T) { - ctx := context.Background() - td := testdata.GenerateTraces(1) - - fooID := component.NewID("foo") - barID := component.NewID("bar") - - foo := new(consumertest.TracesSink) - bar := new(consumertest.TracesSink) - r := NewTracesRouter(map[component.ID]consumer.Traces{fooID: foo, barID: bar}).(connector.TracesRouter) - - rcs := r.PipelineIDs() - assert.Len(t, rcs, 2) - assert.ElementsMatch(t, []component.ID{fooID, barID}, rcs) - - assert.Len(t, foo.AllTraces(), 0) - assert.Len(t, bar.AllTraces(), 0) - - both, err := r.Consumer(fooID, barID) - assert.NotNil(t, both) - assert.NoError(t, err) - - assert.NoError(t, both.ConsumeTraces(ctx, td)) - assert.Len(t, foo.AllTraces(), 1) - assert.Len(t, bar.AllTraces(), 1) - - fooOnly, err := r.Consumer(fooID) - assert.NotNil(t, fooOnly) - assert.NoError(t, err) - - assert.NoError(t, fooOnly.ConsumeTraces(ctx, td)) - assert.Len(t, foo.AllTraces(), 2) - assert.Len(t, bar.AllTraces(), 1) - - barOnly, err := r.Consumer(barID) - assert.NotNil(t, barOnly) - assert.NoError(t, err) - - assert.NoError(t, barOnly.ConsumeTraces(ctx, td)) - assert.Len(t, foo.AllTraces(), 2) - assert.Len(t, bar.AllTraces(), 2) - - none, err := r.Consumer() - assert.Nil(t, none) - assert.Error(t, err) - - fake, err := r.Consumer(component.NewID("fake")) - assert.Nil(t, fake) - assert.Error(t, err) -} diff --git a/internal/iruntime/package_test.go b/internal/iruntime/package_test.go new file mode 100644 index 00000000000..1c0d898aae7 --- /dev/null +++ b/internal/iruntime/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package iruntime + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/internal/iruntime/total_memory_linux.go b/internal/iruntime/total_memory_linux.go index a804cbdbed3..0b53d7a604a 100644 --- a/internal/iruntime/total_memory_linux.go +++ b/internal/iruntime/total_memory_linux.go @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 //go:build linux -// +build linux package iruntime // import "go.opentelemetry.io/collector/internal/iruntime" diff --git a/internal/iruntime/total_memory_linux_test.go b/internal/iruntime/total_memory_linux_test.go index 0a3db2786ec..563f3942207 100644 --- a/internal/iruntime/total_memory_linux_test.go +++ b/internal/iruntime/total_memory_linux_test.go @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 //go:build linux -// +build linux package iruntime diff --git a/internal/iruntime/total_memory_other.go b/internal/iruntime/total_memory_other.go index 00b7116981e..8edb5915d64 100644 --- a/internal/iruntime/total_memory_other.go +++ b/internal/iruntime/total_memory_other.go @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 //go:build !linux -// +build !linux package iruntime // import "go.opentelemetry.io/collector/internal/iruntime" diff --git a/internal/iruntime/total_memory_other_test.go b/internal/iruntime/total_memory_other_test.go index 19d6f997a6c..5b1d9115827 100644 --- a/internal/iruntime/total_memory_other_test.go +++ b/internal/iruntime/total_memory_other_test.go @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 //go:build !linux -// +build !linux package iruntime diff --git a/internal/localhostgate/featuregate.go b/internal/localhostgate/featuregate.go new file mode 100644 index 00000000000..e1b02fca044 --- /dev/null +++ b/internal/localhostgate/featuregate.go @@ -0,0 +1,68 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// package localhostgate defines a feature gate that controls whether server-like receivers and extensions use localhost as the default host for their endpoints. +// This package is duplicated across core and contrib to avoid exposing the feature gate as part of the public API. +// To do this we define a `registerOrLoad` helper and try to register the gate in both modules. +// IMPORTANT NOTE: ANY CHANGES TO THIS PACKAGE MUST BE MIRRORED IN THE CONTRIB COUNTERPART. +package localhostgate // import "go.opentelemetry.io/collector/internal/localhostgate" + +import ( + "errors" + "fmt" + + "go.uber.org/zap" + + "go.opentelemetry.io/collector/featuregate" +) + +const UseLocalHostAsDefaultHostID = "component.UseLocalHostAsDefaultHost" + +// useLocalHostAsDefaultHostfeatureGate is the feature gate that controls whether +// server-like receivers and extensions such as the OTLP receiver use localhost as the default host for their endpoints. +var useLocalHostAsDefaultHostfeatureGate = mustRegisterOrLoad( + featuregate.GlobalRegistry(), + UseLocalHostAsDefaultHostID, + featuregate.StageAlpha, + featuregate.WithRegisterDescription("controls whether server-like receivers and extensions such as the OTLP receiver use localhost as the default host for their endpoints"), +) + +// mustRegisterOrLoad tries to register the feature gate and loads it if it already exists. +// It panics on any other error. +func mustRegisterOrLoad(reg *featuregate.Registry, id string, stage featuregate.Stage, opts ...featuregate.RegisterOption) *featuregate.Gate { + gate, err := reg.Register(id, stage, opts...) + + if errors.Is(err, featuregate.ErrAlreadyRegistered) { + // Gate is already registered; find it. + // Only a handful of feature gates are registered, so it's fine to iterate over all of them. + reg.VisitAll(func(g *featuregate.Gate) { + if g.ID() == id { + gate = g + return + } + }) + } else if err != nil { + panic(err) + } + + return gate +} + +// EndpointForPort gets the endpoint for a given port using localhost or 0.0.0.0 depending on the feature gate. +func EndpointForPort(port int) string { + host := "localhost" + if !useLocalHostAsDefaultHostfeatureGate.IsEnabled() { + host = "0.0.0.0" + } + return fmt.Sprintf("%s:%d", host, port) +} + +// LogAboutUseLocalHostAsDefault logs about the upcoming change from 0.0.0.0 to localhost on server-like components. +func LogAboutUseLocalHostAsDefault(logger *zap.Logger) { + if !useLocalHostAsDefaultHostfeatureGate.IsEnabled() { + logger.Warn( + "The default endpoints for all servers in components will change to use localhost instead of 0.0.0.0 in a future version. Use the feature gate to preview the new default.", + zap.String("feature gate ID", UseLocalHostAsDefaultHostID), + ) + } +} diff --git a/internal/localhostgate/featuregate_test.go b/internal/localhostgate/featuregate_test.go new file mode 100644 index 00000000000..ef09519ac9c --- /dev/null +++ b/internal/localhostgate/featuregate_test.go @@ -0,0 +1,57 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package localhostgate + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/featuregate" +) + +func setFeatureGateForTest(t testing.TB, gate *featuregate.Gate, enabled bool) func() { + originalValue := gate.IsEnabled() + require.NoError(t, featuregate.GlobalRegistry().Set(gate.ID(), enabled)) + return func() { + require.NoError(t, featuregate.GlobalRegistry().Set(gate.ID(), originalValue)) + } +} + +func TestEndpointForPort(t *testing.T) { + tests := []struct { + port int + enabled bool + endpoint string + }{ + { + port: 4317, + enabled: false, + endpoint: "0.0.0.0:4317", + }, + { + port: 4317, + enabled: true, + endpoint: "localhost:4317", + }, + { + port: 0, + enabled: false, + endpoint: "0.0.0.0:0", + }, + { + port: 0, + enabled: true, + endpoint: "localhost:0", + }, + } + + for _, tt := range tests { + t.Run(tt.endpoint, func(t *testing.T) { + defer setFeatureGateForTest(t, useLocalHostAsDefaultHostfeatureGate, tt.enabled)() + assert.Equal(t, EndpointForPort(tt.port), tt.endpoint) + }) + } +} diff --git a/internal/memorylimiter/config.go b/internal/memorylimiter/config.go new file mode 100644 index 00000000000..bb20ad6565a --- /dev/null +++ b/internal/memorylimiter/config.go @@ -0,0 +1,66 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package memorylimiter // import "go.opentelemetry.io/collector/internal/memorylimiter" + +import ( + "errors" + "time" + + "go.opentelemetry.io/collector/component" +) + +var ( + errCheckIntervalOutOfRange = errors.New("'check_interval' must be greater than zero") + errLimitOutOfRange = errors.New("'limit_mib' or 'limit_percentage' must be greater than zero") + errSpikeLimitOutOfRange = errors.New("'spike_limit_mib' must be smaller than 'limit_mib'") + errSpikeLimitPercentageOutOfRange = errors.New("'spike_limit_percentage' must be smaller than 'limit_percentage'") + errLimitPercentageOutOfRange = errors.New( + "'limit_percentage' and 'spike_limit_percentage' must be greater than zero and less than or equal to hundred") +) + +// Config defines configuration for memory memoryLimiter processor. +type Config struct { + // CheckInterval is the time between measurements of memory usage for the + // purposes of avoiding going over the limits. Defaults to zero, so no + // checks will be performed. + CheckInterval time.Duration `mapstructure:"check_interval"` + + // MemoryLimitMiB is the maximum amount of memory, in MiB, targeted to be + // allocated by the process. + MemoryLimitMiB uint32 `mapstructure:"limit_mib"` + + // MemorySpikeLimitMiB is the maximum, in MiB, spike expected between the + // measurements of memory usage. + MemorySpikeLimitMiB uint32 `mapstructure:"spike_limit_mib"` + + // MemoryLimitPercentage is the maximum amount of memory, in %, targeted to be + // allocated by the process. The fixed memory settings MemoryLimitMiB has a higher precedence. + MemoryLimitPercentage uint32 `mapstructure:"limit_percentage"` + + // MemorySpikePercentage is the maximum, in percents against the total memory, + // spike expected between the measurements of memory usage. + MemorySpikePercentage uint32 `mapstructure:"spike_limit_percentage"` +} + +var _ component.Config = (*Config)(nil) + +// Validate checks if the processor configuration is valid +func (cfg *Config) Validate() error { + if cfg.CheckInterval <= 0 { + return errCheckIntervalOutOfRange + } + if cfg.MemoryLimitMiB == 0 && cfg.MemoryLimitPercentage == 0 { + return errLimitOutOfRange + } + if cfg.MemoryLimitPercentage > 100 || cfg.MemorySpikePercentage > 100 { + return errLimitPercentageOutOfRange + } + if cfg.MemoryLimitMiB > 0 && cfg.MemoryLimitMiB <= cfg.MemorySpikeLimitMiB { + return errSpikeLimitOutOfRange + } + if cfg.MemoryLimitPercentage > 0 && cfg.MemoryLimitPercentage <= cfg.MemorySpikePercentage { + return errSpikeLimitPercentageOutOfRange + } + return nil +} diff --git a/internal/memorylimiter/config_test.go b/internal/memorylimiter/config_test.go new file mode 100644 index 00000000000..ca7a243f861 --- /dev/null +++ b/internal/memorylimiter/config_test.go @@ -0,0 +1,95 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package memorylimiter + +import ( + "path/filepath" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestUnmarshalConfig(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + cfg := &Config{} + assert.NoError(t, component.UnmarshalConfig(cm, cfg)) + assert.Equal(t, + &Config{ + CheckInterval: 5 * time.Second, + MemoryLimitMiB: 4000, + MemorySpikeLimitMiB: 500, + }, cfg) +} + +func TestConfigValidate(t *testing.T) { + tests := []struct { + name string + cfg *Config + err error + }{ + { + name: "valid", + cfg: &Config{ + MemoryLimitMiB: 5722, + MemorySpikeLimitMiB: 1907, + CheckInterval: 100 * time.Millisecond, + }, + err: nil, + }, + { + name: "zero check interval", + cfg: &Config{ + CheckInterval: 0, + }, + err: errCheckIntervalOutOfRange, + }, + { + name: "unset memory limit", + cfg: &Config{ + CheckInterval: 1 * time.Second, + MemoryLimitMiB: 0, + MemoryLimitPercentage: 0, + }, + err: errLimitOutOfRange, + }, + { + name: "invalid memory spike limit", + cfg: &Config{ + CheckInterval: 1 * time.Second, + MemoryLimitMiB: 10, + MemorySpikeLimitMiB: 10, + }, + err: errSpikeLimitOutOfRange, + }, + { + name: "invalid memory percentage limit", + cfg: &Config{ + CheckInterval: 1 * time.Second, + MemoryLimitPercentage: 101, + }, + err: errLimitPercentageOutOfRange, + }, + { + name: "invalid memory spike percentage limit", + cfg: &Config{ + CheckInterval: 1 * time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 60, + }, + err: errSpikeLimitPercentageOutOfRange, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.cfg.Validate() + assert.Equal(t, tt.err, err) + }) + } +} diff --git a/internal/memorylimiter/memorylimiter.go b/internal/memorylimiter/memorylimiter.go new file mode 100644 index 00000000000..a010cba5427 --- /dev/null +++ b/internal/memorylimiter/memorylimiter.go @@ -0,0 +1,262 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package memorylimiter // import "go.opentelemetry.io/collector/internal/memorylimiter" + +import ( + "context" + "errors" + "fmt" + "runtime" + "sync" + "sync/atomic" + "time" + + "go.uber.org/zap" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/internal/iruntime" +) + +const ( + mibBytes = 1024 * 1024 + + // Minimum interval between forced GC when in soft limited mode. We don't want to + // do GCs too frequently since it is a CPU-heavy operation. + minGCIntervalWhenSoftLimited = 10 * time.Second +) + +var ( + // ErrDataRefused will be returned to callers of ConsumeTraceData to indicate + // that data is being refused due to high memory usage. + ErrDataRefused = errors.New("data refused due to high memory usage") + + // ErrShutdownNotStarted indicates no memorylimiter has not start when shutdown + ErrShutdownNotStarted = errors.New("no existing monitoring routine is running") + + // GetMemoryFn and ReadMemStatsFn make it overridable by tests + GetMemoryFn = iruntime.TotalMemory + ReadMemStatsFn = runtime.ReadMemStats +) + +// MemoryLimiter is used to prevent out of memory situations on the collector. +type MemoryLimiter struct { + usageChecker memUsageChecker + + memCheckWait time.Duration + ballastSize uint64 + + // mustRefuse is used to indicate when data should be refused. + mustRefuse *atomic.Bool + + ticker *time.Ticker + + lastGCDone time.Time + + // The function to read the mem values is set as a reference to help with + // testing different values. + readMemStatsFn func(m *runtime.MemStats) + + // Fields used for logging. + logger *zap.Logger + configMismatchedLogged bool + + refCounterLock sync.Mutex + refCounter int + waitGroup sync.WaitGroup + closed chan struct{} +} + +// NewMemoryLimiter returns a new memory limiter component +func NewMemoryLimiter(cfg *Config, logger *zap.Logger) (*MemoryLimiter, error) { + usageChecker, err := getMemUsageChecker(cfg, logger) + if err != nil { + return nil, err + } + + logger.Info("Memory limiter configured", + zap.Uint64("limit_mib", usageChecker.memAllocLimit/mibBytes), + zap.Uint64("spike_limit_mib", usageChecker.memSpikeLimit/mibBytes), + zap.Duration("check_interval", cfg.CheckInterval)) + + return &MemoryLimiter{ + usageChecker: *usageChecker, + memCheckWait: cfg.CheckInterval, + ticker: time.NewTicker(cfg.CheckInterval), + readMemStatsFn: ReadMemStatsFn, + logger: logger, + mustRefuse: &atomic.Bool{}, + }, nil +} + +// startMonitoring starts a single ticker'd goroutine per instance +// that will check memory usage every checkInterval period. +func (ml *MemoryLimiter) startMonitoring() { + ml.refCounterLock.Lock() + defer ml.refCounterLock.Unlock() + + ml.refCounter++ + if ml.refCounter == 1 { + ml.closed = make(chan struct{}) + ml.waitGroup.Add(1) + go func() { + defer ml.waitGroup.Done() + + for { + select { + case <-ml.ticker.C: + case <-ml.closed: + return + } + ml.CheckMemLimits() + } + }() + } +} + +func (ml *MemoryLimiter) Start(_ context.Context, host component.Host) error { + extensions := host.GetExtensions() + for _, extension := range extensions { + if ext, ok := extension.(interface{ GetBallastSize() uint64 }); ok { + ml.ballastSize = ext.GetBallastSize() + break + } + } + ml.startMonitoring() + return nil +} + +// Shutdown resets MemoryLimiter monitoring ticker and stop monitoring +func (ml *MemoryLimiter) Shutdown(context.Context) error { + ml.refCounterLock.Lock() + defer ml.refCounterLock.Unlock() + + if ml.refCounter == 0 { + return ErrShutdownNotStarted + } else if ml.refCounter == 1 { + ml.ticker.Stop() + close(ml.closed) + ml.waitGroup.Wait() + } + ml.refCounter-- + return nil +} + +// MustRefuse returns if the caller should deny because memory has reached it's configured limits +func (ml *MemoryLimiter) MustRefuse() bool { + return ml.mustRefuse.Load() +} + +func getMemUsageChecker(cfg *Config, logger *zap.Logger) (*memUsageChecker, error) { + memAllocLimit := uint64(cfg.MemoryLimitMiB) * mibBytes + memSpikeLimit := uint64(cfg.MemorySpikeLimitMiB) * mibBytes + if cfg.MemoryLimitMiB != 0 { + return newFixedMemUsageChecker(memAllocLimit, memSpikeLimit), nil + } + totalMemory, err := GetMemoryFn() + if err != nil { + return nil, fmt.Errorf("failed to get total memory, use fixed memory settings (limit_mib): %w", err) + } + logger.Info("Using percentage memory limiter", + zap.Uint64("total_memory_mib", totalMemory/mibBytes), + zap.Uint32("limit_percentage", cfg.MemoryLimitPercentage), + zap.Uint32("spike_limit_percentage", cfg.MemorySpikePercentage)) + return newPercentageMemUsageChecker(totalMemory, uint64(cfg.MemoryLimitPercentage), + uint64(cfg.MemorySpikePercentage)), nil +} + +func (ml *MemoryLimiter) readMemStats() *runtime.MemStats { + ms := &runtime.MemStats{} + ml.readMemStatsFn(ms) + // If proper configured ms.Alloc should be at least ml.ballastSize but since + // a misconfiguration is possible check for that here. + if ms.Alloc >= ml.ballastSize { + ms.Alloc -= ml.ballastSize + } else if !ml.configMismatchedLogged { + // This indicates misconfiguration. Log it once. + ml.configMismatchedLogged = true + ml.logger.Warn(`"size_mib" in ballast extension is likely incorrectly configured.`) + } + + return ms +} + +func memstatToZapField(ms *runtime.MemStats) zap.Field { + return zap.Uint64("cur_mem_mib", ms.Alloc/mibBytes) +} + +func (ml *MemoryLimiter) doGCandReadMemStats() *runtime.MemStats { + runtime.GC() + ml.lastGCDone = time.Now() + ms := ml.readMemStats() + ml.logger.Info("Memory usage after GC.", memstatToZapField(ms)) + return ms +} + +// CheckMemLimits inspects current memory usage against threshold and toggle mustRefuse when threshold is exceeded +func (ml *MemoryLimiter) CheckMemLimits() { + ms := ml.readMemStats() + + ml.logger.Debug("Currently used memory.", memstatToZapField(ms)) + + if ml.usageChecker.aboveHardLimit(ms) { + ml.logger.Warn("Memory usage is above hard limit. Forcing a GC.", memstatToZapField(ms)) + ms = ml.doGCandReadMemStats() + } + + // Remember current state. + wasRefusing := ml.mustRefuse.Load() + + // Check if the memory usage is above the soft limit. + mustRefuse := ml.usageChecker.aboveSoftLimit(ms) + + if wasRefusing && !mustRefuse { + // Was previously refusing but enough memory is available now, no need to limit. + ml.logger.Info("Memory usage back within limits. Resuming normal operation.", memstatToZapField(ms)) + } + + if !wasRefusing && mustRefuse { + // We are above soft limit, do a GC if it wasn't done recently and see if + // it brings memory usage below the soft limit. + if time.Since(ml.lastGCDone) > minGCIntervalWhenSoftLimited { + ml.logger.Info("Memory usage is above soft limit. Forcing a GC.", memstatToZapField(ms)) + ms = ml.doGCandReadMemStats() + // Check the limit again to see if GC helped. + mustRefuse = ml.usageChecker.aboveSoftLimit(ms) + } + + if mustRefuse { + ml.logger.Warn("Memory usage is above soft limit. Refusing data.", memstatToZapField(ms)) + } + } + + ml.mustRefuse.Store(mustRefuse) +} + +type memUsageChecker struct { + memAllocLimit uint64 + memSpikeLimit uint64 +} + +func (d memUsageChecker) aboveSoftLimit(ms *runtime.MemStats) bool { + return ms.Alloc >= d.memAllocLimit-d.memSpikeLimit +} + +func (d memUsageChecker) aboveHardLimit(ms *runtime.MemStats) bool { + return ms.Alloc >= d.memAllocLimit +} + +func newFixedMemUsageChecker(memAllocLimit, memSpikeLimit uint64) *memUsageChecker { + if memSpikeLimit == 0 { + // If spike limit is unspecified use 20% of mem limit. + memSpikeLimit = memAllocLimit / 5 + } + return &memUsageChecker{ + memAllocLimit: memAllocLimit, + memSpikeLimit: memSpikeLimit, + } +} + +func newPercentageMemUsageChecker(totalMemory uint64, percentageLimit, percentageSpike uint64) *memUsageChecker { + return newFixedMemUsageChecker(percentageLimit*totalMemory/100, percentageSpike*totalMemory/100) +} diff --git a/internal/memorylimiter/memorylimiter_test.go b/internal/memorylimiter/memorylimiter_test.go new file mode 100644 index 00000000000..e9e92a33f70 --- /dev/null +++ b/internal/memorylimiter/memorylimiter_test.go @@ -0,0 +1,188 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package memorylimiter + +import ( + "context" + "runtime" + "sync/atomic" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/internal/iruntime" +) + +// TestMemoryPressureResponse manipulates results from querying memory and +// check expected side effects. +func TestMemoryPressureResponse(t *testing.T) { + var currentMemAlloc uint64 + ml := &MemoryLimiter{ + usageChecker: memUsageChecker{ + memAllocLimit: 1024, + }, + mustRefuse: &atomic.Bool{}, + readMemStatsFn: func(ms *runtime.MemStats) { + ms.Alloc = currentMemAlloc + }, + logger: zap.NewNop(), + } + + // Below memAllocLimit. + currentMemAlloc = 800 + ml.CheckMemLimits() + assert.False(t, ml.MustRefuse()) + + // Above memAllocLimit. + currentMemAlloc = 1800 + ml.CheckMemLimits() + assert.True(t, ml.MustRefuse()) + + // Check ballast effect + ml.ballastSize = 1000 + + // Below memAllocLimit accounting for ballast. + currentMemAlloc = 800 + ml.ballastSize + ml.CheckMemLimits() + assert.False(t, ml.MustRefuse()) + + // Above memAllocLimit even accounting for ballast. + currentMemAlloc = 1800 + ml.ballastSize + ml.CheckMemLimits() + assert.True(t, ml.MustRefuse()) + + // Restore ballast to default. + ml.ballastSize = 0 + + // Check spike limit + ml.usageChecker.memSpikeLimit = 512 + + // Below memSpikeLimit. + currentMemAlloc = 500 + ml.CheckMemLimits() + assert.False(t, ml.MustRefuse()) + + // Above memSpikeLimit. + currentMemAlloc = 550 + ml.CheckMemLimits() + assert.True(t, ml.MustRefuse()) +} + +func TestGetDecision(t *testing.T) { + t.Run("fixed_limit", func(t *testing.T) { + d, err := getMemUsageChecker(&Config{MemoryLimitMiB: 100, MemorySpikeLimitMiB: 20}, zap.NewNop()) + require.NoError(t, err) + assert.Equal(t, &memUsageChecker{ + memAllocLimit: 100 * mibBytes, + memSpikeLimit: 20 * mibBytes, + }, d) + }) + + t.Cleanup(func() { + GetMemoryFn = iruntime.TotalMemory + }) + GetMemoryFn = func() (uint64, error) { + return 100 * mibBytes, nil + } + t.Run("percentage_limit", func(t *testing.T) { + d, err := getMemUsageChecker(&Config{MemoryLimitPercentage: 50, MemorySpikePercentage: 10}, zap.NewNop()) + require.NoError(t, err) + assert.Equal(t, &memUsageChecker{ + memAllocLimit: 50 * mibBytes, + memSpikeLimit: 10 * mibBytes, + }, d) + }) +} + +func TestRefuseDecision(t *testing.T) { + decison1000Limit30Spike30 := newPercentageMemUsageChecker(1000, 60, 30) + decison1000Limit60Spike50 := newPercentageMemUsageChecker(1000, 60, 50) + decison1000Limit40Spike20 := newPercentageMemUsageChecker(1000, 40, 20) + + tests := []struct { + name string + usageChecker memUsageChecker + ms *runtime.MemStats + shouldRefuse bool + }{ + { + name: "should refuse over limit", + usageChecker: *decison1000Limit30Spike30, + ms: &runtime.MemStats{Alloc: 600}, + shouldRefuse: true, + }, + { + name: "should not refuse", + usageChecker: *decison1000Limit30Spike30, + ms: &runtime.MemStats{Alloc: 100}, + shouldRefuse: false, + }, + { + name: "should not refuse spike, fixed usageChecker", + usageChecker: memUsageChecker{ + memAllocLimit: 600, + memSpikeLimit: 500, + }, + ms: &runtime.MemStats{Alloc: 300}, + shouldRefuse: true, + }, + { + name: "should refuse, spike, percentage usageChecker", + usageChecker: *decison1000Limit60Spike50, + ms: &runtime.MemStats{Alloc: 300}, + shouldRefuse: true, + }, + { + name: "should refuse, spike, percentage usageChecker", + usageChecker: *decison1000Limit40Spike20, + ms: &runtime.MemStats{Alloc: 250}, + shouldRefuse: true, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + shouldRefuse := test.usageChecker.aboveSoftLimit(test.ms) + assert.Equal(t, test.shouldRefuse, shouldRefuse) + }) + } +} + +func TestBallastSize(t *testing.T) { + cfg := &Config{ + CheckInterval: 10 * time.Second, + MemoryLimitMiB: 1024, + } + got, err := NewMemoryLimiter(cfg, zap.NewNop()) + require.NoError(t, err) + + got.startMonitoring() + require.NoError(t, got.Start(context.Background(), &host{ballastSize: 113})) + assert.Equal(t, uint64(113), got.ballastSize) + require.NoError(t, got.Shutdown(context.Background())) +} + +type host struct { + ballastSize uint64 + component.Host +} + +func (h *host) GetExtensions() map[component.ID]component.Component { + ret := make(map[component.ID]component.Component) + ret[component.MustNewID("ballast")] = &ballastExtension{ballastSize: h.ballastSize} + return ret +} + +type ballastExtension struct { + ballastSize uint64 + component.StartFunc + component.ShutdownFunc +} + +func (be *ballastExtension) GetBallastSize() uint64 { + return be.ballastSize +} diff --git a/processor/memorylimiterprocessor/testdata/config.yaml b/internal/memorylimiter/testdata/config.yaml similarity index 100% rename from processor/memorylimiterprocessor/testdata/config.yaml rename to internal/memorylimiter/testdata/config.yaml diff --git a/internal/obsreportconfig/obsmetrics/obs_exporter.go b/internal/obsreportconfig/obsmetrics/obs_exporter.go index 9ecebf2d9b4..50a2724070c 100644 --- a/internal/obsreportconfig/obsmetrics/obs_exporter.go +++ b/internal/obsreportconfig/obsmetrics/obs_exporter.go @@ -3,11 +3,6 @@ package obsmetrics // import "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" -import ( - "go.opencensus.io/stats" - "go.opencensus.io/tag" -) - const ( // ExporterKey used to identify exporters in metrics and traces. ExporterKey = "exporter" @@ -16,53 +11,27 @@ const ( SentSpansKey = "sent_spans" // FailedToSendSpansKey used to track spans that failed to be sent by exporters. FailedToSendSpansKey = "send_failed_spans" + // FailedToEnqueueSpansKey used to track spans that failed to be enqueued by exporters. + FailedToEnqueueSpansKey = "enqueue_failed_spans" // SentMetricPointsKey used to track metric points sent by exporters. SentMetricPointsKey = "sent_metric_points" // FailedToSendMetricPointsKey used to track metric points that failed to be sent by exporters. FailedToSendMetricPointsKey = "send_failed_metric_points" + // FailedToEnqueueMetricPointsKey used to track metric points that failed to be enqueued by exporters. + FailedToEnqueueMetricPointsKey = "enqueue_failed_metric_points" // SentLogRecordsKey used to track logs sent by exporters. SentLogRecordsKey = "sent_log_records" // FailedToSendLogRecordsKey used to track logs that failed to be sent by exporters. FailedToSendLogRecordsKey = "send_failed_log_records" + // FailedToEnqueueLogRecordsKey used to track logs that failed to be enqueued by exporters. + FailedToEnqueueLogRecordsKey = "enqueue_failed_log_records" ) var ( - TagKeyExporter, _ = tag.NewKey(ExporterKey) - ExporterPrefix = ExporterKey + NameSep ExportTraceDataOperationSuffix = NameSep + "traces" ExportMetricsOperationSuffix = NameSep + "metrics" ExportLogsOperationSuffix = NameSep + "logs" - - // Exporter metrics. Any count of data items below is in the final format - // that they were sent, reasoning: reconciliation is easier if measurements - // on backend and exporter are expected to be the same. Translation issues - // that result in a different number of elements should be reported in a - // separate way. - ExporterSentSpans = stats.Int64( - ExporterPrefix+SentSpansKey, - "Number of spans successfully sent to destination.", - stats.UnitDimensionless) - ExporterFailedToSendSpans = stats.Int64( - ExporterPrefix+FailedToSendSpansKey, - "Number of spans in failed attempts to send to destination.", - stats.UnitDimensionless) - ExporterSentMetricPoints = stats.Int64( - ExporterPrefix+SentMetricPointsKey, - "Number of metric points successfully sent to destination.", - stats.UnitDimensionless) - ExporterFailedToSendMetricPoints = stats.Int64( - ExporterPrefix+FailedToSendMetricPointsKey, - "Number of metric points in failed attempts to send to destination.", - stats.UnitDimensionless) - ExporterSentLogRecords = stats.Int64( - ExporterPrefix+SentLogRecordsKey, - "Number of log record successfully sent to destination.", - stats.UnitDimensionless) - ExporterFailedToSendLogRecords = stats.Int64( - ExporterPrefix+FailedToSendLogRecordsKey, - "Number of log records in failed attempts to send to destination.", - stats.UnitDimensionless) ) diff --git a/internal/obsreportconfig/obsmetrics/obs_processor.go b/internal/obsreportconfig/obsmetrics/obs_processor.go index 40c8d698cb1..75084014ec5 100644 --- a/internal/obsreportconfig/obsmetrics/obs_processor.go +++ b/internal/obsreportconfig/obsmetrics/obs_processor.go @@ -3,11 +3,6 @@ package obsmetrics // import "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" -import ( - "go.opencensus.io/stats" - "go.opencensus.io/tag" -) - const ( // ProcessorKey is the key used to identify processors in metrics and traces. ProcessorKey = "processor" @@ -23,46 +18,5 @@ const ( ) var ( - TagKeyProcessor, _ = tag.NewKey(ProcessorKey) - ProcessorPrefix = ProcessorKey + NameSep - - // Processor metrics. Any count of data items below is in the internal format - // of the collector since processors only deal with internal format. - ProcessorAcceptedSpans = stats.Int64( - ProcessorPrefix+AcceptedSpansKey, - "Number of spans successfully pushed into the next component in the pipeline.", - stats.UnitDimensionless) - ProcessorRefusedSpans = stats.Int64( - ProcessorPrefix+RefusedSpansKey, - "Number of spans that were rejected by the next component in the pipeline.", - stats.UnitDimensionless) - ProcessorDroppedSpans = stats.Int64( - ProcessorPrefix+DroppedSpansKey, - "Number of spans that were dropped.", - stats.UnitDimensionless) - ProcessorAcceptedMetricPoints = stats.Int64( - ProcessorPrefix+AcceptedMetricPointsKey, - "Number of metric points successfully pushed into the next component in the pipeline.", - stats.UnitDimensionless) - ProcessorRefusedMetricPoints = stats.Int64( - ProcessorPrefix+RefusedMetricPointsKey, - "Number of metric points that were rejected by the next component in the pipeline.", - stats.UnitDimensionless) - ProcessorDroppedMetricPoints = stats.Int64( - ProcessorPrefix+DroppedMetricPointsKey, - "Number of metric points that were dropped.", - stats.UnitDimensionless) - ProcessorAcceptedLogRecords = stats.Int64( - ProcessorPrefix+AcceptedLogRecordsKey, - "Number of log records successfully pushed into the next component in the pipeline.", - stats.UnitDimensionless) - ProcessorRefusedLogRecords = stats.Int64( - ProcessorPrefix+RefusedLogRecordsKey, - "Number of log records that were rejected by the next component in the pipeline.", - stats.UnitDimensionless) - ProcessorDroppedLogRecords = stats.Int64( - ProcessorPrefix+DroppedLogRecordsKey, - "Number of log records that were dropped.", - stats.UnitDimensionless) ) diff --git a/internal/obsreportconfig/obsmetrics/obs_receiver.go b/internal/obsreportconfig/obsmetrics/obs_receiver.go index 0f380b4aa3f..d70148c1ff9 100644 --- a/internal/obsreportconfig/obsmetrics/obs_receiver.go +++ b/internal/obsreportconfig/obsmetrics/obs_receiver.go @@ -3,11 +3,6 @@ package obsmetrics // import "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" -import ( - "go.opencensus.io/stats" - "go.opencensus.io/tag" -) - const ( // ReceiverKey used to identify receivers in metrics and traces. ReceiverKey = "receiver" @@ -35,41 +30,8 @@ const ( ) var ( - TagKeyReceiver, _ = tag.NewKey(ReceiverKey) - TagKeyTransport, _ = tag.NewKey(TransportKey) - ReceiverPrefix = ReceiverKey + NameSep ReceiveTraceDataOperationSuffix = NameSep + "TraceDataReceived" ReceiverMetricsOperationSuffix = NameSep + "MetricsReceived" ReceiverLogsOperationSuffix = NameSep + "LogsReceived" - - // Receiver metrics. Any count of data items below is in the original format - // that they were received, reasoning: reconciliation is easier if measurement - // on clients and receiver are expected to be the same. Translation issues - // that result in a different number of elements should be reported in a - // separate way. - ReceiverAcceptedSpans = stats.Int64( - ReceiverPrefix+AcceptedSpansKey, - "Number of spans successfully pushed into the pipeline.", - stats.UnitDimensionless) - ReceiverRefusedSpans = stats.Int64( - ReceiverPrefix+RefusedSpansKey, - "Number of spans that could not be pushed into the pipeline.", - stats.UnitDimensionless) - ReceiverAcceptedMetricPoints = stats.Int64( - ReceiverPrefix+AcceptedMetricPointsKey, - "Number of metric points successfully pushed into the pipeline.", - stats.UnitDimensionless) - ReceiverRefusedMetricPoints = stats.Int64( - ReceiverPrefix+RefusedMetricPointsKey, - "Number of metric points that could not be pushed into the pipeline.", - stats.UnitDimensionless) - ReceiverAcceptedLogRecords = stats.Int64( - ReceiverPrefix+AcceptedLogRecordsKey, - "Number of log records successfully pushed into the pipeline.", - stats.UnitDimensionless) - ReceiverRefusedLogRecords = stats.Int64( - ReceiverPrefix+RefusedLogRecordsKey, - "Number of log records that could not be pushed into the pipeline.", - stats.UnitDimensionless) ) diff --git a/internal/obsreportconfig/obsmetrics/obs_scraper.go b/internal/obsreportconfig/obsmetrics/obs_scraper.go index 2beaebec78e..7e2b73d127f 100644 --- a/internal/obsreportconfig/obsmetrics/obs_scraper.go +++ b/internal/obsreportconfig/obsmetrics/obs_scraper.go @@ -3,11 +3,6 @@ package obsmetrics // import "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" -import ( - "go.opencensus.io/stats" - "go.opencensus.io/tag" -) - const ( // ScraperKey used to identify scrapers in metrics and traces. ScraperKey = "scraper" @@ -24,16 +19,3 @@ const ( ScraperPrefix = ScraperKey + NameSep ScraperMetricsOperationSuffix = NameSep + "MetricsScraped" ) - -var ( - TagKeyScraper, _ = tag.NewKey(ScraperKey) - - ScraperScrapedMetricPoints = stats.Int64( - ScraperPrefix+ScrapedMetricPointsKey, - "Number of metric points successfully scraped.", - stats.UnitDimensionless) - ScraperErroredMetricPoints = stats.Int64( - ScraperPrefix+ErroredMetricPointsKey, - "Number of metric points that were unable to be scraped.", - stats.UnitDimensionless) -) diff --git a/internal/obsreportconfig/obsreportconfig.go b/internal/obsreportconfig/obsreportconfig.go index 9b3bd1b8abf..aed6813460c 100644 --- a/internal/obsreportconfig/obsreportconfig.go +++ b/internal/obsreportconfig/obsreportconfig.go @@ -4,21 +4,16 @@ package obsreportconfig // import "go.opentelemetry.io/collector/internal/obsreportconfig" import ( - "go.opencensus.io/stats" - "go.opencensus.io/stats/view" - "go.opencensus.io/tag" - - "go.opentelemetry.io/collector/config/configtelemetry" "go.opentelemetry.io/collector/featuregate" - "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" ) // UseOtelForInternalMetricsfeatureGate is the feature gate that controls whether the collector uses open // telemetrySettings for internal metrics. var UseOtelForInternalMetricsfeatureGate = featuregate.GlobalRegistry().MustRegister( "telemetry.useOtelForInternalMetrics", - featuregate.StageAlpha, - featuregate.WithRegisterDescription("controls whether the collector uses OpenTelemetry for internal metrics")) + featuregate.StageStable, + featuregate.WithRegisterDescription("controls whether the collector uses OpenTelemetry for internal metrics"), + featuregate.WithRegisterToVersion("0.95.0")) // 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. @@ -35,109 +30,3 @@ var UseOtelWithSDKConfigurationForInternalTelemetryFeatureGate = featuregate.Glo featuregate.StageAlpha, featuregate.WithRegisterDescription("controls whether the collector supports extended OpenTelemetry"+ "configuration for internal telemetry")) - -// AllViews returns all the OpenCensus views requires by obsreport package. -func AllViews(level configtelemetry.Level) []*view.View { - if level == configtelemetry.LevelNone { - return nil - } - - var views []*view.View - var measures []*stats.Int64Measure - var tagKeys []tag.Key - - // Receiver views. - views = append(views, receiverViews()...) - - // Scraper views. - views = append(views, scraperViews()...) - - // Exporter views. - measures = []*stats.Int64Measure{ - obsmetrics.ExporterSentSpans, - obsmetrics.ExporterFailedToSendSpans, - obsmetrics.ExporterSentMetricPoints, - obsmetrics.ExporterFailedToSendMetricPoints, - obsmetrics.ExporterSentLogRecords, - obsmetrics.ExporterFailedToSendLogRecords, - } - tagKeys = []tag.Key{obsmetrics.TagKeyExporter} - views = append(views, genViews(measures, tagKeys, view.Sum())...) - - errorNumberView := &view.View{ - Name: obsmetrics.ExporterPrefix + "send_failed_requests", - Description: "number of times exporters failed to send requests to the destination", - Measure: obsmetrics.ExporterFailedToSendSpans, - Aggregation: view.Count(), - } - views = append(views, errorNumberView) - - // Processor views. - measures = []*stats.Int64Measure{ - obsmetrics.ProcessorAcceptedSpans, - obsmetrics.ProcessorRefusedSpans, - obsmetrics.ProcessorDroppedSpans, - obsmetrics.ProcessorAcceptedMetricPoints, - obsmetrics.ProcessorRefusedMetricPoints, - obsmetrics.ProcessorDroppedMetricPoints, - obsmetrics.ProcessorAcceptedLogRecords, - obsmetrics.ProcessorRefusedLogRecords, - obsmetrics.ProcessorDroppedLogRecords, - } - tagKeys = []tag.Key{obsmetrics.TagKeyProcessor} - views = append(views, genViews(measures, tagKeys, view.Sum())...) - - return views -} - -func receiverViews() []*view.View { - if UseOtelForInternalMetricsfeatureGate.IsEnabled() { - return nil - } - - measures := []*stats.Int64Measure{ - obsmetrics.ReceiverAcceptedSpans, - obsmetrics.ReceiverRefusedSpans, - obsmetrics.ReceiverAcceptedMetricPoints, - obsmetrics.ReceiverRefusedMetricPoints, - obsmetrics.ReceiverAcceptedLogRecords, - obsmetrics.ReceiverRefusedLogRecords, - } - tagKeys := []tag.Key{ - obsmetrics.TagKeyReceiver, obsmetrics.TagKeyTransport, - } - - return genViews(measures, tagKeys, view.Sum()) -} - -func scraperViews() []*view.View { - if UseOtelForInternalMetricsfeatureGate.IsEnabled() { - return nil - } - - measures := []*stats.Int64Measure{ - obsmetrics.ScraperScrapedMetricPoints, - obsmetrics.ScraperErroredMetricPoints, - } - tagKeys := []tag.Key{obsmetrics.TagKeyReceiver, obsmetrics.TagKeyScraper} - - return genViews(measures, tagKeys, view.Sum()) -} - -func genViews( - measures []*stats.Int64Measure, - tagKeys []tag.Key, - aggregation *view.Aggregation, -) []*view.View { - views := make([]*view.View, 0, len(measures)) - for _, measure := range measures { - views = append(views, &view.View{ - Name: measure.Name(), - Description: measure.Description(), - TagKeys: tagKeys, - Measure: measure, - Aggregation: aggregation, - }) - } - return views -} diff --git a/internal/obsreportconfig/obsreportconfig_test.go b/internal/obsreportconfig/obsreportconfig_test.go deleted file mode 100644 index 3634a437245..00000000000 --- a/internal/obsreportconfig/obsreportconfig_test.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package obsreportconfig - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "go.opentelemetry.io/collector/config/configtelemetry" -) - -func TestConfigure(t *testing.T) { - tests := []struct { - name string - level configtelemetry.Level - wantViewsLen int - }{ - { - name: "none", - level: configtelemetry.LevelNone, - }, - { - name: "basic", - level: configtelemetry.LevelBasic, - wantViewsLen: 24, - }, - { - name: "normal", - level: configtelemetry.LevelNormal, - wantViewsLen: 24, - }, - { - name: "detailed", - level: configtelemetry.LevelDetailed, - wantViewsLen: 24, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Len(t, AllViews(tt.level), tt.wantViewsLen) - }) - } -} diff --git a/internal/obsreportconfig/package_test.go b/internal/obsreportconfig/package_test.go new file mode 100644 index 00000000000..d70955f9088 --- /dev/null +++ b/internal/obsreportconfig/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package obsreportconfig + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/internal/sharedcomponent/package_test.go b/internal/sharedcomponent/package_test.go new file mode 100644 index 00000000000..424f48bf6d6 --- /dev/null +++ b/internal/sharedcomponent/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package sharedcomponent + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/internal/sharedcomponent/sharedcomponent.go b/internal/sharedcomponent/sharedcomponent.go index 2d1c74f355e..1a3e65878c2 100644 --- a/internal/sharedcomponent/sharedcomponent.go +++ b/internal/sharedcomponent/sharedcomponent.go @@ -1,8 +1,9 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -// Package sharedcomponent exposes util functionality for receivers and exporters -// that need to share state between different signal types instances such as net.Listener or os.File. +// Package sharedcomponent exposes functionality for components +// to register against a shared key, such as a configuration object, in order to be reused across signal types. +// This is particularly useful when the component relies on a shared resource such as os.File or http.Server. package sharedcomponent // import "go.opentelemetry.io/collector/internal/sharedcomponent" import ( @@ -12,69 +13,108 @@ import ( "go.opentelemetry.io/collector/component" ) -// SharedComponents a map that keeps reference of all created instances for a given configuration, -// and ensures that the shared state is started and stopped only once. -type SharedComponents[K comparable, V component.Component] struct { - comps map[K]*SharedComponent[V] +func NewMap[K comparable, V component.Component]() *Map[K, V] { + return &Map[K, V]{ + components: map[K]*Component[V]{}, + } } -// NewSharedComponents returns a new empty SharedComponents. -func NewSharedComponents[K comparable, V component.Component]() *SharedComponents[K, V] { - return &SharedComponents[K, V]{ - comps: make(map[K]*SharedComponent[V]), - } +// Map keeps reference of all created instances for a given shared key such as a component configuration. +type Map[K comparable, V component.Component] struct { + lock sync.Mutex + components map[K]*Component[V] } -// GetOrAdd returns the already created instance if exists, otherwise creates a new instance +// LoadOrStore returns the already created instance if exists, otherwise creates a new instance // and adds it to the map of references. -func (scs *SharedComponents[K, V]) GetOrAdd(key K, create func() (V, error)) (*SharedComponent[V], error) { - if c, ok := scs.comps[key]; ok { +func (m *Map[K, V]) LoadOrStore(key K, create func() (V, error), telemetrySettings *component.TelemetrySettings) (*Component[V], error) { + m.lock.Lock() + defer m.lock.Unlock() + if c, ok := m.components[key]; ok { + // If we haven't already seen this telemetry settings, this shared component represents + // another instance. Wrap ReportStatus to report for all instances this shared + // component represents. + if _, ok := c.seenSettings[telemetrySettings]; !ok { + c.seenSettings[telemetrySettings] = struct{}{} + prev := c.telemetry.ReportStatus + c.telemetry.ReportStatus = func(ev *component.StatusEvent) { + telemetrySettings.ReportStatus(ev) + prev(ev) + } + } return c, nil } comp, err := create() if err != nil { return nil, err } - newComp := &SharedComponent[V]{ + + newComp := &Component[V]{ component: comp, removeFunc: func() { - delete(scs.comps, key) + m.lock.Lock() + defer m.lock.Unlock() + delete(m.components, key) + }, + telemetry: telemetrySettings, + seenSettings: map[*component.TelemetrySettings]struct{}{ + telemetrySettings: {}, }, } - scs.comps[key] = newComp + m.components[key] = newComp return newComp, nil } -// SharedComponent ensures that the wrapped component is started and stopped only once. -// When stopped it is removed from the SharedComponents map. -type SharedComponent[V component.Component] struct { +// Component ensures that the wrapped component is started and stopped only once. +// When stopped it is removed from the Map. +type Component[V component.Component] struct { component V startOnce sync.Once stopOnce sync.Once removeFunc func() + + telemetry *component.TelemetrySettings + seenSettings map[*component.TelemetrySettings]struct{} } // Unwrap returns the original component. -func (r *SharedComponent[V]) Unwrap() V { - return r.component +func (c *Component[V]) Unwrap() V { + return c.component } -// Start implements component.Component. -func (r *SharedComponent[V]) Start(ctx context.Context, host component.Host) error { +// Start starts the underlying component if it never started before. +func (c *Component[V]) Start(ctx context.Context, host component.Host) error { var err error - r.startOnce.Do(func() { - err = r.component.Start(ctx, host) + c.startOnce.Do(func() { + // It's important that status for a shared component is reported through its + // telemetry settings to keep status in sync and avoid race conditions. This logic duplicates + // and takes priority over the automated status reporting that happens in graph, making the + // status reporting in graph a no-op. + c.telemetry.ReportStatus(component.NewStatusEvent(component.StatusStarting)) + if err = c.component.Start(ctx, host); err != nil { + c.telemetry.ReportStatus(component.NewPermanentErrorEvent(err)) + } }) return err } -// Shutdown implements component.Component. -func (r *SharedComponent[V]) Shutdown(ctx context.Context) error { +// Shutdown shuts down the underlying component. +func (c *Component[V]) Shutdown(ctx context.Context) error { var err error - r.stopOnce.Do(func() { - err = r.component.Shutdown(ctx) - r.removeFunc() + c.stopOnce.Do(func() { + // It's important that status for a shared component is reported through its + // telemetry settings to keep status in sync and avoid race conditions. This logic duplicates + // and takes priority over the automated status reporting that happens in graph, making the + // status reporting in graph a no-op. + c.telemetry.ReportStatus(component.NewStatusEvent(component.StatusStopping)) + err = c.component.Shutdown(ctx) + if err != nil { + c.telemetry.ReportStatus(component.NewPermanentErrorEvent(err)) + } else { + c.telemetry.ReportStatus(component.NewStatusEvent(component.StatusStopped)) + } + c.removeFunc() }) return err } diff --git a/internal/sharedcomponent/sharedcomponent_test.go b/internal/sharedcomponent/sharedcomponent_test.go index 112f1d79d07..77cda5124db 100644 --- a/internal/sharedcomponent/sharedcomponent_test.go +++ b/internal/sharedcomponent/sharedcomponent_test.go @@ -15,43 +15,61 @@ import ( "go.opentelemetry.io/collector/component/componenttest" ) -var id = component.NewID("test") +var id = component.MustNewID("test") type baseComponent struct { component.StartFunc component.ShutdownFunc + telemetry *component.TelemetrySettings } -func TestNewSharedComponents(t *testing.T) { - comps := NewSharedComponents[component.ID, *baseComponent]() - assert.Len(t, comps.comps, 0) +func TestNewMap(t *testing.T) { + comps := NewMap[component.ID, *baseComponent]() + assert.Len(t, comps.components, 0) } func TestNewSharedComponentsCreateError(t *testing.T) { - comps := NewSharedComponents[component.ID, *baseComponent]() - assert.Len(t, comps.comps, 0) + comps := NewMap[component.ID, *baseComponent]() + assert.Len(t, comps.components, 0) myErr := errors.New("my error") - _, err := comps.GetOrAdd(id, func() (*baseComponent, error) { return nil, myErr }) + _, err := comps.LoadOrStore( + id, + func() (*baseComponent, error) { return nil, myErr }, + newNopTelemetrySettings(), + ) assert.ErrorIs(t, err, myErr) - assert.Len(t, comps.comps, 0) + assert.Len(t, comps.components, 0) } -func TestSharedComponentsGetOrAdd(t *testing.T) { +func TestSharedComponentsLoadOrStore(t *testing.T) { nop := &baseComponent{} - comps := NewSharedComponents[component.ID, *baseComponent]() - got, err := comps.GetOrAdd(id, func() (*baseComponent, error) { return nop, nil }) + comps := NewMap[component.ID, *baseComponent]() + got, err := comps.LoadOrStore( + id, + func() (*baseComponent, error) { return nop, nil }, + newNopTelemetrySettings(), + ) require.NoError(t, err) - assert.Len(t, comps.comps, 1) + assert.Len(t, comps.components, 1) assert.Same(t, nop, got.Unwrap()) - gotSecond, err := comps.GetOrAdd(id, func() (*baseComponent, error) { panic("should not be called") }) + gotSecond, err := comps.LoadOrStore( + id, + func() (*baseComponent, error) { panic("should not be called") }, + newNopTelemetrySettings(), + ) + require.NoError(t, err) assert.Same(t, got, gotSecond) // Shutdown nop will remove assert.NoError(t, got.Shutdown(context.Background())) - assert.Len(t, comps.comps, 0) - gotThird, err := comps.GetOrAdd(id, func() (*baseComponent, error) { return nop, nil }) + assert.Len(t, comps.components, 0) + gotThird, err := comps.LoadOrStore( + id, + func() (*baseComponent, error) { return nop, nil }, + newNopTelemetrySettings(), + ) require.NoError(t, err) assert.NotSame(t, got, gotThird) } @@ -61,26 +79,201 @@ func TestSharedComponent(t *testing.T) { calledStart := 0 calledStop := 0 comp := &baseComponent{ - StartFunc: func(ctx context.Context, host component.Host) error { + StartFunc: func(context.Context, component.Host) error { calledStart++ return wantErr }, - ShutdownFunc: func(ctx context.Context) error { + ShutdownFunc: func(context.Context) error { calledStop++ return wantErr }} - comps := NewSharedComponents[component.ID, *baseComponent]() - got, err := comps.GetOrAdd(id, func() (*baseComponent, error) { return comp, nil }) + comps := NewMap[component.ID, *baseComponent]() + got, err := comps.LoadOrStore( + id, + func() (*baseComponent, error) { return comp, nil }, + newNopTelemetrySettings(), + ) require.NoError(t, err) assert.Equal(t, wantErr, got.Start(context.Background(), componenttest.NewNopHost())) assert.Equal(t, 1, calledStart) // Second time is not called anymore. assert.NoError(t, got.Start(context.Background(), componenttest.NewNopHost())) assert.Equal(t, 1, calledStart) + // first time, shutdown is called. assert.Equal(t, wantErr, got.Shutdown(context.Background())) assert.Equal(t, 1, calledStop) // Second time is not called anymore. assert.NoError(t, got.Shutdown(context.Background())) assert.Equal(t, 1, calledStop) } +func TestSharedComponentsReportStatus(t *testing.T) { + reportedStatuses := make(map[*component.InstanceID][]component.Status) + newStatusFunc := func() func(*component.StatusEvent) { + instanceID := &component.InstanceID{} + return func(ev *component.StatusEvent) { + if ev.Status() == component.StatusNone { + return + } + reportedStatuses[instanceID] = append(reportedStatuses[instanceID], ev.Status()) + } + } + + comp := &baseComponent{} + comps := NewMap[component.ID, *baseComponent]() + var telemetrySettings *component.TelemetrySettings + + // make a shared component that represents three instances + for i := 0; i < 3; i++ { + telemetrySettings = newNopTelemetrySettings() + telemetrySettings.ReportStatus = newStatusFunc() + // The initial settings for the shared component need to match the ones passed to the first + // invocation of LoadOrStore so that underlying telemetry settings reference can be used to + // wrap ReportStatus for subsequently added "instances". + if i == 0 { + comp.telemetry = telemetrySettings + } + got, err := comps.LoadOrStore( + id, + func() (*baseComponent, error) { return comp, nil }, + telemetrySettings, + ) + require.NoError(t, err) + assert.Len(t, comps.components, 1) + assert.Same(t, comp, got.Unwrap()) + } + + // make sure we don't try to represent a fourth instance if we reuse a telemetrySettings + _, _ = comps.LoadOrStore( + id, + func() (*baseComponent, error) { return comp, nil }, + telemetrySettings, + ) + + comp.telemetry.ReportStatus(component.NewStatusEvent(component.StatusStarting)) + + comp.telemetry.ReportStatus(component.NewStatusEvent(component.StatusOK)) + + // simulate an error + comp.telemetry.ReportStatus(component.NewStatusEvent(component.StatusNone)) + + // stopping + comp.telemetry.ReportStatus(component.NewStatusEvent(component.StatusStopping)) + + // stopped + comp.telemetry.ReportStatus(component.NewStatusEvent(component.StatusStopped)) + + // The shared component represents 3 component instances. Reporting status for the shared + // component should report status for each of the instances it represents. + expectedStatuses := []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusStopping, + component.StatusStopped, + } + + require.Equal(t, 3, len(reportedStatuses)) + + for _, actualStatuses := range reportedStatuses { + require.Equal(t, expectedStatuses, actualStatuses) + } +} + +func TestReportStatusOnStartShutdown(t *testing.T) { + for _, tc := range []struct { + name string + startErr error + shutdownErr error + expectedStatuses []component.Status + }{ + { + name: "successful start/stop", + startErr: nil, + shutdownErr: nil, + expectedStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusStopping, + component.StatusStopped, + }, + }, + { + name: "start error", + startErr: assert.AnError, + shutdownErr: nil, + expectedStatuses: []component.Status{ + component.StatusStarting, + component.StatusPermanentError, + }, + }, + { + name: "shutdown error", + shutdownErr: assert.AnError, + expectedStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusStopping, + component.StatusPermanentError, + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + reportedStatuses := make(map[*component.InstanceID][]component.Status) + newStatusFunc := func() func(*component.StatusEvent) { + instanceID := &component.InstanceID{} + return func(ev *component.StatusEvent) { + reportedStatuses[instanceID] = append(reportedStatuses[instanceID], ev.Status()) + } + } + base := &baseComponent{} + if tc.startErr != nil { + base.StartFunc = func(context.Context, component.Host) error { + return tc.startErr + } + } + if tc.shutdownErr != nil { + base.ShutdownFunc = func(context.Context) error { + return tc.shutdownErr + } + } + comps := NewMap[component.ID, *baseComponent]() + var comp *Component[*baseComponent] + var err error + for i := 0; i < 3; i++ { + telemetrySettings := newNopTelemetrySettings() + telemetrySettings.ReportStatus = newStatusFunc() + if i == 0 { + base.telemetry = telemetrySettings + } + comp, err = comps.LoadOrStore( + id, + func() (*baseComponent, error) { return base, nil }, + telemetrySettings, + ) + require.NoError(t, err) + } + + err = comp.Start(context.Background(), componenttest.NewNopHost()) + require.Equal(t, tc.startErr, err) + + if tc.startErr == nil { + comp.telemetry.ReportStatus(component.NewStatusEvent(component.StatusOK)) + + err = comp.Shutdown(context.Background()) + require.Equal(t, tc.shutdownErr, err) + } + + require.Equal(t, 3, len(reportedStatuses)) + + for _, actualStatuses := range reportedStatuses { + require.Equal(t, tc.expectedStatuses, actualStatuses) + } + }) + } +} + +// newNopTelemetrySettings streamlines getting a pointer to a NopTelemetrySettings +func newNopTelemetrySettings() *component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + return &set +} diff --git a/internal/testutil/package_test.go b/internal/testutil/package_test.go new file mode 100644 index 00000000000..d77e80fc1ab --- /dev/null +++ b/internal/testutil/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package testutil + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/internal/testutil/testutil.go b/internal/testutil/testutil.go index 427e51d2e19..b8d9923869c 100644 --- a/internal/testutil/testutil.go +++ b/internal/testutil/testutil.go @@ -13,8 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - - "go.opentelemetry.io/collector/service/telemetry" + "go.opentelemetry.io/contrib/config" ) type portpair struct { @@ -57,7 +56,7 @@ func GetAvailableLocalAddress(t testing.TB) string { return endpoint } -func GetAvailableLocalAddressPrometheus(t testing.TB) *telemetry.Prometheus { +func GetAvailableLocalAddressPrometheus(t testing.TB) *config.Prometheus { address := GetAvailableLocalAddress(t) host, port, err := net.SplitHostPort(address) if err != nil { @@ -67,7 +66,7 @@ func GetAvailableLocalAddressPrometheus(t testing.TB) *telemetry.Prometheus { if err != nil { return nil } - return &telemetry.Prometheus{ + return &config.Prometheus{ Host: &host, Port: &portInt, } diff --git a/internal/tools/go.mod b/internal/tools/go.mod index 9f8c6a53af4..c5dda5ebbdc 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -1,43 +1,42 @@ module go.opentelemetry.io/collector/internal/tools -go 1.20 +go 1.21 require ( github.com/a8m/envsubst v1.4.2 - github.com/atombender/go-jsonschema v0.12.1 github.com/client9/misspell v0.3.4 - github.com/golangci/golangci-lint v1.54.2 + github.com/golangci/golangci-lint v1.56.2 github.com/google/addlicense v1.1.1 - github.com/jcchavezs/porto v0.4.0 - github.com/mikefarah/yq/v4 v4.35.1 + github.com/jcchavezs/porto v0.6.0 github.com/pavius/impi v0.0.3 - go.opentelemetry.io/build-tools/checkfile v0.11.0 - go.opentelemetry.io/build-tools/chloggen v0.11.0 - go.opentelemetry.io/build-tools/crosslink v0.11.0 - go.opentelemetry.io/build-tools/multimod v0.11.0 - go.opentelemetry.io/build-tools/semconvgen v0.11.0 - golang.org/x/exp v0.0.0-20230711023510-fffb14384f22 - golang.org/x/tools v0.13.0 - golang.org/x/vuln v1.0.1 + go.opentelemetry.io/build-tools/checkfile v0.12.0 + go.opentelemetry.io/build-tools/chloggen v0.12.0 + go.opentelemetry.io/build-tools/crosslink v0.12.1-0.20240121161735-d70c842b1bf5 + go.opentelemetry.io/build-tools/multimod v0.12.0 + go.opentelemetry.io/build-tools/semconvgen v0.12.0 + golang.org/x/exp v0.0.0-20240119083558-1b970713d09a + golang.org/x/tools v0.18.0 + golang.org/x/vuln v1.0.4 ) require ( 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect 4d63.com/gochecknoglobals v0.2.1 // indirect dario.cat/mergo v1.0.0 // indirect - github.com/4meepo/tagalign v1.3.2 // indirect - github.com/Abirdcfly/dupword v0.0.12 // indirect + github.com/4meepo/tagalign v1.3.3 // indirect + github.com/Abirdcfly/dupword v0.0.13 // indirect github.com/Antonboom/errname v0.1.12 // indirect github.com/Antonboom/nilnil v0.1.7 // indirect + github.com/Antonboom/testifylint v1.1.2 // indirect github.com/BurntSushi/toml v1.3.2 // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect - github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0 // indirect + github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/OpenPeeDeeP/depguard/v2 v2.1.0 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect - github.com/acomagu/bufpipe v1.0.4 // indirect - github.com/alecthomas/participle/v2 v2.0.0 // indirect + github.com/OpenPeeDeeP/depguard/v2 v2.2.0 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect + github.com/alecthomas/assert/v2 v2.3.0 // indirect + github.com/alecthomas/go-check-sumtype v0.1.4 // indirect github.com/alexkohler/nakedret/v2 v2.0.2 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect @@ -47,137 +46,132 @@ require ( github.com/bkielbasa/cyclop v1.2.1 // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect github.com/bmatcuk/doublestar/v4 v4.0.2 // indirect - github.com/bombsimon/wsl/v3 v3.4.0 // indirect - github.com/breml/bidichk v0.2.4 // indirect - github.com/breml/errchkjson v0.3.1 // indirect - github.com/butuzov/ireturn v0.2.0 // indirect + github.com/bombsimon/wsl/v4 v4.2.1 // indirect + github.com/breml/bidichk v0.2.7 // indirect + github.com/breml/errchkjson v0.3.6 // indirect + github.com/butuzov/ireturn v0.3.0 // indirect github.com/butuzov/mirror v1.1.0 // indirect - github.com/ccojocar/zxcvbn-go v1.0.1 // indirect + github.com/catenacyber/perfsprint v0.6.0 // indirect + github.com/ccojocar/zxcvbn-go v1.0.2 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/charithe/durationcheck v0.0.10 // indirect - github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 // indirect - github.com/cloudflare/circl v1.3.3 // indirect + github.com/chavacava/garif v0.1.0 // indirect + github.com/cloudflare/circl v1.3.7 // indirect github.com/curioswitch/go-reassign v0.2.0 // indirect - github.com/daixiang0/gci v0.11.0 // indirect + github.com/cyphar/filepath-securejoin v0.2.4 // indirect + github.com/daixiang0/gci v0.12.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/denis-tingaikin/go-header v0.4.3 // indirect - github.com/dimchansky/utfbom v1.1.1 // indirect - github.com/elliotchance/orderedmap v1.5.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/esimonov/ifshort v1.0.4 // indirect - github.com/ettle/strcase v0.1.1 // indirect - github.com/fatih/color v1.15.0 // indirect + github.com/ettle/strcase v0.2.0 // indirect + github.com/fatih/color v1.16.0 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/firefart/nonamedreturns v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/go-critic/go-critic v0.9.0 // indirect + github.com/ghostiam/protogetter v0.3.4 // indirect + github.com/go-critic/go-critic v0.11.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.4.1 // indirect - github.com/go-git/go-git/v5 v5.8.1 // indirect + github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/go-git/go-git/v5 v5.11.0 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect - github.com/go-toolsmith/astequal v1.1.0 // indirect + github.com/go-toolsmith/astequal v1.2.0 // indirect github.com/go-toolsmith/astfmt v1.1.0 // indirect github.com/go-toolsmith/astp v1.1.0 // indirect github.com/go-toolsmith/strparse v1.1.0 // indirect github.com/go-toolsmith/typep v1.1.0 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect github.com/gobwas/glob v0.2.3 // indirect - github.com/goccy/go-json v0.10.2 // indirect - github.com/goccy/go-yaml v1.11.0 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect - github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 // indirect + github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e // indirect github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca // indirect github.com/golangci/misspell v0.4.1 // indirect - github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 // indirect + github.com/golangci/revgrep v0.5.2 // indirect github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect - github.com/google/go-cmp v0.5.9 // indirect - github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/gordonklaus/ineffassign v0.1.0 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.4.2 // indirect github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect github.com/gostaticanalysis/nilerr v0.1.1 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jgautheron/goconst v1.5.1 // indirect + github.com/jgautheron/goconst v1.7.0 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect - github.com/jinzhu/copier v0.3.5 // indirect github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect + github.com/jjti/go-spancheck v0.5.2 // indirect github.com/julz/importas v0.1.0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/kisielk/errcheck v1.6.3 // indirect + github.com/kisielk/errcheck v1.7.0 // indirect github.com/kisielk/gotool v1.0.0 // indirect github.com/kkHAIKE/contextcheck v1.1.4 // indirect github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.8 // indirect + github.com/kunwardeep/paralleltest v1.0.9 // indirect github.com/kyoh86/exportloopref v0.1.11 // indirect github.com/ldez/gomoddirectives v0.2.3 // indirect github.com/ldez/tagliatelle v0.5.0 // indirect github.com/leonklingele/grouper v1.1.1 // indirect github.com/lufeee/execinquery v1.2.1 // indirect + github.com/macabu/inamedparam v0.1.3 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/maratori/testableexamples v1.0.0 // indirect github.com/maratori/testpackage v1.1.1 // indirect github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mbilski/exhaustivestruct v1.2.0 // indirect - github.com/mgechev/revive v1.3.2 // indirect + github.com/mgechev/revive v1.3.7 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/moricho/tparallel v0.3.1 // indirect github.com/nakabonne/nestif v0.3.1 // indirect - github.com/nishanths/exhaustive v0.11.0 // indirect + github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.13.5 // indirect + github.com/nunnatsa/ginkgolinter v0.15.2 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.9 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polyfloyd/go-errorlint v1.4.4 // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect + github.com/polyfloyd/go-errorlint v1.4.8 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.11.1 // indirect github.com/quasilyte/go-ruleguard v0.4.0 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect github.com/ryancurrah/gomodguard v1.3.0 // indirect - github.com/ryanrolds/sqlclosecheck v0.4.0 // indirect - github.com/sanity-io/litter v1.5.5 // indirect + github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.24.0 // indirect - github.com/securego/gosec/v2 v2.17.0 // indirect + github.com/sashamelentyev/usestdlibvars v1.25.0 // indirect + github.com/securego/gosec/v2 v2.19.0 // indirect github.com/sergi/go-diff v1.1.0 // indirect github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect github.com/sivchari/nosnakecase v1.7.0 // indirect github.com/sivchari/tenv v1.7.1 // indirect - github.com/skeema/knownhosts v1.2.0 // indirect + github.com/skeema/knownhosts v1.2.1 // indirect github.com/sonatard/noctx v0.0.2 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect - github.com/spf13/afero v1.9.5 // indirect + github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.5.1 // indirect - github.com/spf13/cobra v1.7.0 // indirect + github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.16.0 // indirect @@ -188,43 +182,42 @@ require ( github.com/subosito/gotenv v1.4.2 // indirect github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect github.com/tdakkota/asciicheck v0.2.0 // indirect - github.com/tetafro/godot v1.4.14 // indirect + github.com/tetafro/godot v1.4.16 // indirect github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 // indirect github.com/timonwong/loggercheck v0.9.4 // indirect github.com/tomarrell/wrapcheck/v2 v2.8.1 // indirect github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect github.com/ultraware/funlen v0.1.0 // indirect - github.com/ultraware/whitespace v0.0.5 // indirect - github.com/uudashr/gocognit v1.0.7 // indirect + github.com/ultraware/whitespace v0.1.0 // indirect + github.com/uudashr/gocognit v1.1.2 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - github.com/xen0n/gosmopolitan v1.2.1 // indirect + github.com/xen0n/gosmopolitan v1.2.2 // indirect github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.2.0 // indirect - github.com/ykadowak/zerologlint v0.1.3 // indirect - gitlab.com/bosi/decorder v0.4.0 // indirect - go.opentelemetry.io/build-tools v0.11.0 // indirect - go.tmz.dev/musttag v0.7.2 // indirect + github.com/ykadowak/zerologlint v0.1.5 // indirect + gitlab.com/bosi/decorder v0.4.1 // indirect + go-simpler.org/musttag v0.8.0 // indirect + go-simpler.org/sloglint v0.4.0 // indirect + go.opentelemetry.io/build-tools v0.12.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect - golang.org/x/crypto v0.13.0 // indirect - golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect + golang.org/x/crypto v0.19.0 // indirect + golang.org/x/exp/typeparams v0.0.0-20231219180239-dc181d75b848 // indirect + golang.org/x/mod v0.15.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/tools v0.4.5 // indirect - mvdan.cc/gofumpt v0.5.0 // indirect + honnef.co/go/tools v0.4.6 // indirect + mvdan.cc/gofumpt v0.6.0 // indirect mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect - mvdan.cc/unparam v0.0.0-20230312165513-e84e2d14e3b8 // indirect + mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14 // indirect ) retract ( diff --git a/internal/tools/go.sum b/internal/tools/go.sum index 3a2a1c9a7b7..b0c915fbf3d 100644 --- a/internal/tools/go.sum +++ b/internal/tools/go.sum @@ -7,7 +7,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -18,9 +17,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -38,43 +34,44 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/4meepo/tagalign v1.3.2 h1:1idD3yxlRGV18VjqtDbqYvQ5pXqQS0wO2dn6M3XstvI= -github.com/4meepo/tagalign v1.3.2/go.mod h1:Q9c1rYMZJc9dPRkbQPpcBNCLEmY2njbAsXhQOZFE2dE= -github.com/Abirdcfly/dupword v0.0.12 h1:56NnOyrXzChj07BDFjeRA+IUzSz01jmzEq+G4kEgFhc= -github.com/Abirdcfly/dupword v0.0.12/go.mod h1:+us/TGct/nI9Ndcbcp3rgNcQzctTj68pq7TcgNpLfdI= +github.com/4meepo/tagalign v1.3.3 h1:ZsOxcwGD/jP4U/aw7qeWu58i7dwYemfy5Y+IF1ACoNw= +github.com/4meepo/tagalign v1.3.3/go.mod h1:Q9c1rYMZJc9dPRkbQPpcBNCLEmY2njbAsXhQOZFE2dE= +github.com/Abirdcfly/dupword v0.0.13 h1:SMS17YXypwP000fA7Lr+kfyBQyW14tTT+nRv9ASwUUo= +github.com/Abirdcfly/dupword v0.0.13/go.mod h1:Ut6Ue2KgF/kCOawpW4LnExT+xZLQviJPE4klBPMK/5Y= github.com/Antonboom/errname v0.1.12 h1:oh9ak2zUtsLp5oaEd/erjB4GPu9w19NyoIskZClDcQY= github.com/Antonboom/errname v0.1.12/go.mod h1:bK7todrzvlaZoQagP1orKzWXv59X/x0W0Io2XT1Ssro= github.com/Antonboom/nilnil v0.1.7 h1:ofgL+BA7vlA1K2wNQOsHzLJ2Pw5B5DpWRLdDAVvvTow= github.com/Antonboom/nilnil v0.1.7/go.mod h1:TP+ScQWVEq0eSIxqU8CbdT5DFWoHp0MbP+KMUO1BKYQ= +github.com/Antonboom/testifylint v1.1.2 h1:IdLRermiLRogxY5AumBL4sP0A+qKHQM/AP1Xd7XOTKc= +github.com/Antonboom/testifylint v1.1.2/go.mod h1:9PFi+vWa8zzl4/B/kqmFJcw85ZUv8ReyBzuQCd30+WI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0 h1:3ZBs7LAezy8gh0uECsA6CGU43FF3zsx5f4eah5FxTMA= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0/go.mod h1:rZLTje5A9kFBe0pzhpe2TdhRniBF++PRHQuRpR8esVc= +github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0 h1:sATXp1x6/axKxz2Gjxv8MALP0bXaNRfQinEwyfMcx8c= +github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0/go.mod h1:Nl76DrGNJTA1KJ0LePKBw/vznBX1EHbAZX8mwjR82nI= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/OpenPeeDeeP/depguard/v2 v2.1.0 h1:aQl70G173h/GZYhWf36aE5H0KaujXfVMnn/f1kSDVYY= -github.com/OpenPeeDeeP/depguard/v2 v2.1.0/go.mod h1:PUBgk35fX4i7JDmwzlJwJ+GMe6NfO1723wmJMgPThNQ= -github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 h1:KLq8BE0KwCL+mmXnjLWEAOYO+2l2AE4YMmqG1ZpZHBs= -github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/OpenPeeDeeP/depguard/v2 v2.2.0 h1:vDfG60vDtIuf0MEOhmLlLLSzqaRM8EMcgJPdp74zmpA= +github.com/OpenPeeDeeP/depguard/v2 v2.2.0/go.mod h1:CIzddKRvLBC4Au5aYP/i3nyaWQ+ClszLIuVocRiCYFQ= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/a8m/envsubst v1.4.2 h1:4yWIHXOLEJHQEFd4UjrWDrYeYlV7ncFWJOCBRLOZHQg= github.com/a8m/envsubst v1.4.2/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY= -github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= -github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= -github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= -github.com/alecthomas/participle/v2 v2.0.0 h1:Fgrq+MbuSsJwIkw3fEj9h75vDP0Er5JzepJ0/HNHv0g= -github.com/alecthomas/participle/v2 v2.0.0/go.mod h1:rAKZdJldHu8084ojcWevWAL8KmEU+AT+Olodb+WoN2Y= +github.com/alecthomas/assert/v2 v2.3.0 h1:mAsH2wmvjsuvyBvAmCtm7zFsBlb8mIHx5ySLVdDZXL0= +github.com/alecthomas/assert/v2 v2.3.0/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= +github.com/alecthomas/go-check-sumtype v0.1.4 h1:WCvlB3l5Vq5dZQTFmodqL2g68uHiSwwlWcT5a2FGK0c= +github.com/alecthomas/go-check-sumtype v0.1.4/go.mod h1:WyYPfhfkdhyrdaligV6svFopZV8Lqdzn5pyVBaV6jhQ= github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= +github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -87,13 +84,13 @@ github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cv github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= -github.com/atombender/go-jsonschema v0.12.1 h1:TGt/A1LIT6K/8Kro0Mgu0urhMSuDah9UdI9HfBScn10= -github.com/atombender/go-jsonschema v0.12.1/go.mod h1:O/retkAzM5emQ4e/3Mv16NHzc/+oBIAdzPk/JL4DQt8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -104,19 +101,21 @@ github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bmatcuk/doublestar/v4 v4.0.2 h1:X0krlUVAVmtr2cRoTqR8aDMrDqnB36ht8wpWTiQ3jsA= github.com/bmatcuk/doublestar/v4 v4.0.2/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= -github.com/bombsimon/wsl/v3 v3.4.0 h1:RkSxjT3tmlptwfgEgTgU+KYKLI35p/tviNXNXiL2aNU= -github.com/bombsimon/wsl/v3 v3.4.0/go.mod h1:KkIB+TXkqy6MvK9BDZVbZxKNYsE1/oLRJbIFtf14qqo= -github.com/breml/bidichk v0.2.4 h1:i3yedFWWQ7YzjdZJHnPo9d/xURinSq3OM+gyM43K4/8= -github.com/breml/bidichk v0.2.4/go.mod h1:7Zk0kRFt1LIZxtQdl9W9JwGAcLTTkOs+tN7wuEYGJ3s= -github.com/breml/errchkjson v0.3.1 h1:hlIeXuspTyt8Y/UmP5qy1JocGNR00KQHgfaNtRAjoxQ= -github.com/breml/errchkjson v0.3.1/go.mod h1:XroxrzKjdiutFyW3nWhw34VGg7kiMsDQox73yWCGI2U= -github.com/butuzov/ireturn v0.2.0 h1:kCHi+YzC150GE98WFuZQu9yrTn6GEydO2AuPLbTgnO4= -github.com/butuzov/ireturn v0.2.0/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= +github.com/bombsimon/wsl/v4 v4.2.1 h1:Cxg6u+XDWff75SIFFmNsqnIOgob+Q9hG6y/ioKbRFiM= +github.com/bombsimon/wsl/v4 v4.2.1/go.mod h1:Xu/kDxGZTofQcDGCtQe9KCzhHphIe0fDuyWTxER9Feo= +github.com/breml/bidichk v0.2.7 h1:dAkKQPLl/Qrk7hnP6P+E0xOodrq8Us7+U0o4UBOAlQY= +github.com/breml/bidichk v0.2.7/go.mod h1:YodjipAGI9fGcYM7II6wFvGhdMYsC5pHDlGzqvEW3tQ= +github.com/breml/errchkjson v0.3.6 h1:VLhVkqSBH96AvXEyclMR37rZslRrY2kcyq+31HCsVrA= +github.com/breml/errchkjson v0.3.6/go.mod h1:jhSDoFheAF2RSDOlCfhHO9KqhZgAYLyvHe7bRCX8f/U= +github.com/butuzov/ireturn v0.3.0 h1:hTjMqWw3y5JC3kpnC5vXmFJAWI/m31jaCYQqzkS6PL0= +github.com/butuzov/ireturn v0.3.0/go.mod h1:A09nIiwiqzN/IoVo9ogpa0Hzi9fex1kd9PSD6edP5ZA= github.com/butuzov/mirror v1.1.0 h1:ZqX54gBVMXu78QLoiqdwpl2mgmoOJTk7s4p4o+0avZI= github.com/butuzov/mirror v1.1.0/go.mod h1:8Q0BdQU6rC6WILDiBM60DBfvV78OLJmMmixe7GF45AE= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/ccojocar/zxcvbn-go v1.0.1 h1:+sxrANSCj6CdadkcMnvde/GWU1vZiiXRbqYSCalV4/4= -github.com/ccojocar/zxcvbn-go v1.0.1/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= +github.com/catenacyber/perfsprint v0.6.0 h1:VSv95RRkk5+BxrU/YTPcnxuMEWar1iMK5Vyh3fWcBfs= +github.com/catenacyber/perfsprint v0.6.0/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= +github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= +github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -124,68 +123,67 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= -github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 h1:W9o46d2kbNL06lq7UNDPV0zYLzkrde/bjIqO02eoll0= -github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8/go.mod h1:gakxgyXaaPkxvLw1XQxNGK4I37ys9iBRzNUx/B7pUCo= +github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= +github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= -github.com/daixiang0/gci v0.11.0 h1:XeQbFKkCRxvVyn06EOuNY6LPGBLVuB/W130c8FrnX6A= -github.com/daixiang0/gci v0.11.0/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= -github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/daixiang0/gci v0.12.1 h1:ugsG+KRYny1VK4oqrX4Vtj70bo4akYKa0tgT1DXMYiY= +github.com/daixiang0/gci v0.12.1/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20Ha7UVm+mtU= github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= -github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= -github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= -github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0= -github.com/elliotchance/orderedmap v1.5.0 h1:1IsExUsjv5XNBD3ZdC7jkAAqLWOOKdbPTmkHx63OsBg= -github.com/elliotchance/orderedmap v1.5.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= -github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= -github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q= +github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= +github.com/ghostiam/protogetter v0.3.4 h1:5SZ+lZSNmNkSbGVSF9hUHhv/b7ELF9Rwchoq7btYo6c= +github.com/ghostiam/protogetter v0.3.4/go.mod h1:A0JgIhs0fgVnotGinjQiKaFVG3waItLJNwPmcMzDnvk= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= -github.com/go-critic/go-critic v0.9.0 h1:Pmys9qvU3pSML/3GEQ2Xd9RZ/ip+aXHKILuxczKGV/U= -github.com/go-critic/go-critic v0.9.0/go.mod h1:5P8tdXL7m/6qnyG6oRAlYLORvoXH0WDypYgAEmagT40= +github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= +github.com/go-critic/go-critic v0.11.1 h1:/zBseUSUMytnRqxjlsYNbDDxpu3R2yH8oLXo/FOE8b8= +github.com/go-critic/go-critic v0.11.1/go.mod h1:aZVQR7+gazH6aDEQx4356SD7d8ez8MipYjXbEl5JAKA= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= -github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8= -github.com/go-git/go-git/v5 v5.8.1 h1:Zo79E4p7TRk0xoRgMq0RShiTHGKcKI4+DI6BfJc/Q+A= -github.com/go-git/go-git/v5 v5.8.1/go.mod h1:FHFuoD6yGz5OSKEBK+aWN9Oah0q54Jxl0abmj6GnqAo= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= +github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= +github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -195,37 +193,36 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= -github.com/go-toolsmith/astequal v1.1.0 h1:kHKm1AWqClYn15R0K1KKE4RG614D46n+nqUQ06E1dTw= github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= +github.com/go-toolsmith/astequal v1.2.0 h1:3Fs3CYZ1k9Vo4FzFhwwewC3CHISHDnVUPC4x0bI2+Cw= +github.com/go-toolsmith/astequal v1.2.0/go.mod h1:c8NZ3+kSFtFY/8lPso4v8LuJjdJiUFVnSuU3s0qrrDY= github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= +github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U= github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-yaml v1.11.0 h1:n7Z+zx8S9f9KgzG6KtQKf+kwqXZlLNR2F6018Dgau54= -github.com/goccy/go-yaml v1.11.0/go.mod h1:H+mJrWtjPTJAHvRbV09MCK9xYwODM+wRTVFFTWckfng= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -258,26 +255,24 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6J5HIP8ZtyMdiDscjMLfRBSPuzVVeo= github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= -github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY= -github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= -github.com/golangci/golangci-lint v1.54.2 h1:oR9zxfWYxt7hFqk6+fw6Enr+E7F0SN2nqHhJYyIb0yo= -github.com/golangci/golangci-lint v1.54.2/go.mod h1:vnsaCTPKCI2wreL9tv7RkHDwUrz3htLjed6+6UsvcwU= +github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e h1:ULcKCDV1LOZPFxGZaA6TlQbiM3J2GCPnkx/bGF6sX/g= +github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e/go.mod h1:Pm5KhLPA8gSnQwrQ6ukebRcapGb/BG9iUkdaiCcGHJM= +github.com/golangci/golangci-lint v1.56.2 h1:dgQzlWHgNbCqJjuxRJhFEnHDVrrjuTGQHJ3RIZMpp/o= +github.com/golangci/golangci-lint v1.56.2/go.mod h1:7CfNO675+EY7j84jihO4iAqDQ80s3HCjcc5M6B7SlZQ= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= github.com/golangci/misspell v0.4.1 h1:+y73iSicVy2PqyX7kmUefHusENlrP9YwuHZHPLGQj/g= github.com/golangci/misspell v0.4.1/go.mod h1:9mAN1quEo3DlpbaIKKyEvRxK1pwqR9s/Sea1bJCtlNI= -github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 h1:DIPQnGy2Gv2FSA4B/hh8Q7xx3B7AIDk3DAMeHclH1vQ= -github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs= +github.com/golangci/revgrep v0.5.2 h1:EndcWoRhcnfj2NHQ+28hyuXpLMF+dQmCN+YaeeIl4FU= +github.com/golangci/revgrep v0.5.2/go.mod h1:bjAMA+Sh/QUfTDcHzxfyHxr4xKvllVr/0sCv2e7jJHA= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/google/addlicense v1.1.1 h1:jpVf9qPbU8rz5MxKo7d+RMcNHkqxi4YJi/laauX4aAE= @@ -285,6 +280,7 @@ github.com/google/addlicense v1.1.1/go.mod h1:Sm/DHu7Jk+T5miFHHehdIjbi4M5+dJDRS3 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU= +github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -297,12 +293,11 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -310,18 +305,14 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601 h1:mrEEilTAUmaAORhssPPkxj84TsHrPMLBGW2Z4SoTxm8= -github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= +github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= @@ -333,10 +324,7 @@ github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3 github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= @@ -347,21 +335,20 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jcchavezs/porto v0.4.0 h1:Zj7RligrxmDdKGo6fBO2xYAHxEgrVBfs1YAja20WbV4= -github.com/jcchavezs/porto v0.4.0/go.mod h1:fESH0gzDHiutHRdX2hv27ojnOVFco37hg1W6E9EZF4A= -github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= -github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jcchavezs/porto v0.6.0 h1:AgQLGwsXaxDkPj4Y+paFkVGLAR4n/1RRF0xV5UKinwg= +github.com/jcchavezs/porto v0.6.0/go.mod h1:fESH0gzDHiutHRdX2hv27ojnOVFco37hg1W6E9EZF4A= +github.com/jgautheron/goconst v1.7.0 h1:cEqH+YBKLsECnRSd4F4TK5ri8t/aXtt/qoL0Ft252B0= +github.com/jgautheron/goconst v1.7.0/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= -github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= -github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= +github.com/jjti/go-spancheck v0.5.2 h1:WXTZG3efY/ji1Vi8mkH+23O3bLeKR6hp3tI3YB7XwKk= +github.com/jjti/go-spancheck v0.5.2/go.mod h1:ARPNI1JRG1V2Rjnd6/2f2NEfghjSVDZGVmruNKlnXU0= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -375,38 +362,38 @@ github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8= -github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= +github.com/kisielk/errcheck v1.7.0 h1:+SbscKmWJ5mOK/bO1zS60F5I9WwZDWOfRsC4RwfwRV0= +github.com/kisielk/errcheck v1.7.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkHAIKE/contextcheck v1.1.4 h1:B6zAaLhOEEcjvUgIYEqystmnFk1Oemn8bvJhbt0GMb8= github.com/kkHAIKE/contextcheck v1.1.4/go.mod h1:1+i/gWqokIa+dm31mqGLZhZJ7Uh44DJGZVmr6QRBNJg= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.8 h1:Ul2KsqtzFxTlSU7IP0JusWlLiNqQaloB9vguyjbE558= -github.com/kunwardeep/paralleltest v1.0.8/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= +github.com/kunwardeep/paralleltest v1.0.9 h1:3Sr2IfFNcsMmlqPk1cjTUbJ4zofKPGyHxenwPebgTug= +github.com/kunwardeep/paralleltest v1.0.9/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo= github.com/ldez/tagliatelle v0.5.0/go.mod h1:rj1HmWiL1MiKQuOONhd09iySTEkUuE/8+5jtPYz9xa4= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= +github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk= +github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= @@ -415,29 +402,24 @@ github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1r github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 h1:gWg6ZQ4JhDfJPqlo2srm/LN17lpybq15AryXIRcWYLE= github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= -github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= -github.com/mgechev/revive v1.3.2 h1:Wb8NQKBaALBJ3xrrj4zpwJwqwNA6nDpyJSEQWcCka6U= -github.com/mgechev/revive v1.3.2/go.mod h1:UCLtc7o5vg5aXCwdUTU1kEBQ1v+YXPAkYDIDXbrs5I0= -github.com/mikefarah/yq/v4 v4.35.1 h1:NTQ6CECE+9fjxPhBojdsmUvQM8YCmaZITz0+/nbWkbc= -github.com/mikefarah/yq/v4 v4.35.1/go.mod h1:KdjcC3wn+Dm9qp6A2WAKMXY6YQ3wxPvh3mj8A7NPK1E= +github.com/mgechev/revive v1.3.7 h1:502QY0vQGe9KtYJ9FpxMz9rL+Fc/P13CI5POL4uHCcE= +github.com/mgechev/revive v1.3.7/go.mod h1:RJ16jUbF0OWC3co/+XTxmFNgEpUPwnnA0BRllX2aDNA= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= -github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -451,66 +433,65 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nishanths/exhaustive v0.11.0 h1:T3I8nUGhl/Cwu5Z2hfc92l0e04D2GEW6e0l8pzda2l0= -github.com/nishanths/exhaustive v0.11.0/go.mod h1:RqwDsZ1xY0dNdqHho2z6X+bgzizwbLYOWnZbbl2wLB4= +github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhKRf3Swg= +github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.13.5 h1:fOsPB4CEZOPkyMqF4B9hoqOpooFWU7vWSVkCSscVpgU= -github.com/nunnatsa/ginkgolinter v0.13.5/go.mod h1:OBHy4536xtuX3102NM63XRtOyxqZOO02chsaeDWXVO8= +github.com/nunnatsa/ginkgolinter v0.15.2 h1:N2ORxUxPU56R9gsfLIlVVvCv/V/VVou5qVI1oBKBNHg= +github.com/nunnatsa/ginkgolinter v0.15.2/go.mod h1:oYxE7dt1vZI8cK2rZOs3RgTaBN2vggkqnENmoJ8kVvc= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= +github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= +github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo= +github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= -github.com/otiai10/copy v1.12.0 h1:cLMgSQnXBs1eehF0Wy/FAGsgDTDmAqFR7rQylBb1nDY= +github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= +github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= 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/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.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= -github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polyfloyd/go-errorlint v1.4.4 h1:A9gytp+p6TYqeALTYRoxJESYP8wJRETRX2xzGWFsEBU= -github.com/polyfloyd/go-errorlint v1.4.4/go.mod h1:ry5NqF7l9Q77V+XqAfUg1zfryrEtyac3G5+WVpIK0xU= +github.com/polyfloyd/go-errorlint v1.4.8 h1:jiEjKDH33ouFktyez7sckv6pHWif9B7SuS8cutDXFHw= +github.com/polyfloyd/go-errorlint v1.4.8/go.mod h1:NNCxFcFjZcw3xNjVdCchERkEM6Oz7wta2XJVxRftwO4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/quasilyte/go-ruleguard v0.4.0 h1:DyM6r+TKL+xbKB4Nm7Afd1IQh9kEUKQs2pboWGKtvQo= github.com/quasilyte/go-ruleguard v0.4.0/go.mod h1:Eu76Z/R8IXtViWUIHkE3p8gdH3/PKk1eh3YGfaEof10= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= @@ -520,22 +501,21 @@ github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:r github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= -github.com/ryanrolds/sqlclosecheck v0.4.0 h1:i8SX60Rppc1wRuyQjMciLqIzV3xnoHB7/tXbr6RGYNI= -github.com/ryanrolds/sqlclosecheck v0.4.0/go.mod h1:TBRRjzL31JONc9i4XMinicuo+s+E8yKZ5FN8X3G6CKQ= -github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= -github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= +github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc= github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.24.0 h1:MKNzmXtGh5N0y74Z/CIaJh4GlB364l0K1RUT08WSWAc= -github.com/sashamelentyev/usestdlibvars v1.24.0/go.mod h1:9cYkq+gYJ+a5W2RPdhfaSCnTVUC1OQP/bSiiBhq3OZE= -github.com/securego/gosec/v2 v2.17.0 h1:ZpAStTDKY39insEG9OH6kV3IkhQZPTq9a9eGOLOjcdI= -github.com/securego/gosec/v2 v2.17.0/go.mod h1:lt+mgC91VSmriVoJLentrMkRCYs+HLTBnUFUBuhV2hc= +github.com/sashamelentyev/usestdlibvars v1.25.0 h1:IK8SI2QyFzy/2OD2PYnhy84dpfNo9qADrRt6LH8vSzU= +github.com/sashamelentyev/usestdlibvars v1.25.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= +github.com/securego/gosec/v2 v2.19.0 h1:gl5xMkOI0/E6Hxx0XCY2XujA3V7SNSefA8sC+3f1gnk= +github.com/securego/gosec/v2 v2.19.0/go.mod h1:hOkDcHz9J/XIgIlPDXalxjeVYsHxoWUc5zJSHxcB8YM= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= @@ -554,18 +534,18 @@ github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak= github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= -github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM= -github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo= +github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00= github.com/sonatard/noctx v0.0.2/go.mod h1:kzFz+CzWSjQ2OzIm46uJZoXuBpa2+0y3T36U18dWqIo= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -581,7 +561,6 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -590,7 +569,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= @@ -603,8 +581,8 @@ github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.4.14 h1:ScO641OHpf9UpHPk8fCknSuXNMpi4iFlwuWoBs3L+1s= -github.com/tetafro/godot v1.4.14/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= +github.com/tetafro/godot v1.4.16 h1:4ChfhveiNLk4NveAZ9Pu2AN8QZ2nkUGFuadM9lrr5D0= +github.com/tetafro/godot v1.4.16/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 h1:quvGphlmUVU+nhpFa4gg4yJyTRJ13reZMDHrKwYw53M= github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= github.com/timonwong/loggercheck v0.9.4 h1:HKKhqrjcVj8sxL7K77beXh0adEm6DLjV/QOGeMXEVi4= @@ -615,20 +593,20 @@ github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+ github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ultraware/funlen v0.1.0 h1:BuqclbkY6pO+cvxoq7OsktIXZpgBSkYTQtmwhAK81vI= github.com/ultraware/funlen v0.1.0/go.mod h1:XJqmOQja6DpxarLj6Jj1U7JuoS8PvL4nEqDaQhy22p4= -github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI= -github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= -github.com/uudashr/gocognit v1.0.7 h1:e9aFXgKgUJrQ5+bs61zBigmj7bFJ/5cC6HmMahVzuDo= -github.com/uudashr/gocognit v1.0.7/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY= +github.com/ultraware/whitespace v0.1.0 h1:O1HKYoh0kIeqE8sFqZf1o0qbORXUCOQFrlaQyZsczZw= +github.com/ultraware/whitespace v0.1.0/go.mod h1:/se4r3beMFNmewJ4Xmz0nMQ941GJt+qmSHGP9emHYe0= +github.com/uudashr/gocognit v1.1.2 h1:l6BAEKJqQH2UpKAPKdMfZf5kE4W/2xk8pfU1OVLvniI= +github.com/uudashr/gocognit v1.1.2/go.mod h1:aAVdLURqcanke8h3vg35BC++eseDm66Z7KmchI5et4k= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -github.com/xen0n/gosmopolitan v1.2.1 h1:3pttnTuFumELBRSh+KQs1zcz4fN6Zy7aB0xlnQSn1Iw= -github.com/xen0n/gosmopolitan v1.2.1/go.mod h1:JsHq/Brs1o050OOdmzHeOr0N7OtlnKRAGAsElF8xBQA= +github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= +github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o= github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= -github.com/ykadowak/zerologlint v0.1.3 h1:TLy1dTW3Nuc+YE3bYRPToG1Q9Ej78b5UUN6bjbGdxPE= -github.com/ykadowak/zerologlint v0.1.3/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= +github.com/ykadowak/zerologlint v0.1.5 h1:Gy/fMz1dFQN9JZTPjv1hxEk+sRWm05row04Yoolgdiw= +github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -636,30 +614,33 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -gitlab.com/bosi/decorder v0.4.0 h1:HWuxAhSxIvsITcXeP+iIRg9d1cVfvVkmlF7M68GaoDY= -gitlab.com/bosi/decorder v0.4.0/go.mod h1:xarnteyUoJiOTEldDysquWKTVDCKo2TOIOIibSuWqOg= -go-simpler.org/assert v0.6.0 h1:QxSrXa4oRuo/1eHMXSBFHKvJIpWABayzKldqZyugG7E= +gitlab.com/bosi/decorder v0.4.1 h1:VdsdfxhstabyhZovHafFw+9eJ6eU0d2CkFNJcZz/NU4= +gitlab.com/bosi/decorder v0.4.1/go.mod h1:jecSqWUew6Yle1pCr2eLWTensJMmsxHsBwt+PVbkAqA= +go-simpler.org/assert v0.7.0 h1:OzWWZqfNxt8cLS+MlUp6Tgk1HjPkmgdKBq9qvy8lZsA= +go-simpler.org/assert v0.7.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= +go-simpler.org/musttag v0.8.0 h1:DR4UTgetNNhPRNo02rkK1hwDTRzAPotN+ZqYpdtEwWc= +go-simpler.org/musttag v0.8.0/go.mod h1:fiNdCkXt2S6je9Eblma3okjnlva9NT1Eg/WUt19rWu8= +go-simpler.org/sloglint v0.4.0 h1:UVJuUJo63iNQNFEOtZ6o1xAgagVg/giVLLvG9nNLobI= +go-simpler.org/sloglint v0.4.0/go.mod h1:v6zJ++j/thFPhefs2wEXoCKwT10yo5nkBDYRCXyqgNQ= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/build-tools v0.11.0 h1:yXTgCJM/vxWZEB8FbgVhKOAFnRlacG2Z3eoTQZ0/gYE= -go.opentelemetry.io/build-tools v0.11.0/go.mod h1:GFpz8YD/DG5shfY1J2f3uuK88zr61U5rVRGOhKMDE9M= -go.opentelemetry.io/build-tools/checkfile v0.11.0 h1:Qtp1ZKj9jXwR9zL4/YEzRv7CmTajSPJwoTRrrZ24mpQ= -go.opentelemetry.io/build-tools/checkfile v0.11.0/go.mod h1:0Ql58QUUwr2jaQJSjFKkAFkT/Eent7eEOKiQ1+R+zvA= -go.opentelemetry.io/build-tools/chloggen v0.11.0 h1:PYbfjzw/4pHNfwH0kCAMolvmdorMVGxSSFY8A9097fw= -go.opentelemetry.io/build-tools/chloggen v0.11.0/go.mod h1:zuYbAo3TkrHo3C7lCrM5dHWSS50BDr0UfRYtyBFv2dQ= -go.opentelemetry.io/build-tools/crosslink v0.11.0 h1:K0eJY/AT6SiIaoJSrQyiVquGErcJEHsx4oHkhxvpj9k= -go.opentelemetry.io/build-tools/crosslink v0.11.0/go.mod h1:h5oxbHx+O50aO0/M7mFejZmd7cMONdsmmC+IOmgWoWw= -go.opentelemetry.io/build-tools/multimod v0.11.0 h1:QMo2Y4BlsTsWUR0LXV4gmiv5yEiX2iPLn2qAdAcCE6k= -go.opentelemetry.io/build-tools/multimod v0.11.0/go.mod h1:EID7sjEGyk1FWzRdsV6rlWp43IIn8iHXGE5pM4TytyQ= -go.opentelemetry.io/build-tools/semconvgen v0.11.0 h1:gQsNzy49l9JjNozybaRUl+vy0EMxYasV8w6aK+IWquc= -go.opentelemetry.io/build-tools/semconvgen v0.11.0/go.mod h1:Zy04Bw3w3lT7mORe23V2BwjfJYpoza6Xz1XSMIrLTCg= -go.tmz.dev/musttag v0.7.2 h1:1J6S9ipDbalBSODNT5jCep8dhZyMr4ttnjQagmGYR5s= -go.tmz.dev/musttag v0.7.2/go.mod h1:m6q5NiiSKMnQYokefa2xGoyoXnrswCbJ0AWYzf4Zs28= +go.opentelemetry.io/build-tools v0.12.0 h1:ZqK1GuqBp9Mf1RthYO3/jjf9tPWzeHMcVDo0itFi/lI= +go.opentelemetry.io/build-tools v0.12.0/go.mod h1:I76Qvv9cN055XJfTHw9t257EUd5Yp0EofeTMESlZuRU= +go.opentelemetry.io/build-tools/checkfile v0.12.0 h1:1g3iBxjPuack0pEvqkTiEcyh0uJvKXkQg8IMJkhiFX0= +go.opentelemetry.io/build-tools/checkfile v0.12.0/go.mod h1:0Ql58QUUwr2jaQJSjFKkAFkT/Eent7eEOKiQ1+R+zvA= +go.opentelemetry.io/build-tools/chloggen v0.12.0 h1:BFj/1bNIGxOs1GykGjhV4gycz1nqVWI/xVDUaVfNibw= +go.opentelemetry.io/build-tools/chloggen v0.12.0/go.mod h1:zuYbAo3TkrHo3C7lCrM5dHWSS50BDr0UfRYtyBFv2dQ= +go.opentelemetry.io/build-tools/crosslink v0.12.1-0.20240121161735-d70c842b1bf5 h1:3XxFDNe5QBv6qPqUJK/ihejuTpJfCPSFyoJuP8DHKew= +go.opentelemetry.io/build-tools/crosslink v0.12.1-0.20240121161735-d70c842b1bf5/go.mod h1:pHYd1joKyVZPA5sf6gOrbzfbY8VFDiXFp0fVi68whAU= +go.opentelemetry.io/build-tools/multimod v0.12.0 h1:DKi+A+4EaKrOZDTNDDZz3ijiAduEQDo8j1rzWUaGUHo= +go.opentelemetry.io/build-tools/multimod v0.12.0/go.mod h1:w03q3WgZs7reoBNnmfdClkKdTIA/IHM8ric5E2jEDD0= +go.opentelemetry.io/build-tools/semconvgen v0.12.0 h1:AsjYFwo8sSLAjwjklj+yVwm2xogJUxRf5pxflATg9N0= +go.opentelemetry.io/build-tools/semconvgen v0.12.0/go.mod h1:SRmou8pp+7gBmf1AvdxOTwVts74Syyrgm1/Qx7R8mis= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= @@ -670,15 +651,13 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -689,12 +668,12 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230711023510-fffb14384f22 h1:FqrVOBQxQ8r/UwwXibI0KMolVhvFiGobSfdE33deHJM= -golang.org/x/exp v0.0.0-20230711023510-fffb14384f22/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 h1:jWGQJV4niP+CCmFW9ekjA9Zx8vYORzOUH2/Nl5WPuLQ= -golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20231219180239-dc181d75b848 h1:UhRVJ0i7bF9n/Hd8YjW3eKjlPVBHzbQdxrBgjbSKl64= +golang.org/x/exp/typeparams v0.0.0-20231219180239-dc181d75b848/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -707,7 +686,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -716,7 +694,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= @@ -725,8 +702,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -756,9 +733,6 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -770,17 +744,13 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -795,8 +765,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -829,17 +799,12 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -851,15 +816,14 @@ golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -867,21 +831,21 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -932,14 +896,8 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= @@ -953,16 +911,14 @@ golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/vuln v1.0.1 h1:KUas02EjQK5LTuIx1OylBQdKKZ9jeugs+HiqO5HormU= -golang.org/x/vuln v1.0.1/go.mod h1:bb2hMwln/tqxg32BNY4CcxHWtHXuYa3SbIBmtsyjxtM= +golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +golang.org/x/vuln v1.0.4 h1:SP0mPeg2PmGCu03V+61EcQiOjmpri2XijexKdzv8Z1I= +golang.org/x/vuln v1.0.4/go.mod h1:NbJdUQhX8jY++FtuhrXs2Eyx0yePo9pF7nPlIjo9aaQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -979,16 +935,12 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1018,13 +970,6 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1037,10 +982,6 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1064,8 +1005,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 h1:6D+BvnJ/j6e222UW8s2qTSe3wGBtvo0MbVQG/c5k8RE= -gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1085,16 +1024,16 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.4.5 h1:YGD4H+SuIOOqsyoLOpZDWcieM28W47/zRO7f+9V3nvo= -honnef.co/go/tools v0.4.5/go.mod h1:GUV+uIBCLpdf0/v6UhHHG/yzI/z6qPskBeQCjcNB96k= -mvdan.cc/gofumpt v0.5.0 h1:0EQ+Z56k8tXjj/6TQD25BFNKQXpCvT0rnansIc7Ug5E= -mvdan.cc/gofumpt v0.5.0/go.mod h1:HBeVDtMKRZpXyxFciAirzdKklDlGu8aAy1wEbH5Y9js= +honnef.co/go/tools v0.4.6 h1:oFEHCKeID7to/3autwsWfnuv69j3NsfcXbvJKuIcep8= +honnef.co/go/tools v0.4.6/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0= +mvdan.cc/gofumpt v0.6.0 h1:G3QvahNDmpD+Aek/bNOLrFR2XC6ZAdo62dZu65gmwGo= +mvdan.cc/gofumpt v0.6.0/go.mod h1:4L0wf+kgIPZtcCWXynNS2e6bhmj73umwnuXSZarixzA= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= -mvdan.cc/unparam v0.0.0-20230312165513-e84e2d14e3b8 h1:VuJo4Mt0EVPychre4fNlDWDuE5AjXtPJpRUWqZDQhaI= -mvdan.cc/unparam v0.0.0-20230312165513-e84e2d14e3b8/go.mod h1:Oh/d7dEtzsNHGOq1Cdv8aMm3KdKhVvPbRQcM8WFpBR8= +mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14 h1:zCr3iRRgdk5eIikZNDphGcM6KGVTx3Yu+/Uu9Es254w= +mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14/go.mod h1:ZzZjEpJDOmx8TdVU6umamY3Xy0UAQUI2DHbf05USVbI= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/internal/tools/jsonschema_patch.sed b/internal/tools/jsonschema_patch.sed deleted file mode 100644 index 04090d912d0..00000000000 --- a/internal/tools/jsonschema_patch.sed +++ /dev/null @@ -1,4 +0,0 @@ -# go-jsonschema always generates patternProperties as -# map[string]interface{}, for more specific types, they must -# be replaced here -s+type Headers.*+type Headers map[string]string+g \ No newline at end of file diff --git a/internal/tools/semconvkit/main.go b/internal/tools/semconvkit/main.go new file mode 100644 index 00000000000..2dc73c37c05 --- /dev/null +++ b/internal/tools/semconvkit/main.go @@ -0,0 +1,70 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "embed" + "flag" + "log" + "os" + "path/filepath" + "strings" + "text/template" +) + +var ( + out = flag.String("output", "./", "output directory") + tag = flag.String("tag", "", "OpenTelemetry tagged version") + + //go:embed templates/*.tmpl + rootFS embed.FS +) + +// SemanticConventions are information about the semantic conventions being +// generated. +type SemanticConventions struct { + // TagVer is the tagged version (i.e. v1.7.0 and not 1.7.0). + TagVer string +} + +func (sc SemanticConventions) SemVer() string { + return strings.TrimPrefix(*tag, "v") +} + +// render renders all templates to the dest directory using the data. +func render(src, dest string, data *SemanticConventions) error { + tmpls, err := template.ParseFS(rootFS, src) + if err != nil { + return err + } + for _, tmpl := range tmpls.Templates() { + target := filepath.Join(dest, strings.TrimSuffix(tmpl.Name(), ".tmpl")) + // nolint: gosec + wr, err := os.Create(target) + if err != nil { + return err + } + + err = tmpl.Execute(wr, data) + if err != nil { + return err + } + } + + return nil +} + +func main() { + flag.Parse() + + if *tag == "" { + log.Fatalf("invalid tag: %q", *tag) + } + + sc := &SemanticConventions{TagVer: *tag} + + if err := render("templates/*.tmpl", *out, sc); err != nil { + log.Fatal(err) + } +} diff --git a/internal/tools/semconvkit/templates/doc.go.tmpl b/internal/tools/semconvkit/templates/doc.go.tmpl new file mode 100644 index 00000000000..0085e604fae --- /dev/null +++ b/internal/tools/semconvkit/templates/doc.go.tmpl @@ -0,0 +1,9 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package semconv implements OpenTelemetry semantic conventions. +// +// OpenTelemetry semantic conventions are agreed standardized naming +// patterns for OpenTelemetry things. This package represents the {{.TagVer}} +// version of the OpenTelemetry semantic conventions. +package semconv // import "go.opentelemetry.io/collector/semconv/{{.TagVer}}" diff --git a/internal/tools/semconvkit/templates/schema.go.tmpl b/internal/tools/semconvkit/templates/schema.go.tmpl new file mode 100644 index 00000000000..41006fa206b --- /dev/null +++ b/internal/tools/semconvkit/templates/schema.go.tmpl @@ -0,0 +1,9 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package semconv // import "go.opentelemetry.io/collector/semconv/{{.TagVer}}" + +// SchemaURL is the schema URL that matches the version of the semantic conventions +// that this package defines. Semconv packages starting from v1.4.0 must declare +// non-empty schema URL in the form https://opentelemetry.io/schemas/ +const SchemaURL = "https://opentelemetry.io/schemas/{{.SemVer}}" diff --git a/internal/tools/tools.go b/internal/tools/tools.go index 1cc59069724..06f143c3701 100644 --- a/internal/tools/tools.go +++ b/internal/tools/tools.go @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 //go:build tools -// +build tools package tools // import "go.opentelemetry.io/collector/internal/tools" @@ -13,12 +12,10 @@ package tools // import "go.opentelemetry.io/collector/internal/tools" import ( _ "github.com/a8m/envsubst/cmd/envsubst" - _ "github.com/atombender/go-jsonschema/cmd/gojsonschema" _ "github.com/client9/misspell/cmd/misspell" _ "github.com/golangci/golangci-lint/cmd/golangci-lint" _ "github.com/google/addlicense" _ "github.com/jcchavezs/porto/cmd/porto" - _ "github.com/mikefarah/yq/v4" _ "github.com/pavius/impi/cmd/impi" _ "go.opentelemetry.io/build-tools/checkfile" _ "go.opentelemetry.io/build-tools/chloggen" @@ -28,4 +25,6 @@ import ( _ "golang.org/x/exp/cmd/apidiff" _ "golang.org/x/tools/cmd/goimports" _ "golang.org/x/vuln/cmd/govulncheck" + + _ "go.opentelemetry.io/collector/internal/tools/semconvkit" ) diff --git a/obsreport/obsreport_exporter.go b/obsreport/obsreport_exporter.go deleted file mode 100644 index acbbedf9f5a..00000000000 --- a/obsreport/obsreport_exporter.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package obsreport // import "go.opentelemetry.io/collector/obsreport" - -import "go.opentelemetry.io/collector/exporter/exporterhelper" - -// Exporter is a helper to add observability to an exporter. -// -// Deprecated: [0.85.0] Use exporterhelper.ObsReport instead. -type Exporter = exporterhelper.ObsReport - -// ExporterSettings are settings for creating an Exporter. -// -// Deprecated: [0.85.0] Use exporterhelper.ObsReportSettings instead. -type ExporterSettings = exporterhelper.ObsReportSettings - -// NewExporter creates a new Exporter. -// -// Deprecated: [0.85.0] Use exporterhelper.New instead. -func NewExporter(cfg ExporterSettings) (*exporterhelper.ObsReport, error) { - return exporterhelper.NewObsReport(cfg) -} diff --git a/obsreport/obsreport_processor.go b/obsreport/obsreport_processor.go deleted file mode 100644 index 95915200f6a..00000000000 --- a/obsreport/obsreport_processor.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package obsreport // import "go.opentelemetry.io/collector/obsreport" - -import ( - "go.opentelemetry.io/collector/processor/processorhelper" -) - -// BuildProcessorCustomMetricName is used to be build a metric name following -// the standards used in the Collector. The configType should be the same -// value used to identify the type on the config. -// -// Deprecated: [0.85.0] Use processorhelper.BuildCustomMetricName instead. -func BuildProcessorCustomMetricName(configType, metric string) string { - return processorhelper.BuildCustomMetricName(configType, metric) -} - -// Processor is a helper to add observability to a processor. -// -// Deprecated: [0.85.0] Use processorhelper.ObsReport instead. -type Processor = processorhelper.ObsReport - -// ProcessorSettings is a helper to add observability to a processor. -// -// Deprecated: [0.85.0] Use processorhelper.ObsReportSettings instead. -type ProcessorSettings = processorhelper.ObsReportSettings - -// NewProcessor creates a new Processor. -// -// Deprecated: [0.85.0] Use processorhelper.NewObsReport instead. -func NewProcessor(cfg ProcessorSettings) (*Processor, error) { - return processorhelper.NewObsReport(cfg) -} diff --git a/obsreport/obsreport_receiver.go b/obsreport/obsreport_receiver.go deleted file mode 100644 index e816434d895..00000000000 --- a/obsreport/obsreport_receiver.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package obsreport // import "go.opentelemetry.io/collector/obsreport" - -import "go.opentelemetry.io/collector/receiver/receiverhelper" - -// Receiver is a helper to add observability to a receiver. -// -// Deprecated: [0.85.0] Use receiverhelper.ObsReport instead. -type Receiver = receiverhelper.ObsReport - -// ReceiverSettings are settings for creating an Receiver. -// -// Deprecated: [0.85.0] Use receiverhelper.ObsReportSettings instead. -type ReceiverSettings = receiverhelper.ObsReportSettings - -// NewReceiver creates a new Receiver. -// -// Deprecated: [0.85.0] Use receiverhelper.NewObsReport instead. -func NewReceiver(cfg ReceiverSettings) (*Receiver, error) { - return receiverhelper.NewObsReport(cfg) -} diff --git a/obsreport/obsreport_scraper.go b/obsreport/obsreport_scraper.go deleted file mode 100644 index f6ae510b20f..00000000000 --- a/obsreport/obsreport_scraper.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package obsreport // import "go.opentelemetry.io/collector/obsreport" - -import "go.opentelemetry.io/collector/receiver/scraperhelper" - -// Scraper is a helper to add observability to a scraper. -// -// Deprecated: [0.85.0] Use scraperhelper.ObsReport instead. -type Scraper = scraperhelper.ObsReport - -// ScraperSettings are settings for creating a Scraper. -// -// Deprecated: [0.85.0] Use scraperhelper.ObsReportSettings instead. -type ScraperSettings = scraperhelper.ObsReportSettings - -// NewScraper creates a new Scraper. -// -// Deprecated: [0.85.0] Use scraperhelper.NewObsReport instead. -func NewScraper(cfg ScraperSettings) (*Scraper, error) { - return scraperhelper.NewObsReport(cfg) -} diff --git a/obsreport/obsreporttest/deprecated.go b/obsreport/obsreporttest/deprecated.go new file mode 100644 index 00000000000..b822191ee4e --- /dev/null +++ b/obsreport/obsreporttest/deprecated.go @@ -0,0 +1,29 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package obsreporttest // import "go.opentelemetry.io/collector/obsreport/obsreporttest" + +import ( + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" +) + +// Deprecated: [0.93.0] Use componenttest.TestTelemetry instead +type TestTelemetry = componenttest.TestTelemetry + +// SetupTelemetry does setup the testing environment to check the metrics recorded by receivers, producers or exporters. +// The caller must pass the ID of the component that intends to test, so the CreateSettings and Check methods will use. +// The caller should defer a call to Shutdown the returned TestTelemetry. +// +// Deprecated: [0.93.0] Use componenttest.SetupTelemetry instead +func SetupTelemetry(id component.ID) (TestTelemetry, error) { + return componenttest.SetupTelemetry(id) +} + +// CheckScraperMetrics checks that for the current exported values for metrics scraper metrics match given values. +// When this function is called it is required to also call SetupTelemetry as first thing. +// +// Deprecated: [0.93.0] Use TestTelemetry.CheckScraperMetrics instead +func CheckScraperMetrics(tts TestTelemetry, receiver component.ID, scraper component.ID, scrapedMetricPoints, erroredMetricPoints int64) error { + return tts.CheckScraperMetrics(receiver, scraper, scrapedMetricPoints, erroredMetricPoints) +} diff --git a/obsreport/obsreporttest/obsreporttest_test.go b/obsreport/obsreporttest/obsreporttest_test.go deleted file mode 100644 index bfc4256f8f6..00000000000 --- a/obsreport/obsreporttest/obsreporttest_test.go +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package obsreporttest_test - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/exporter/exporterhelper" - "go.opentelemetry.io/collector/exporter/exportertest" - "go.opentelemetry.io/collector/obsreport/obsreporttest" - "go.opentelemetry.io/collector/processor/processorhelper" - "go.opentelemetry.io/collector/processor/processortest" - "go.opentelemetry.io/collector/receiver/receiverhelper" - "go.opentelemetry.io/collector/receiver/receivertest" - "go.opentelemetry.io/collector/receiver/scraperhelper" -) - -const ( - transport = "fakeTransport" - format = "fakeFormat" -) - -var ( - scraper = component.NewID("fakeScraper") - receiver = component.NewID("fakeReicever") - processor = component.NewID("fakeProcessor") - exporter = component.NewID("fakeExporter") -) - -func TestCheckScraperMetricsViews(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(receiver) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - s, err := scraperhelper.NewObsReport(scraperhelper.ObsReportSettings{ - ReceiverID: receiver, - Scraper: scraper, - ReceiverCreateSettings: receivertest.NewCreateSettings(receiver, tt.TelemetrySettings), - }) - require.NoError(t, err) - ctx := s.StartMetricsOp(context.Background()) - require.NotNil(t, ctx) - s.EndMetricsOp(ctx, 7, nil) - - assert.NoError(t, obsreporttest.CheckScraperMetrics(tt, receiver, scraper, 7, 0)) - assert.Error(t, obsreporttest.CheckScraperMetrics(tt, receiver, scraper, 7, 7)) - assert.Error(t, obsreporttest.CheckScraperMetrics(tt, receiver, scraper, 0, 0)) - assert.Error(t, obsreporttest.CheckScraperMetrics(tt, receiver, scraper, 0, 7)) -} - -func TestCheckReceiverTracesViews(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(receiver) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - rec, err := receiverhelper.NewObsReport(receiverhelper.ObsReportSettings{ - ReceiverID: receiver, - Transport: transport, - ReceiverCreateSettings: receivertest.NewCreateSettings(receiver, tt.TelemetrySettings), - }) - require.NoError(t, err) - ctx := rec.StartTracesOp(context.Background()) - require.NotNil(t, ctx) - rec.EndTracesOp(ctx, format, 7, nil) - - assert.NoError(t, tt.CheckReceiverTraces(transport, 7, 0)) - assert.Error(t, tt.CheckReceiverTraces(transport, 7, 7)) - assert.Error(t, tt.CheckReceiverTraces(transport, 0, 0)) - assert.Error(t, tt.CheckReceiverTraces(transport, 0, 7)) -} - -func TestCheckReceiverMetricsViews(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(receiver) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - rec, err := receiverhelper.NewObsReport(receiverhelper.ObsReportSettings{ - ReceiverID: receiver, - Transport: transport, - ReceiverCreateSettings: receivertest.NewCreateSettings(receiver, tt.TelemetrySettings), - }) - require.NoError(t, err) - ctx := rec.StartMetricsOp(context.Background()) - require.NotNil(t, ctx) - rec.EndMetricsOp(ctx, format, 7, nil) - - assert.NoError(t, tt.CheckReceiverMetrics(transport, 7, 0)) - assert.Error(t, tt.CheckReceiverMetrics(transport, 7, 7)) - assert.Error(t, tt.CheckReceiverMetrics(transport, 0, 0)) - assert.Error(t, tt.CheckReceiverMetrics(transport, 0, 7)) -} - -func TestCheckReceiverLogsViews(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(receiver) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - rec, err := receiverhelper.NewObsReport(receiverhelper.ObsReportSettings{ - ReceiverID: receiver, - Transport: transport, - ReceiverCreateSettings: receivertest.NewCreateSettings(receiver, tt.TelemetrySettings), - }) - require.NoError(t, err) - ctx := rec.StartLogsOp(context.Background()) - require.NotNil(t, ctx) - rec.EndLogsOp(ctx, format, 7, nil) - - assert.NoError(t, tt.CheckReceiverLogs(transport, 7, 0)) - assert.Error(t, tt.CheckReceiverLogs(transport, 7, 7)) - assert.Error(t, tt.CheckReceiverLogs(transport, 0, 0)) - assert.Error(t, tt.CheckReceiverLogs(transport, 0, 7)) -} - -func TestCheckProcessorTracesViews(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(processor) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - por, err := processorhelper.NewObsReport(processorhelper.ObsReportSettings{ - ProcessorID: processor, - ProcessorCreateSettings: processortest.NewCreateSettings(processor, tt.TelemetrySettings), - }) - assert.NoError(t, err) - - por.TracesAccepted(context.Background(), 7) - por.TracesRefused(context.Background(), 8) - por.TracesDropped(context.Background(), 9) - - assert.NoError(t, tt.CheckProcessorTraces(7, 8, 9)) - assert.Error(t, tt.CheckProcessorTraces(0, 0, 0)) - assert.Error(t, tt.CheckProcessorTraces(7, 0, 0)) - assert.Error(t, tt.CheckProcessorTraces(7, 8, 0)) - assert.Error(t, tt.CheckProcessorTraces(7, 0, 9)) - assert.Error(t, tt.CheckProcessorTraces(0, 8, 0)) - assert.Error(t, tt.CheckProcessorTraces(0, 8, 9)) - assert.Error(t, tt.CheckProcessorTraces(0, 0, 9)) -} - -func TestCheckProcessorMetricsViews(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(processor) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - por, err := processorhelper.NewObsReport(processorhelper.ObsReportSettings{ - ProcessorID: processor, - ProcessorCreateSettings: processortest.NewCreateSettings(processor, tt.TelemetrySettings), - }) - assert.NoError(t, err) - - por.MetricsAccepted(context.Background(), 7) - por.MetricsRefused(context.Background(), 8) - por.MetricsDropped(context.Background(), 9) - - assert.NoError(t, tt.CheckProcessorMetrics(7, 8, 9)) - assert.Error(t, tt.CheckProcessorMetrics(0, 0, 0)) - assert.Error(t, tt.CheckProcessorMetrics(7, 0, 0)) - assert.Error(t, tt.CheckProcessorMetrics(7, 8, 0)) - assert.Error(t, tt.CheckProcessorMetrics(7, 0, 9)) - assert.Error(t, tt.CheckProcessorMetrics(0, 8, 0)) - assert.Error(t, tt.CheckProcessorMetrics(0, 8, 9)) - assert.Error(t, tt.CheckProcessorMetrics(0, 0, 9)) -} - -func TestCheckProcessorLogViews(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(processor) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - por, err := processorhelper.NewObsReport(processorhelper.ObsReportSettings{ - ProcessorID: processor, - ProcessorCreateSettings: processortest.NewCreateSettings(processor, tt.TelemetrySettings), - }) - assert.NoError(t, err) - - por.LogsAccepted(context.Background(), 7) - por.LogsRefused(context.Background(), 8) - por.LogsDropped(context.Background(), 9) - - assert.NoError(t, tt.CheckProcessorLogs(7, 8, 9)) - assert.Error(t, tt.CheckProcessorLogs(0, 0, 0)) - assert.Error(t, tt.CheckProcessorLogs(7, 0, 0)) - assert.Error(t, tt.CheckProcessorLogs(7, 8, 0)) - assert.Error(t, tt.CheckProcessorLogs(7, 0, 9)) - assert.Error(t, tt.CheckProcessorLogs(0, 8, 0)) - assert.Error(t, tt.CheckProcessorLogs(0, 8, 9)) - assert.Error(t, tt.CheckProcessorLogs(0, 0, 9)) -} - -func TestCheckExporterTracesViews(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(exporter) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - obsrep, err := exporterhelper.NewObsReport(exporterhelper.ObsReportSettings{ - ExporterID: exporter, - ExporterCreateSettings: exportertest.NewCreateSettings(exporter, tt.TelemetrySettings), - }) - require.NoError(t, err) - ctx := obsrep.StartTracesOp(context.Background()) - require.NotNil(t, ctx) - obsrep.EndTracesOp(ctx, 7, nil) - - assert.NoError(t, tt.CheckExporterTraces(7, 0)) - assert.Error(t, tt.CheckExporterTraces(7, 7)) - assert.Error(t, tt.CheckExporterTraces(0, 0)) - assert.Error(t, tt.CheckExporterTraces(0, 7)) -} - -func TestCheckExporterMetricsViews(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(exporter) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - obsrep, err := exporterhelper.NewObsReport(exporterhelper.ObsReportSettings{ - ExporterID: exporter, - ExporterCreateSettings: exportertest.NewCreateSettings(exporter, tt.TelemetrySettings), - }) - require.NoError(t, err) - ctx := obsrep.StartMetricsOp(context.Background()) - require.NotNil(t, ctx) - obsrep.EndMetricsOp(ctx, 7, nil) - - assert.NoError(t, tt.CheckExporterMetrics(7, 0)) - assert.Error(t, tt.CheckExporterMetrics(7, 7)) - assert.Error(t, tt.CheckExporterMetrics(0, 0)) - assert.Error(t, tt.CheckExporterMetrics(0, 7)) -} - -func TestCheckExporterLogsViews(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(exporter) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - - obsrep, err := exporterhelper.NewObsReport(exporterhelper.ObsReportSettings{ - ExporterID: exporter, - ExporterCreateSettings: exportertest.NewCreateSettings(exporter, tt.TelemetrySettings), - }) - require.NoError(t, err) - ctx := obsrep.StartLogsOp(context.Background()) - require.NotNil(t, ctx) - obsrep.EndLogsOp(ctx, 7, nil) - - assert.NoError(t, tt.CheckExporterLogs(7, 0)) - assert.Error(t, tt.CheckExporterLogs(7, 7)) - assert.Error(t, tt.CheckExporterLogs(0, 0)) - assert.Error(t, tt.CheckExporterLogs(0, 7)) -} diff --git a/obsreport/obsreporttest/package_test.go b/obsreport/obsreporttest/package_test.go new file mode 100644 index 00000000000..97b3f7f9210 --- /dev/null +++ b/obsreport/obsreporttest/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package obsreporttest + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/otelcol/collector.go b/otelcol/collector.go index 557ff6f18aa..3fd5cb2ca31 100644 --- a/otelcol/collector.go +++ b/otelcol/collector.go @@ -7,7 +7,6 @@ package otelcol // import "go.opentelemetry.io/collector/otelcol" import ( "context" - "errors" "fmt" "os" "os/signal" @@ -55,7 +54,7 @@ func (s State) String() string { // CollectorSettings holds configuration for creating a new Collector. type CollectorSettings struct { // Factories service factories. - Factories Factories + Factories func() (Factories, error) // BuildInfo provides collector start information. BuildInfo component.BuildInfo @@ -66,10 +65,16 @@ type CollectorSettings struct { // and manually handle the signals to shutdown the collector. DisableGracefulShutdown bool + // Deprecated: [v0.95.0] Use ConfigProviderSettings instead. // ConfigProvider provides the service configuration. // If the provider watches for configuration change, collector may reload the new configuration upon changes. ConfigProvider ConfigProvider + // ConfigProviderSettings allows configuring the way the Collector retrieves its configuration + // The Collector will reload based on configuration changes from the ConfigProvider if any + // confmap.Providers watch for configuration changes. + ConfigProviderSettings ConfigProviderSettings + // LoggingOptions provides a way to change behavior of zap logging. LoggingOptions []zap.Option @@ -92,6 +97,8 @@ type CollectorSettings struct { type Collector struct { set CollectorSettings + configProvider ConfigProvider + service *service.Service state *atomic.Int32 @@ -105,8 +112,14 @@ type Collector struct { // NewCollector creates and returns a new instance of Collector. func NewCollector(set CollectorSettings) (*Collector, error) { - if set.ConfigProvider == nil { - return nil, errors.New("invalid nil config provider") + var err error + configProvider := set.ConfigProvider + + if configProvider == nil { + configProvider, err = NewConfigProvider(set.ConfigProviderSettings) + if err != nil { + return nil, err + } } state := &atomic.Int32{} @@ -119,6 +132,7 @@ func NewCollector(set CollectorSettings) (*Collector, error) { // the number of signals getting notified on is recommended. signalsChannel: make(chan os.Signal, 3), asyncErrorChannel: make(chan error), + configProvider: configProvider, }, nil } @@ -146,7 +160,7 @@ func (col *Collector) setupConfigurationComponents(ctx context.Context) error { var conf *confmap.Conf - if cp, ok := col.set.ConfigProvider.(ConfmapProvider); ok { + if cp, ok := col.configProvider.(ConfmapProvider); ok { var err error conf, err = cp.GetConfmap(ctx) @@ -155,7 +169,11 @@ func (col *Collector) setupConfigurationComponents(ctx context.Context) error { } } - cfg, err := col.set.ConfigProvider.Get(ctx, col.set.Factories) + factories, err := col.set.Factories() + if err != nil { + return fmt.Errorf("failed to initialize factories: %w", err) + } + cfg, err := col.configProvider.Get(ctx, factories) if err != nil { return fmt.Errorf("failed to get config: %w", err) } @@ -167,11 +185,11 @@ func (col *Collector) setupConfigurationComponents(ctx context.Context) error { col.service, err = service.New(ctx, service.Settings{ BuildInfo: col.set.BuildInfo, CollectorConf: conf, - Receivers: receiver.NewBuilder(cfg.Receivers, col.set.Factories.Receivers), - Processors: processor.NewBuilder(cfg.Processors, col.set.Factories.Processors), - Exporters: exporter.NewBuilder(cfg.Exporters, col.set.Factories.Exporters), - Connectors: connector.NewBuilder(cfg.Connectors, col.set.Factories.Connectors), - Extensions: extension.NewBuilder(cfg.Extensions, col.set.Factories.Extensions), + Receivers: receiver.NewBuilder(cfg.Receivers, factories.Receivers), + Processors: processor.NewBuilder(cfg.Processors, factories.Processors), + Exporters: exporter.NewBuilder(cfg.Exporters, factories.Exporters), + Connectors: connector.NewBuilder(cfg.Connectors, factories.Connectors), + Extensions: extension.NewBuilder(cfg.Extensions, factories.Extensions), AsyncErrorChannel: col.asyncErrorChannel, LoggingOptions: col.set.LoggingOptions, }, cfg.Service) @@ -207,7 +225,11 @@ func (col *Collector) reloadConfiguration(ctx context.Context) error { } func (col *Collector) DryRun(ctx context.Context) error { - cfg, err := col.set.ConfigProvider.Get(ctx, col.set.Factories) + factories, err := col.set.Factories() + if err != nil { + return fmt.Errorf("failed to initialize factories: %w", err) + } + cfg, err := col.configProvider.Get(ctx, factories) if err != nil { return fmt.Errorf("failed to get config: %w", err) } @@ -235,7 +257,7 @@ func (col *Collector) Run(ctx context.Context) error { LOOP: for { select { - case err := <-col.set.ConfigProvider.Watch(): + case err := <-col.configProvider.Watch(): if err != nil { col.service.Logger().Error("Config watch failed", zap.Error(err)) break LOOP @@ -272,7 +294,7 @@ func (col *Collector) shutdown(ctx context.Context) error { // Accumulate errors and proceed with shutting down remaining components. var errs error - if err := col.set.ConfigProvider.Shutdown(ctx); err != nil { + if err := col.configProvider.Shutdown(ctx); err != nil { errs = multierr.Append(errs, fmt.Errorf("failed to shutdown config provider: %w", err)) } diff --git a/otelcol/collector_test.go b/otelcol/collector_test.go index 1a0ad8d0607..c56d56fc728 100644 --- a/otelcol/collector_test.go +++ b/otelcol/collector_test.go @@ -18,7 +18,8 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/confmap" - "go.opentelemetry.io/collector/confmap/converter/expandconverter" + "go.opentelemetry.io/collector/extension/extensiontest" + "go.opentelemetry.io/collector/processor/processortest" ) func TestStateString(t *testing.T) { @@ -30,16 +31,10 @@ func TestStateString(t *testing.T) { } func TestCollectorStartAsGoRoutine(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) - require.NoError(t, err) - set := CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: cfgProvider, + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")}), } col, err := NewCollector(set) require.NoError(t, err) @@ -57,16 +52,10 @@ func TestCollectorStartAsGoRoutine(t *testing.T) { } func TestCollectorCancelContext(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) - require.NoError(t, err) - set := CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: cfgProvider, + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")}), } col, err := NewCollector(set) require.NoError(t, err) @@ -93,16 +82,13 @@ func (p mockCfgProvider) Watch() <-chan error { } func TestCollectorStateAfterConfigChange(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - provider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) require.NoError(t, err) watcher := make(chan error, 1) col, err := NewCollector(CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: &mockCfgProvider{ConfigProvider: provider, watcher: watcher}, }) require.NoError(t, err) @@ -126,16 +112,10 @@ func TestCollectorStateAfterConfigChange(t *testing.T) { } func TestCollectorReportError(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) - require.NoError(t, err) - col, err := NewCollector(CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: cfgProvider, + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")}), }) require.NoError(t, err) @@ -151,17 +131,104 @@ func TestCollectorReportError(t *testing.T) { assert.Equal(t, StateClosed, col.GetState()) } -func TestCollectorSendSignal(t *testing.T) { +func TestComponentStatusWatcher(t *testing.T) { factories, err := nopFactories() - require.NoError(t, err) + assert.NoError(t, err) + + // Use a processor factory that creates "unhealthy" processor: one that + // always reports StatusRecoverableError after successful Start. + unhealthyProcessorFactory := processortest.NewUnhealthyProcessorFactory() + factories.Processors[unhealthyProcessorFactory.Type()] = unhealthyProcessorFactory + + // Keep track of all status changes in a map. + changedComponents := map[*component.InstanceID][]component.Status{} + var mux sync.Mutex + onStatusChanged := func(source *component.InstanceID, event *component.StatusEvent) { + if source.ID.Type() != unhealthyProcessorFactory.Type() { + return + } + mux.Lock() + defer mux.Unlock() + changedComponents[source] = append(changedComponents[source], event.Status()) + } - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) + // Add a "statuswatcher" extension that will receive notifications when processor + // status changes. + factory := extensiontest.NewStatusWatcherExtensionFactory(onStatusChanged) + factories.Extensions[factory.Type()] = factory + + // Read config from file. This config uses 3 "unhealthy" processors. + validProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-statuswatcher.yaml")})) require.NoError(t, err) + // Create a collector col, err := NewCollector(CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: cfgProvider, + Factories: func() (Factories, error) { return factories, nil }, + ConfigProvider: validProvider, + }) + require.NoError(t, err) + + // Start the newly created collector. + wg := startCollector(context.Background(), t, col) + + // An unhealthy processor asynchronously reports a recoverable error. Depending on the Go + // Scheduler the statuses reported at startup will be one of the two valid sequnces below. + startupStatuses1 := []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusRecoverableError, + } + startupStatuses2 := []component.Status{ + component.StatusStarting, + component.StatusRecoverableError, + } + // the modulus of the actual statuses will match the modulus of the startup statuses + startupStatuses := func(actualStatuses []component.Status) []component.Status { + if len(actualStatuses)%2 == 1 { + return startupStatuses1 + } + return startupStatuses2 + } + + // The "unhealthy" processors will now begin to asynchronously report StatusRecoverableError. + // We expect to see these reports. + assert.Eventually(t, func() bool { + mux.Lock() + defer mux.Unlock() + + for k, v := range changedComponents { + // All processors must report a status change with the same ID + assert.EqualValues(t, component.NewID(unhealthyProcessorFactory.Type()), k.ID) + // And all must have a valid startup sequence + assert.Equal(t, startupStatuses(v), v) + } + // We have 3 processors with exactly the same ID in otelcol-statuswatcher.yaml + // We must have exactly 3 items in our map. This ensures that the "source" argument + // passed to status change func is unique per instance of source component despite + // components having the same IDs (having same ID for different component instances + // is a normal situation for processors). + return len(changedComponents) == 3 + }, 2*time.Second, time.Millisecond*100) + + col.Shutdown() + wg.Wait() + + // Check for additional statuses after Shutdown. + for _, v := range changedComponents { + expectedStatuses := append([]component.Status{}, startupStatuses(v)...) + expectedStatuses = append(expectedStatuses, component.StatusStopping, component.StatusStopped) + assert.Equal(t, expectedStatuses, v) + } + + assert.Equal(t, StateClosed, col.GetState()) +} + +func TestCollectorSendSignal(t *testing.T) { + col, err := NewCollector(CollectorSettings{ + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")}), }) require.NoError(t, err) @@ -185,16 +252,11 @@ func TestCollectorSendSignal(t *testing.T) { func TestCollectorFailedShutdown(t *testing.T) { t.Skip("This test was using telemetry shutdown failure, switch to use a component that errors on shutdown.") - factories, err := nopFactories() - require.NoError(t, err) - - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) - require.NoError(t, err) col, err := NewCollector(CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: cfgProvider, + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")}), }) require.NoError(t, err) @@ -216,19 +278,49 @@ func TestCollectorFailedShutdown(t *testing.T) { } func TestCollectorStartInvalidConfig(t *testing.T) { - factories, err := nopFactories() + col, err := NewCollector(CollectorSettings{ + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-invalid.yaml")}), + }) require.NoError(t, err) + assert.Error(t, col.Run(context.Background())) +} - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-invalid.yaml")})) - require.NoError(t, err) +func TestNewCollectorInvalidConfigProviderSettings(t *testing.T) { + _, err := NewCollector(CollectorSettings{ + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: ConfigProviderSettings{}, + }) + require.Error(t, err) +} + +func TestNewCollectorUseConfig(t *testing.T) { + set := newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")}) col, err := NewCollector(CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: cfgProvider, + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: set, }) require.NoError(t, err) - assert.Error(t, col.Run(context.Background())) + require.NotNil(t, col.configProvider) +} + +func TestNewCollectorValidatesResolverSettings(t *testing.T) { + set := ConfigProviderSettings{ + ResolverSettings: confmap.ResolverSettings{ + URIs: []string{filepath.Join("testdata", "otelcol-nop.yaml")}, + }, + } + + _, err := NewCollector(CollectorSettings{ + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: set, + }) + require.Error(t, err) } func TestCollectorStartWithTraceContextPropagation(t *testing.T) { @@ -243,16 +335,10 @@ func TestCollectorStartWithTraceContextPropagation(t *testing.T) { for _, tt := range tests { t.Run(tt.file, func(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", tt.file)})) - require.NoError(t, err) - set := CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: cfgProvider, + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: newDefaultConfigProviderSettings([]string{filepath.Join("testdata", tt.file)}), } col, err := NewCollector(set) @@ -281,16 +367,10 @@ func TestCollectorRun(t *testing.T) { for _, tt := range tests { t.Run(tt.file, func(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", tt.file)})) - require.NoError(t, err) - set := CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: cfgProvider, + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: newDefaultConfigProviderSettings([]string{filepath.Join("testdata", tt.file)}), } col, err := NewCollector(set) require.NoError(t, err) @@ -305,16 +385,10 @@ func TestCollectorRun(t *testing.T) { } func TestCollectorShutdownBeforeRun(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) - require.NoError(t, err) - set := CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: cfgProvider, + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")}), } col, err := NewCollector(set) require.NoError(t, err) @@ -330,17 +404,11 @@ func TestCollectorShutdownBeforeRun(t *testing.T) { } func TestCollectorClosedStateOnStartUpError(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-invalid.yaml")})) - require.NoError(t, err) - // Load a bad config causing startup to fail set := CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: cfgProvider, + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-invalid.yaml")}), } col, err := NewCollector(set) require.NoError(t, err) @@ -353,17 +421,11 @@ func TestCollectorClosedStateOnStartUpError(t *testing.T) { } func TestCollectorDryRun(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - - cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-invalid.yaml")})) - require.NoError(t, err) - // Load a bad config causing startup to fail set := CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: cfgProvider, + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-invalid.yaml")}), } col, err := NewCollector(set) require.NoError(t, err) @@ -372,22 +434,15 @@ func TestCollectorDryRun(t *testing.T) { } func TestPassConfmapToServiceFailure(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - - cfgProvider, err := NewConfigProvider(ConfigProviderSettings{ - ResolverSettings: confmap.ResolverSettings{ - URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")}, - Providers: makeMapProvidersMap(newFailureProvider()), - Converters: []confmap.Converter{expandconverter.New()}, - }, - }) - require.NoError(t, err) - set := CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: cfgProvider, + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: ConfigProviderSettings{ + ResolverSettings: confmap.ResolverSettings{ + URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")}, + Providers: makeMapProvidersMap(newFailureProvider()), + }, + }, } col, err := NewCollector(set) require.NoError(t, err) @@ -412,7 +467,7 @@ func newFailureProvider() confmap.Provider { return &failureProvider{} } -func (fmp *failureProvider) Retrieve(_ context.Context, _ string, _ confmap.WatcherFunc) (*confmap.Retrieved, error) { +func (fmp *failureProvider) Retrieve(context.Context, string, confmap.WatcherFunc) (*confmap.Retrieved, error) { return nil, errors.New("a failure occurred during configuration retrieval") } diff --git a/otelcol/collector_windows.go b/otelcol/collector_windows.go index 3959d28ce7c..f443d930b17 100644 --- a/otelcol/collector_windows.go +++ b/otelcol/collector_windows.go @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 //go:build windows -// +build windows package otelcol // import "go.opentelemetry.io/collector/otelcol" @@ -88,7 +87,11 @@ func (s *windowsService) start(elog *eventlog.Log, colErrorChannel chan error) e } var err error - s.col, err = newCollectorWithFlags(s.settings, s.flags) + err = updateSettingsUsingFlags(&s.settings, s.flags) + if err != nil { + return err + } + s.col, err = NewCollector(s.settings) if err != nil { return err } diff --git a/otelcol/collector_windows_test.go b/otelcol/collector_windows_test.go index fb12df6d11b..f562c02db4c 100644 --- a/otelcol/collector_windows_test.go +++ b/otelcol/collector_windows_test.go @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 //go:build windows -// +build windows package otelcol @@ -12,7 +11,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "golang.org/x/sys/windows/svc" "go.opentelemetry.io/collector/component" @@ -23,10 +21,7 @@ func TestNewSvcHandler(t *testing.T) { defer func() { os.Args = oldArgs }() os.Args = []string{"otelcol", "--config", filepath.Join("testdata", "otelcol-nop.yaml")} - factories, err := nopFactories() - require.NoError(t, err) - - s := NewSvcHandler(CollectorSettings{BuildInfo: component.NewDefaultBuildInfo(), Factories: factories}) + s := NewSvcHandler(CollectorSettings{BuildInfo: component.NewDefaultBuildInfo(), Factories: nopFactories}) colDone := make(chan struct{}) requests := make(chan svc.ChangeRequest) diff --git a/otelcol/command.go b/otelcol/command.go index a9baff305f3..f510687c31b 100644 --- a/otelcol/command.go +++ b/otelcol/command.go @@ -13,14 +13,22 @@ import ( ) // NewCommand constructs a new cobra.Command using the given CollectorSettings. +// Any URIs specified in CollectorSettings.ConfigProviderSettings.ResolverSettings.URIs +// are considered defaults and will be overwritten by config flags passed as +// command-line arguments to the executable. func NewCommand(set CollectorSettings) *cobra.Command { flagSet := flags(featuregate.GlobalRegistry()) rootCmd := &cobra.Command{ Use: set.BuildInfo.Command, Version: set.BuildInfo.Version, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { - col, err := newCollectorWithFlags(set, flagSet) + RunE: func(cmd *cobra.Command, _ []string) error { + err := updateSettingsUsingFlags(&set, flagSet) + if err != nil { + return err + } + + col, err := NewCollector(set) if err != nil { return err } @@ -33,18 +41,23 @@ func NewCommand(set CollectorSettings) *cobra.Command { return rootCmd } -func newCollectorWithFlags(set CollectorSettings, flags *flag.FlagSet) (*Collector, error) { +func updateSettingsUsingFlags(set *CollectorSettings, flags *flag.FlagSet) error { if set.ConfigProvider == nil { + resolverSet := &set.ConfigProviderSettings.ResolverSettings configFlags := getConfigFlag(flags) - if len(configFlags) == 0 { - return nil, errors.New("at least one config flag must be provided") - } - var err error - set.ConfigProvider, err = NewConfigProvider(newDefaultConfigProviderSettings(configFlags)) - if err != nil { - return nil, err + if len(configFlags) > 0 { + resolverSet.URIs = configFlags + } + if len(resolverSet.URIs) == 0 { + return errors.New("at least one config flag must be provided") + } + // Provide a default set of providers and converters if none have been specified. + // TODO: Remove this after CollectorSettings.ConfigProvider is removed and instead + // do it in the builder. + if len(resolverSet.Providers) == 0 && len(resolverSet.Converters) == 0 { + set.ConfigProviderSettings = newDefaultConfigProviderSettings(resolverSet.URIs) } } - return NewCollector(set) + return nil } diff --git a/otelcol/command_components.go b/otelcol/command_components.go index f63fce8e55f..83dd4670375 100644 --- a/otelcol/command_components.go +++ b/otelcol/command_components.go @@ -33,62 +33,67 @@ func newComponentsCommand(set CollectorSettings) *cobra.Command { Short: "Outputs available components in this collector distribution", Long: "Outputs available components in this collector distribution including their stability levels. The output format is not stable and can change between releases.", Args: cobra.ExactArgs(0), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { + + factories, err := set.Factories() + if err != nil { + return fmt.Errorf("failed to initialize factories: %w", err) + } components := componentsOutput{} - for con := range set.Factories.Connectors { + for con := range factories.Connectors { components.Connectors = append(components.Connectors, componentWithStability{ Name: con, Stability: map[string]string{ - "logs-to-logs": set.Factories.Connectors[con].LogsToLogsStability().String(), - "logs-to-metrics": set.Factories.Connectors[con].LogsToMetricsStability().String(), - "logs-to-traces": set.Factories.Connectors[con].LogsToTracesStability().String(), + "logs-to-logs": factories.Connectors[con].LogsToLogsStability().String(), + "logs-to-metrics": factories.Connectors[con].LogsToMetricsStability().String(), + "logs-to-traces": factories.Connectors[con].LogsToTracesStability().String(), - "metrics-to-logs": set.Factories.Connectors[con].MetricsToLogsStability().String(), - "metrics-to-metrics": set.Factories.Connectors[con].MetricsToMetricsStability().String(), - "metrics-to-traces": set.Factories.Connectors[con].MetricsToTracesStability().String(), + "metrics-to-logs": factories.Connectors[con].MetricsToLogsStability().String(), + "metrics-to-metrics": factories.Connectors[con].MetricsToMetricsStability().String(), + "metrics-to-traces": factories.Connectors[con].MetricsToTracesStability().String(), - "traces-to-logs": set.Factories.Connectors[con].TracesToLogsStability().String(), - "traces-to-metrics": set.Factories.Connectors[con].TracesToMetricsStability().String(), - "traces-to-traces": set.Factories.Connectors[con].TracesToTracesStability().String(), + "traces-to-logs": factories.Connectors[con].TracesToLogsStability().String(), + "traces-to-metrics": factories.Connectors[con].TracesToMetricsStability().String(), + "traces-to-traces": factories.Connectors[con].TracesToTracesStability().String(), }, }) } - for ext := range set.Factories.Extensions { + for ext := range factories.Extensions { components.Extensions = append(components.Extensions, componentWithStability{ Name: ext, Stability: map[string]string{ - "extension": set.Factories.Extensions[ext].ExtensionStability().String(), + "extension": factories.Extensions[ext].ExtensionStability().String(), }, }) } - for prs := range set.Factories.Processors { + for prs := range factories.Processors { components.Processors = append(components.Processors, componentWithStability{ Name: prs, Stability: map[string]string{ - "logs": set.Factories.Processors[prs].LogsProcessorStability().String(), - "metrics": set.Factories.Processors[prs].MetricsProcessorStability().String(), - "traces": set.Factories.Processors[prs].TracesProcessorStability().String(), + "logs": factories.Processors[prs].LogsProcessorStability().String(), + "metrics": factories.Processors[prs].MetricsProcessorStability().String(), + "traces": factories.Processors[prs].TracesProcessorStability().String(), }, }) } - for rcv := range set.Factories.Receivers { + for rcv := range factories.Receivers { components.Receivers = append(components.Receivers, componentWithStability{ Name: rcv, Stability: map[string]string{ - "logs": set.Factories.Receivers[rcv].LogsReceiverStability().String(), - "metrics": set.Factories.Receivers[rcv].MetricsReceiverStability().String(), - "traces": set.Factories.Receivers[rcv].TracesReceiverStability().String(), + "logs": factories.Receivers[rcv].LogsReceiverStability().String(), + "metrics": factories.Receivers[rcv].MetricsReceiverStability().String(), + "traces": factories.Receivers[rcv].TracesReceiverStability().String(), }, }) } - for exp := range set.Factories.Exporters { + for exp := range factories.Exporters { components.Exporters = append(components.Exporters, componentWithStability{ Name: exp, Stability: map[string]string{ - "logs": set.Factories.Exporters[exp].LogsExporterStability().String(), - "metrics": set.Factories.Exporters[exp].MetricsExporterStability().String(), - "traces": set.Factories.Exporters[exp].TracesExporterStability().String(), + "logs": factories.Exporters[exp].LogsExporterStability().String(), + "metrics": factories.Exporters[exp].MetricsExporterStability().String(), + "traces": factories.Exporters[exp].TracesExporterStability().String(), }, }) } diff --git a/otelcol/command_components_test.go b/otelcol/command_components_test.go index b143023eb5c..141fb586010 100644 --- a/otelcol/command_components_test.go +++ b/otelcol/command_components_test.go @@ -16,16 +16,15 @@ import ( "go.opentelemetry.io/collector/component" ) -func TestNewBuildSubCommand(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) +var nopType = component.MustNewType("nop") +func TestNewBuildSubCommand(t *testing.T) { cfgProvider, err := NewConfigProvider(newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-nop.yaml")})) require.NoError(t, err) set := CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, + Factories: nopFactories, ConfigProvider: cfgProvider, } cmd := NewCommand(set) @@ -34,7 +33,7 @@ func TestNewBuildSubCommand(t *testing.T) { ExpectedYamlStruct := componentsOutput{ BuildInfo: component.NewDefaultBuildInfo(), Receivers: []componentWithStability{{ - Name: component.Type("nop"), + Name: nopType, Stability: map[string]string{ "logs": "Stable", "metrics": "Stable", @@ -42,7 +41,7 @@ func TestNewBuildSubCommand(t *testing.T) { }, }}, Processors: []componentWithStability{{ - Name: component.Type("nop"), + Name: nopType, Stability: map[string]string{ "logs": "Stable", "metrics": "Stable", @@ -50,7 +49,7 @@ func TestNewBuildSubCommand(t *testing.T) { }, }}, Exporters: []componentWithStability{{ - Name: component.Type("nop"), + Name: nopType, Stability: map[string]string{ "logs": "Stable", "metrics": "Stable", @@ -58,7 +57,7 @@ func TestNewBuildSubCommand(t *testing.T) { }, }}, Connectors: []componentWithStability{{ - Name: component.Type("nop"), + Name: nopType, Stability: map[string]string{ "logs-to-logs": "Development", "logs-to-metrics": "Development", @@ -74,7 +73,7 @@ func TestNewBuildSubCommand(t *testing.T) { }, }}, Extensions: []componentWithStability{{ - Name: component.Type("nop"), + Name: nopType, Stability: map[string]string{ "extension": "Stable", }, diff --git a/otelcol/command_test.go b/otelcol/command_test.go index fdf2885dc1e..d599441c658 100644 --- a/otelcol/command_test.go +++ b/otelcol/command_test.go @@ -7,6 +7,7 @@ import ( "path/filepath" "testing" + "github.com/spf13/cobra" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -14,6 +15,7 @@ import ( "go.opentelemetry.io/collector/confmap" "go.opentelemetry.io/collector/confmap/converter/expandconverter" "go.opentelemetry.io/collector/confmap/provider/fileprovider" + "go.opentelemetry.io/collector/featuregate" ) func TestNewCommandVersion(t *testing.T) { @@ -22,27 +24,89 @@ func TestNewCommandVersion(t *testing.T) { } func TestNewCommandNoConfigURI(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - - cmd := NewCommand(CollectorSettings{Factories: factories}) + cmd := NewCommand(CollectorSettings{Factories: nopFactories}) require.Error(t, cmd.Execute()) } -func TestNewCommandInvalidComponent(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) +// This test emulates usage of Collector in Jaeger all-in-one, which +// allows running the binary with no explicit configuration. +func TestNewCommandProgrammaticallyPassedConfig(t *testing.T) { + cmd := NewCommand(CollectorSettings{Factories: nopFactories}) + otelRunE := cmd.RunE + cmd.RunE = func(c *cobra.Command, args []string) error { + configFlag := c.Flag("config") + cfg := ` +service: + extensions: [invalid_component_name] +receivers: + invalid_component_name: +` + require.NoError(t, configFlag.Value.Set("yaml:"+cfg)) + return otelRunE(cmd, args) + } + // verify that cmd.Execute was run with the implicitly provided config. + require.ErrorContains(t, cmd.Execute(), "invalid_component_name") +} - cfgProvider, err := NewConfigProvider( - ConfigProviderSettings{ +func TestAddFlagToSettings(t *testing.T) { + set := CollectorSettings{ + ConfigProviderSettings: ConfigProviderSettings{ ResolverSettings: confmap.ResolverSettings{ URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")}, - Providers: map[string]confmap.Provider{"file": fileprovider.New()}, - Converters: []confmap.Converter{expandconverter.New()}, + Providers: map[string]confmap.Provider{"file": fileprovider.NewWithSettings(confmap.ProviderSettings{})}, + Converters: []confmap.Converter{expandconverter.New(confmap.ConverterSettings{})}, }, - }) + }, + } + flgs := flags(featuregate.NewRegistry()) + err := flgs.Parse([]string{"--config=otelcol-nop.yaml"}) require.NoError(t, err) - cmd := NewCommand(CollectorSettings{Factories: factories, ConfigProvider: cfgProvider}) + err = updateSettingsUsingFlags(&set, flgs) + require.NoError(t, err) + require.Len(t, set.ConfigProviderSettings.ResolverSettings.URIs, 1) +} + +func TestAddDefaultConfmapModules(t *testing.T) { + set := CollectorSettings{ + ConfigProviderSettings: ConfigProviderSettings{ + ResolverSettings: confmap.ResolverSettings{}, + }, + } + flgs := flags(featuregate.NewRegistry()) + err := flgs.Parse([]string{"--config=otelcol-nop.yaml"}) + require.NoError(t, err) + + err = updateSettingsUsingFlags(&set, flgs) + require.NoError(t, err) + require.Len(t, set.ConfigProviderSettings.ResolverSettings.URIs, 1) + require.Len(t, set.ConfigProviderSettings.ResolverSettings.Converters, 1) + require.Len(t, set.ConfigProviderSettings.ResolverSettings.Providers, 5) +} + +func TestInvalidCollectorSettings(t *testing.T) { + set := CollectorSettings{ + ConfigProviderSettings: ConfigProviderSettings{ + ResolverSettings: confmap.ResolverSettings{ + Converters: []confmap.Converter{expandconverter.New(confmap.ConverterSettings{})}, + URIs: []string{"--config=otelcol-nop.yaml"}, + }, + }, + } + + cmd := NewCommand(set) + require.Error(t, cmd.Execute()) +} + +func TestNewCommandInvalidComponent(t *testing.T) { + set := ConfigProviderSettings{ + ResolverSettings: confmap.ResolverSettings{ + URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")}, + Providers: map[string]confmap.Provider{"file": fileprovider.NewWithSettings(confmap.ProviderSettings{})}, + Converters: []confmap.Converter{expandconverter.New(confmap.ConverterSettings{})}, + }, + } + + cmd := NewCommand(CollectorSettings{Factories: nopFactories, ConfigProviderSettings: set}) require.Error(t, cmd.Execute()) } diff --git a/otelcol/command_validate.go b/otelcol/command_validate.go index b64cb282d1d..72d20d476d8 100644 --- a/otelcol/command_validate.go +++ b/otelcol/command_validate.go @@ -16,7 +16,7 @@ func newValidateSubCommand(set CollectorSettings, flagSet *flag.FlagSet) *cobra. Use: "validate", Short: "Validates the config without running the collector", Args: cobra.ExactArgs(0), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { if set.ConfigProvider == nil { var err error diff --git a/otelcol/command_validate_test.go b/otelcol/command_validate_test.go index 4511eb73097..b215a77ffbf 100644 --- a/otelcol/command_validate_test.go +++ b/otelcol/command_validate_test.go @@ -16,30 +16,24 @@ import ( ) func TestValidateSubCommandNoConfig(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - - cmd := newValidateSubCommand(CollectorSettings{Factories: factories}, flags(featuregate.GlobalRegistry())) - err = cmd.Execute() + cmd := newValidateSubCommand(CollectorSettings{Factories: nopFactories}, flags(featuregate.GlobalRegistry())) + err := cmd.Execute() require.Error(t, err) require.Contains(t, err.Error(), "at least one config flag must be provided") } func TestValidateSubCommandInvalidComponents(t *testing.T) { - factories, err := nopFactories() - require.NoError(t, err) - cfgProvider, err := NewConfigProvider( ConfigProviderSettings{ ResolverSettings: confmap.ResolverSettings{ URIs: []string{filepath.Join("testdata", "otelcol-invalid-components.yaml")}, - Providers: map[string]confmap.Provider{"file": fileprovider.New()}, - Converters: []confmap.Converter{expandconverter.New()}, + Providers: map[string]confmap.Provider{"file": fileprovider.NewWithSettings(confmap.ProviderSettings{})}, + Converters: []confmap.Converter{expandconverter.New(confmap.ConverterSettings{})}, }, }) require.NoError(t, err) - cmd := newValidateSubCommand(CollectorSettings{Factories: factories, ConfigProvider: cfgProvider}, flags(featuregate.GlobalRegistry())) + cmd := newValidateSubCommand(CollectorSettings{Factories: nopFactories, ConfigProvider: cfgProvider}, flags(featuregate.GlobalRegistry())) err = cmd.Execute() require.Error(t, err) require.Contains(t, err.Error(), "unknown type: \"nosuchprocessor\"") diff --git a/otelcol/config_test.go b/otelcol/config_test.go index 9a4ddb87c4f..e482e6c8ae8 100644 --- a/otelcol/config_test.go +++ b/otelcol/config_test.go @@ -76,7 +76,7 @@ func TestConfigValidate(t *testing.T) { name: "invalid-extension-reference", cfgFn: func() *Config { cfg := generateConfig() - cfg.Service.Extensions = append(cfg.Service.Extensions, component.NewIDWithName("nop", "2")) + cfg.Service.Extensions = append(cfg.Service.Extensions, component.MustNewIDWithName("nop", "2")) return cfg }, expected: errors.New(`service::extensions: references extension "nop/2" which is not configured`), @@ -85,8 +85,8 @@ func TestConfigValidate(t *testing.T) { name: "invalid-receiver-reference", cfgFn: func() *Config { cfg := generateConfig() - pipe := cfg.Service.Pipelines[component.NewID("traces")] - pipe.Receivers = append(pipe.Receivers, component.NewIDWithName("nop", "2")) + pipe := cfg.Service.Pipelines[component.MustNewID("traces")] + pipe.Receivers = append(pipe.Receivers, component.MustNewIDWithName("nop", "2")) return cfg }, expected: errors.New(`service::pipelines::traces: references receiver "nop/2" which is not configured`), @@ -95,8 +95,8 @@ func TestConfigValidate(t *testing.T) { name: "invalid-processor-reference", cfgFn: func() *Config { cfg := generateConfig() - pipe := cfg.Service.Pipelines[component.NewID("traces")] - pipe.Processors = append(pipe.Processors, component.NewIDWithName("nop", "2")) + pipe := cfg.Service.Pipelines[component.MustNewID("traces")] + pipe.Processors = append(pipe.Processors, component.MustNewIDWithName("nop", "2")) return cfg }, expected: errors.New(`service::pipelines::traces: references processor "nop/2" which is not configured`), @@ -105,8 +105,8 @@ func TestConfigValidate(t *testing.T) { name: "invalid-exporter-reference", cfgFn: func() *Config { cfg := generateConfig() - pipe := cfg.Service.Pipelines[component.NewID("traces")] - pipe.Exporters = append(pipe.Exporters, component.NewIDWithName("nop", "2")) + pipe := cfg.Service.Pipelines[component.MustNewID("traces")] + pipe.Exporters = append(pipe.Exporters, component.MustNewIDWithName("nop", "2")) return cfg }, expected: errors.New(`service::pipelines::traces: references exporter "nop/2" which is not configured`), @@ -115,7 +115,7 @@ func TestConfigValidate(t *testing.T) { name: "invalid-receiver-config", cfgFn: func() *Config { cfg := generateConfig() - cfg.Receivers[component.NewID("nop")] = &errConfig{ + cfg.Receivers[component.MustNewID("nop")] = &errConfig{ validateErr: errInvalidRecvConfig, } return cfg @@ -126,7 +126,7 @@ func TestConfigValidate(t *testing.T) { name: "invalid-exporter-config", cfgFn: func() *Config { cfg := generateConfig() - cfg.Exporters[component.NewID("nop")] = &errConfig{ + cfg.Exporters[component.MustNewID("nop")] = &errConfig{ validateErr: errInvalidExpConfig, } return cfg @@ -137,7 +137,7 @@ func TestConfigValidate(t *testing.T) { name: "invalid-processor-config", cfgFn: func() *Config { cfg := generateConfig() - cfg.Processors[component.NewID("nop")] = &errConfig{ + cfg.Processors[component.MustNewID("nop")] = &errConfig{ validateErr: errInvalidProcConfig, } return cfg @@ -148,7 +148,7 @@ func TestConfigValidate(t *testing.T) { name: "invalid-extension-config", cfgFn: func() *Config { cfg := generateConfig() - cfg.Extensions[component.NewID("nop")] = &errConfig{ + cfg.Extensions[component.MustNewID("nop")] = &errConfig{ validateErr: errInvalidExtConfig, } return cfg @@ -159,7 +159,7 @@ func TestConfigValidate(t *testing.T) { name: "invalid-connector-config", cfgFn: func() *Config { cfg := generateConfig() - cfg.Connectors[component.NewIDWithName("nop", "conn")] = &errConfig{ + cfg.Connectors[component.MustNewIDWithName("nop", "conn")] = &errConfig{ validateErr: errInvalidConnConfig, } return cfg @@ -170,34 +170,34 @@ func TestConfigValidate(t *testing.T) { name: "ambiguous-connector-name-as-receiver", cfgFn: func() *Config { cfg := generateConfig() - cfg.Receivers[component.NewID("nop/2")] = &errConfig{} - cfg.Connectors[component.NewID("nop/2")] = &errConfig{} - pipe := cfg.Service.Pipelines[component.NewID("traces")] - pipe.Receivers = append(pipe.Receivers, component.NewIDWithName("nop", "2")) - pipe.Exporters = append(pipe.Exporters, component.NewIDWithName("nop", "2")) + cfg.Receivers[component.MustNewID("nop2")] = &errConfig{} + cfg.Connectors[component.MustNewID("nop2")] = &errConfig{} + pipe := cfg.Service.Pipelines[component.MustNewID("traces")] + pipe.Receivers = append(pipe.Receivers, component.MustNewIDWithName("nop", "2")) + pipe.Exporters = append(pipe.Exporters, component.MustNewIDWithName("nop", "2")) return cfg }, - expected: errors.New(`connectors::nop/2: ambiguous ID: Found both "nop/2" receiver and "nop/2" connector. Change one of the components' IDs to eliminate ambiguity (e.g. rename "nop/2" connector to "nop/2/connector")`), + expected: errors.New(`connectors::nop2: ambiguous ID: Found both "nop2" receiver and "nop2" connector. Change one of the components' IDs to eliminate ambiguity (e.g. rename "nop2" connector to "nop2/connector")`), }, { name: "ambiguous-connector-name-as-exporter", cfgFn: func() *Config { cfg := generateConfig() - cfg.Exporters[component.NewID("nop/2")] = &errConfig{} - cfg.Connectors[component.NewID("nop/2")] = &errConfig{} - pipe := cfg.Service.Pipelines[component.NewID("traces")] - pipe.Receivers = append(pipe.Receivers, component.NewIDWithName("nop", "2")) - pipe.Exporters = append(pipe.Exporters, component.NewIDWithName("nop", "2")) + cfg.Exporters[component.MustNewID("nop2")] = &errConfig{} + cfg.Connectors[component.MustNewID("nop2")] = &errConfig{} + pipe := cfg.Service.Pipelines[component.MustNewID("traces")] + pipe.Receivers = append(pipe.Receivers, component.MustNewIDWithName("nop", "2")) + pipe.Exporters = append(pipe.Exporters, component.MustNewIDWithName("nop", "2")) return cfg }, - expected: errors.New(`connectors::nop/2: ambiguous ID: Found both "nop/2" exporter and "nop/2" connector. Change one of the components' IDs to eliminate ambiguity (e.g. rename "nop/2" connector to "nop/2/connector")`), + expected: errors.New(`connectors::nop2: ambiguous ID: Found both "nop2" exporter and "nop2" connector. Change one of the components' IDs to eliminate ambiguity (e.g. rename "nop2" connector to "nop2/connector")`), }, { name: "invalid-connector-reference-as-receiver", cfgFn: func() *Config { cfg := generateConfig() - pipe := cfg.Service.Pipelines[component.NewID("traces")] - pipe.Receivers = append(pipe.Receivers, component.NewIDWithName("nop", "conn2")) + pipe := cfg.Service.Pipelines[component.MustNewID("traces")] + pipe.Receivers = append(pipe.Receivers, component.MustNewIDWithName("nop", "conn2")) return cfg }, expected: errors.New(`service::pipelines::traces: references receiver "nop/conn2" which is not configured`), @@ -206,8 +206,8 @@ func TestConfigValidate(t *testing.T) { name: "invalid-connector-reference-as-receiver", cfgFn: func() *Config { cfg := generateConfig() - pipe := cfg.Service.Pipelines[component.NewID("traces")] - pipe.Exporters = append(pipe.Exporters, component.NewIDWithName("nop", "conn2")) + pipe := cfg.Service.Pipelines[component.MustNewID("traces")] + pipe.Exporters = append(pipe.Exporters, component.MustNewIDWithName("nop", "conn2")) return cfg }, expected: errors.New(`service::pipelines::traces: references exporter "nop/conn2" which is not configured`), @@ -234,19 +234,19 @@ func TestConfigValidate(t *testing.T) { func generateConfig() *Config { return &Config{ Receivers: map[component.ID]component.Config{ - component.NewID("nop"): &errConfig{}, + component.MustNewID("nop"): &errConfig{}, }, Exporters: map[component.ID]component.Config{ - component.NewID("nop"): &errConfig{}, + component.MustNewID("nop"): &errConfig{}, }, Processors: map[component.ID]component.Config{ - component.NewID("nop"): &errConfig{}, + component.MustNewID("nop"): &errConfig{}, }, Connectors: map[component.ID]component.Config{ - component.NewIDWithName("nop", "conn"): &errConfig{}, + component.MustNewIDWithName("nop", "conn"): &errConfig{}, }, Extensions: map[component.ID]component.Config{ - component.NewID("nop"): &errConfig{}, + component.MustNewID("nop"): &errConfig{}, }, Service: service.Config{ Telemetry: telemetry.Config{ @@ -265,12 +265,12 @@ func generateConfig() *Config { Address: ":8080", }, }, - Extensions: []component.ID{component.NewID("nop")}, + Extensions: []component.ID{component.MustNewID("nop")}, Pipelines: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, }, diff --git a/otelcol/configprovider.go b/otelcol/configprovider.go index c266c9a47df..fa43aa64ae6 100644 --- a/otelcol/configprovider.go +++ b/otelcol/configprovider.go @@ -132,11 +132,19 @@ func (cm *configProvider) GetConfmap(ctx context.Context) (*confmap.Conf, error) } func newDefaultConfigProviderSettings(uris []string) ConfigProviderSettings { + converterSet := confmap.ConverterSettings{} + providerSet := confmap.ProviderSettings{} return ConfigProviderSettings{ ResolverSettings: confmap.ResolverSettings{ - URIs: uris, - Providers: makeMapProvidersMap(fileprovider.New(), envprovider.New(), yamlprovider.New(), httpprovider.New(), httpsprovider.New()), - Converters: []confmap.Converter{expandconverter.New()}, + URIs: uris, + Providers: makeMapProvidersMap( + fileprovider.NewWithSettings(providerSet), + envprovider.NewWithSettings(providerSet), + yamlprovider.NewWithSettings(providerSet), + httpprovider.NewWithSettings(providerSet), + httpsprovider.NewWithSettings(providerSet), + ), + Converters: []confmap.Converter{expandconverter.New(converterSet)}, }, } } diff --git a/otelcol/flags.go b/otelcol/flags.go index a2d0885f53e..06f9989adb3 100644 --- a/otelcol/flags.go +++ b/otelcol/flags.go @@ -12,8 +12,7 @@ import ( ) const ( - configFlag = "config" - featureGatesFlag = "feature-gates" + configFlag = "config" ) type configFlagValue struct { @@ -50,9 +49,7 @@ func flags(reg *featuregate.Registry) *flag.FlagSet { return nil }) - flagSet.Var(featuregate.NewFlag(reg), featureGatesFlag, - "Comma-delimited list of feature gate identifiers. Prefix with '-' to disable the feature. '+' or no prefix will enable the feature.") - + reg.RegisterFlags(flagSet) return flagSet } diff --git a/otelcol/go.mod b/otelcol/go.mod index e2b9dfee6ca..78caf027f15 100644 --- a/otelcol/go.mod +++ b/otelcol/go.mod @@ -1,97 +1,99 @@ module go.opentelemetry.io/collector/otelcol -go 1.20 +go 1.21 require ( - github.com/spf13/cobra v1.7.0 + github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 - go.opentelemetry.io/collector/confmap v0.85.0 - go.opentelemetry.io/collector/connector v0.85.0 - go.opentelemetry.io/collector/exporter v0.85.0 - go.opentelemetry.io/collector/extension v0.85.0 - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 - go.opentelemetry.io/collector/processor v0.85.0 - go.opentelemetry.io/collector/receiver v0.85.0 - go.opentelemetry.io/collector/service v0.0.0-20230915215502-07938f20fcc7 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 + go.opentelemetry.io/collector/confmap v0.96.0 + go.opentelemetry.io/collector/confmap/converter/expandconverter v0.96.0 + go.opentelemetry.io/collector/confmap/provider/envprovider v0.96.0 + go.opentelemetry.io/collector/confmap/provider/fileprovider v0.96.0 + go.opentelemetry.io/collector/confmap/provider/httpprovider v0.96.0 + go.opentelemetry.io/collector/confmap/provider/httpsprovider v0.96.0 + go.opentelemetry.io/collector/confmap/provider/yamlprovider v0.96.0 + go.opentelemetry.io/collector/connector v0.96.0 + go.opentelemetry.io/collector/exporter v0.96.0 + go.opentelemetry.io/collector/extension v0.96.0 + go.opentelemetry.io/collector/featuregate v1.3.0 + go.opentelemetry.io/collector/processor v0.96.0 + go.opentelemetry.io/collector/receiver v0.96.0 + go.opentelemetry.io/collector/service v0.96.0 + go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 - go.uber.org/zap v1.26.0 - golang.org/x/sys v0.12.0 - google.golang.org/grpc v1.58.1 + go.uber.org/zap v1.27.0 + golang.org/x/sys v0.17.0 + google.golang.org/grpc v1.62.0 gopkg.in/yaml.v3 v3.0.1 ) require ( - contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/uuid v1.3.1 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect - github.com/prometheus/statsd_exporter v0.22.7 // indirect - github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/shirou/gopsutil/v3 v3.24.1 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector v0.85.0 // indirect - go.opentelemetry.io/collector/consumer v0.85.0 // indirect - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/semconv v0.85.0 // indirect - go.opentelemetry.io/contrib/propagators/b3 v1.19.0 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/bridge/opencensus v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/sdk v1.18.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/text v0.13.0 // indirect + go.opentelemetry.io/collector v0.96.0 // indirect + go.opentelemetry.io/collector/consumer v0.96.0 // indirect + go.opentelemetry.io/collector/pdata v1.3.0 // indirect + go.opentelemetry.io/collector/semconv v0.96.0 // indirect + go.opentelemetry.io/contrib/config v0.4.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.24.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/bridge/opencensus v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/text v0.14.0 // indirect gonum.org/v1/gonum v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/protobuf v1.32.0 // indirect ) replace go.opentelemetry.io/collector => ../ @@ -112,6 +114,18 @@ replace go.opentelemetry.io/collector/exporter => ../exporter replace go.opentelemetry.io/collector/confmap => ../confmap +replace go.opentelemetry.io/collector/confmap/converter/expandconverter => ../confmap/converter/expandconverter + +replace go.opentelemetry.io/collector/confmap/provider/envprovider => ../confmap/provider/envprovider + +replace go.opentelemetry.io/collector/confmap/provider/fileprovider => ../confmap/provider/fileprovider + +replace go.opentelemetry.io/collector/confmap/provider/httpprovider => ../confmap/provider/httpprovider + +replace go.opentelemetry.io/collector/confmap/provider/httpsprovider => ../confmap/provider/httpsprovider + +replace go.opentelemetry.io/collector/confmap/provider/yamlprovider => ../confmap/provider/yamlprovider + replace go.opentelemetry.io/collector/config/configtelemetry => ../config/configtelemetry replace go.opentelemetry.io/collector/processor => ../processor @@ -125,3 +139,5 @@ replace go.opentelemetry.io/collector/receiver => ../receiver replace go.opentelemetry.io/collector/featuregate => ../featuregate replace go.opentelemetry.io/collector/config/confignet => ../config/confignet + +replace go.opentelemetry.io/collector/config/configretry => ../config/configretry diff --git a/otelcol/go.sum b/otelcol/go.sum index cfe49b1fc62..c0bb0cbd6fd 100644 --- a/otelcol/go.sum +++ b/otelcol/go.sum @@ -1,63 +1,15 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -65,468 +17,217 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= -github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= +github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= -go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ= -go.opentelemetry.io/contrib/zpages v0.44.0 h1:9J/cxTTWhM6kzgdaBt6NiXS2HUreXn/eW2M+vzHgDAQ= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/bridge/opencensus v0.41.0 h1:VBpeaTbrvLFHvRtsyCJXjsTaicBNrAFdmctiN1k6WNI= -go.opentelemetry.io/otel/bridge/opencensus v0.41.0/go.mod h1:yCQB5IKRhgjlbTLc91+ixcZc2/8BncGGJ+CS3dZJwtY= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 h1:k0k7hFNDd8K4iOMJXj7s8sHaC4mhTlAeppRmZXLgZ6k= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 h1:HgbDTD8pioFdY3NRc/YCvsWjqQPtweGyXxa32LgnTOw= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0/go.mod h1:tmvt/yK5Es5d6lHYWerLSOna8lCEfrBVX/a9M0ggqss= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.41.0 h1:iV3BOgW4fry1Riw9dwypigqlIYWXvSRVT2RJmblzo40= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.41.0/go.mod h1:7PGzqlKrxIRmbj5tlNW0nTkYZ5fHXDgk6Fy8/KjR0CI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.18.0 h1:6pu8ttx76BxHf+xz/H77AUZkPF3cwWzXqAUsXhVKI18= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.18.0/go.mod h1:IOmXxPrxoxFMXdNy7lfDmE8MzE61YPcurbUm0SMjerI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 h1:XzjGkawtAXs20Y+s6k1GNDMBsMDOV28TOT8cxmE42qM= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0/go.mod h1:HAomEgjcKZk3VJ+HHdHLnhZXeGqdzPxxNTdKYRopUXY= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/contrib/config v0.4.0 h1:Xb+ncYOqseLroMuBesGNRgVQolXcXOhMj7EhGwJCdHs= +go.opentelemetry.io/contrib/config v0.4.0/go.mod h1:drNk2xRqLWW4/amk6Uh1S+sDAJTc7bcEEN1GfJzj418= +go.opentelemetry.io/contrib/propagators/b3 v1.24.0 h1:n4xwCdTx3pZqZs2CjS/CUZAs03y3dZcGhC/FepKtEUY= +go.opentelemetry.io/contrib/propagators/b3 v1.24.0/go.mod h1:k5wRxKRU2uXx2F8uNJ4TaonuEO/V7/5xoz7kdsDACT8= +go.opentelemetry.io/contrib/zpages v0.49.0 h1:Wk217PkNBxcKWnIQpwtbZZE286K4ZY9uajnM5woSeLU= +go.opentelemetry.io/contrib/zpages v0.49.0/go.mod h1:6alLi5mmkZWbAtZMRPd1ffIgkTcsU9OTHQF2NbSOhrQ= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/bridge/opencensus v1.24.0 h1:Vlhy5ee5k5R0zASpH+9AgHiJH7xnKACI3XopO1tUZfY= +go.opentelemetry.io/otel/bridge/opencensus v1.24.0/go.mod h1:jRjVXV/X38jyrnHtvMGN8+9cejZB21JvXAAvooF2s+Q= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0 h1:f2jriWfOdldanBwS9jNBdeOKAQN7b4ugAMaNu1/1k9g= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0/go.mod h1:B+bcQI1yTY+N0vqMpoZbEN7+XU4tNM0DmUiOwebFJWI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0 h1:mM8nKi6/iFQ0iqst80wDHU2ge198Ye/TfN0WBS5U24Y= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0/go.mod h1:0PrIIzDteLSmNyxqcGYRL4mDIo8OTuBAOI/Bn1URxac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.24.0 h1:JYE2HM7pZbOt5Jhk8ndWZTUWYOVift2cHjXVMkPdmdc= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.24.0/go.mod h1:yMb/8c6hVsnma0RpsBMNo0fEiQKeclawtgaIaOp2MLY= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -534,77 +235,24 @@ 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= gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -613,37 +261,16 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/otelcol/internal/configunmarshaler/configs.go b/otelcol/internal/configunmarshaler/configs.go index 83996d5f015..ab226d3b670 100644 --- a/otelcol/internal/configunmarshaler/configs.go +++ b/otelcol/internal/configunmarshaler/configs.go @@ -23,7 +23,7 @@ func NewConfigs[F component.Factory](factories map[component.Type]F) *Configs[F] func (c *Configs[F]) Unmarshal(conf *confmap.Conf) error { rawCfgs := make(map[component.ID]map[string]any) - if err := conf.Unmarshal(&rawCfgs, confmap.WithErrorUnused()); err != nil { + if err := conf.Unmarshal(&rawCfgs); err != nil { return err } diff --git a/otelcol/internal/configunmarshaler/configs_test.go b/otelcol/internal/configunmarshaler/configs_test.go index bc869456455..f6cd2865281 100644 --- a/otelcol/internal/configunmarshaler/configs_test.go +++ b/otelcol/internal/configunmarshaler/configs_test.go @@ -18,6 +18,8 @@ import ( "go.opentelemetry.io/collector/receiver/receivertest" ) +var nopType = component.MustNewType("nop") + var testKinds = []struct { kind string factories map[component.Type]component.Factory @@ -25,31 +27,31 @@ var testKinds = []struct { { kind: "receiver", factories: map[component.Type]component.Factory{ - "nop": receivertest.NewNopFactory(), + nopType: receivertest.NewNopFactory(), }, }, { kind: "processor", factories: map[component.Type]component.Factory{ - "nop": processortest.NewNopFactory(), + nopType: processortest.NewNopFactory(), }, }, { kind: "exporter", factories: map[component.Type]component.Factory{ - "nop": exportertest.NewNopFactory(), + nopType: exportertest.NewNopFactory(), }, }, { kind: "connector", factories: map[component.Type]component.Factory{ - "nop": connectortest.NewNopFactory(), + nopType: connectortest.NewNopFactory(), }, }, { kind: "extension", factories: map[component.Type]component.Factory{ - "nop": extensiontest.NewNopFactory(), + nopType: extensiontest.NewNopFactory(), }, }, } @@ -65,8 +67,8 @@ func TestUnmarshal(t *testing.T) { require.NoError(t, cfgs.Unmarshal(conf)) assert.Equal(t, map[component.ID]component.Config{ - component.NewID("nop"): tk.factories["nop"].CreateDefaultConfig(), - component.NewIDWithName("nop", "my"+tk.kind): tk.factories["nop"].CreateDefaultConfig(), + component.NewID(nopType): tk.factories[nopType].CreateDefaultConfig(), + component.NewIDWithName(nopType, "my"+tk.kind): tk.factories[nopType].CreateDefaultConfig(), }, cfgs.Configs()) }) } diff --git a/otelcol/internal/configunmarshaler/package_test.go b/otelcol/internal/configunmarshaler/package_test.go new file mode 100644 index 00000000000..740d7d943dc --- /dev/null +++ b/otelcol/internal/configunmarshaler/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package configunmarshaler + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/otelcol/internal/grpclog/package_test.go b/otelcol/internal/grpclog/package_test.go new file mode 100644 index 00000000000..c21c7a4dd4a --- /dev/null +++ b/otelcol/internal/grpclog/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package grpclog + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/otelcol/otelcoltest/config.go b/otelcol/otelcoltest/config.go index 74cdb18f260..fc2957d893a 100644 --- a/otelcol/otelcoltest/config.go +++ b/otelcol/otelcoltest/config.go @@ -20,9 +20,14 @@ func LoadConfig(fileName string, factories otelcol.Factories) (*otelcol.Config, // Read yaml config from file provider, err := otelcol.NewConfigProvider(otelcol.ConfigProviderSettings{ ResolverSettings: confmap.ResolverSettings{ - URIs: []string{fileName}, - Providers: makeMapProvidersMap(fileprovider.New(), envprovider.New(), yamlprovider.New(), httpprovider.New()), - Converters: []confmap.Converter{expandconverter.New()}, + URIs: []string{fileName}, + Providers: makeMapProvidersMap( + fileprovider.NewWithSettings(confmap.ProviderSettings{}), + envprovider.NewWithSettings(confmap.ProviderSettings{}), + yamlprovider.NewWithSettings(confmap.ProviderSettings{}), + httpprovider.NewWithSettings(confmap.ProviderSettings{}), + ), + Converters: []confmap.Converter{expandconverter.New(confmap.ConverterSettings{})}, }, }) if err != nil { diff --git a/otelcol/otelcoltest/config_test.go b/otelcol/otelcoltest/config_test.go index 1ab8ad1304d..71502de536e 100644 --- a/otelcol/otelcoltest/config_test.go +++ b/otelcol/otelcoltest/config_test.go @@ -23,39 +23,39 @@ func TestLoadConfig(t *testing.T) { // Verify extensions. require.Len(t, cfg.Extensions, 2) - assert.Contains(t, cfg.Extensions, component.NewID("nop")) - assert.Contains(t, cfg.Extensions, component.NewIDWithName("nop", "myextension")) + assert.Contains(t, cfg.Extensions, component.MustNewID("nop")) + assert.Contains(t, cfg.Extensions, component.MustNewIDWithName("nop", "myextension")) // Verify receivers require.Len(t, cfg.Receivers, 2) - assert.Contains(t, cfg.Receivers, component.NewID("nop")) - assert.Contains(t, cfg.Receivers, component.NewIDWithName("nop", "myreceiver")) + assert.Contains(t, cfg.Receivers, component.MustNewID("nop")) + assert.Contains(t, cfg.Receivers, component.MustNewIDWithName("nop", "myreceiver")) // Verify exporters assert.Len(t, cfg.Exporters, 2) - assert.Contains(t, cfg.Exporters, component.NewID("nop")) - assert.Contains(t, cfg.Exporters, component.NewIDWithName("nop", "myexporter")) + assert.Contains(t, cfg.Exporters, component.MustNewID("nop")) + assert.Contains(t, cfg.Exporters, component.MustNewIDWithName("nop", "myexporter")) // Verify procs assert.Len(t, cfg.Processors, 2) - assert.Contains(t, cfg.Processors, component.NewID("nop")) - assert.Contains(t, cfg.Processors, component.NewIDWithName("nop", "myprocessor")) + assert.Contains(t, cfg.Processors, component.MustNewID("nop")) + assert.Contains(t, cfg.Processors, component.MustNewIDWithName("nop", "myprocessor")) // Verify connectors assert.Len(t, cfg.Connectors, 1) - assert.Contains(t, cfg.Connectors, component.NewIDWithName("nop", "myconnector")) + assert.Contains(t, cfg.Connectors, component.MustNewIDWithName("nop", "myconnector")) // Verify service. require.Len(t, cfg.Service.Extensions, 1) - assert.Contains(t, cfg.Service.Extensions, component.NewID("nop")) + assert.Contains(t, cfg.Service.Extensions, component.MustNewID("nop")) require.Len(t, cfg.Service.Pipelines, 1) assert.Equal(t, &pipelines.PipelineConfig{ - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, - cfg.Service.Pipelines[component.NewID("traces")], + cfg.Service.Pipelines[component.MustNewID("traces")], "Did not load pipeline config correctly") } diff --git a/otelcol/otelcoltest/nop_factories_test.go b/otelcol/otelcoltest/nop_factories_test.go index b70720c026b..1f77ecdd68e 100644 --- a/otelcol/otelcoltest/nop_factories_test.go +++ b/otelcol/otelcoltest/nop_factories_test.go @@ -11,32 +11,34 @@ import ( "go.opentelemetry.io/collector/component" ) +var nopType = component.MustNewType("nop") + func TestNopFactories(t *testing.T) { nopFactories, err := NopFactories() require.NoError(t, err) require.Equal(t, 1, len(nopFactories.Receivers)) - nopReceiverFactory, ok := nopFactories.Receivers["nop"] + nopReceiverFactory, ok := nopFactories.Receivers[nopType] require.True(t, ok) - require.Equal(t, component.Type("nop"), nopReceiverFactory.Type()) + require.Equal(t, nopType, nopReceiverFactory.Type()) require.Equal(t, 1, len(nopFactories.Processors)) - nopProcessorFactory, ok := nopFactories.Processors["nop"] + nopProcessorFactory, ok := nopFactories.Processors[nopType] require.True(t, ok) - require.Equal(t, component.Type("nop"), nopProcessorFactory.Type()) + require.Equal(t, nopType, nopProcessorFactory.Type()) require.Equal(t, 1, len(nopFactories.Exporters)) - nopExporterFactory, ok := nopFactories.Exporters["nop"] + nopExporterFactory, ok := nopFactories.Exporters[nopType] require.True(t, ok) - require.Equal(t, component.Type("nop"), nopExporterFactory.Type()) + require.Equal(t, nopType, nopExporterFactory.Type()) require.Equal(t, 1, len(nopFactories.Extensions)) - nopExtensionFactory, ok := nopFactories.Extensions["nop"] + nopExtensionFactory, ok := nopFactories.Extensions[nopType] require.True(t, ok) - require.Equal(t, component.Type("nop"), nopExtensionFactory.Type()) + require.Equal(t, nopType, nopExtensionFactory.Type()) require.Equal(t, 1, len(nopFactories.Connectors)) - nopConnectorFactory, ok := nopFactories.Connectors["nop"] + nopConnectorFactory, ok := nopFactories.Connectors[nopType] require.True(t, ok) - require.Equal(t, component.Type("nop"), nopConnectorFactory.Type()) + require.Equal(t, nopType, nopConnectorFactory.Type()) } diff --git a/otelcol/otelcoltest/package_test.go b/otelcol/otelcoltest/package_test.go new file mode 100644 index 00000000000..9c8fe3dde5a --- /dev/null +++ b/otelcol/otelcoltest/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package otelcoltest + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/otelcol/package_test.go b/otelcol/package_test.go new file mode 100644 index 00000000000..539e88c85c4 --- /dev/null +++ b/otelcol/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package otelcol + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/otelcol/testdata/otelcol-statuswatcher.yaml b/otelcol/testdata/otelcol-statuswatcher.yaml new file mode 100644 index 00000000000..2dcc322d341 --- /dev/null +++ b/otelcol/testdata/otelcol-statuswatcher.yaml @@ -0,0 +1,31 @@ +receivers: + nop: + +processors: + nop: + unhealthy: + +exporters: + nop: + +extensions: + statuswatcher: + +service: + telemetry: + metrics: + address: localhost:8888 + extensions: [statuswatcher] + pipelines: + traces: + receivers: [nop] + processors: [nop,unhealthy] + exporters: [nop] + metrics: + receivers: [nop] + processors: [nop,unhealthy] + exporters: [nop] + logs: + receivers: [nop] + processors: [nop,unhealthy] + exporters: [nop] diff --git a/otelcol/unmarshaler.go b/otelcol/unmarshaler.go index 88f25dfc93f..643e396db42 100644 --- a/otelcol/unmarshaler.go +++ b/otelcol/unmarshaler.go @@ -4,6 +4,8 @@ package otelcol // import "go.opentelemetry.io/collector/otelcol" import ( + "time" + "go.uber.org/zap/zapcore" "go.opentelemetry.io/collector/config/configtelemetry" @@ -45,7 +47,9 @@ func unmarshal(v *confmap.Conf, factories Factories) (*configSettings, error) { Development: false, Encoding: "console", Sampling: &telemetry.LogsSamplingConfig{ - Initial: 100, + Enabled: true, + Tick: 10 * time.Second, + Initial: 10, Thereafter: 100, }, OutputPaths: []string{"stderr"}, @@ -62,5 +66,5 @@ func unmarshal(v *confmap.Conf, factories Factories) (*configSettings, error) { }, } - return cfg, v.Unmarshal(&cfg, confmap.WithErrorUnused()) + return cfg, v.Unmarshal(&cfg) } diff --git a/otelcol/unmarshaler_test.go b/otelcol/unmarshaler_test.go index c4ef21906db..18fd5f631db 100644 --- a/otelcol/unmarshaler_test.go +++ b/otelcol/unmarshaler_test.go @@ -5,6 +5,7 @@ package otelcol import ( "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -45,7 +46,9 @@ func TestUnmarshalEmptyAllSections(t *testing.T) { Development: zapProdCfg.Development, Encoding: "console", Sampling: &telemetry.LogsSamplingConfig{ - Initial: 100, + Enabled: true, + Tick: 10 * time.Second, + Initial: 10, Thereafter: 100, }, DisableCaller: zapProdCfg.DisableCaller, @@ -132,7 +135,7 @@ func TestPipelineConfigUnmarshalError(t *testing.T) { for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { pips := new(pipelines.Config) - err := tt.conf.Unmarshal(&pips, confmap.WithErrorUnused()) + err := tt.conf.Unmarshal(&pips) require.Error(t, err) assert.Contains(t, err.Error(), tt.expectError) }) @@ -200,7 +203,7 @@ func TestServiceUnmarshalError(t *testing.T) { for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { - err := tt.conf.Unmarshal(&service.Config{}, confmap.WithErrorUnused()) + err := tt.conf.Unmarshal(&service.Config{}) require.Error(t, err) assert.Contains(t, err.Error(), tt.expectError) }) diff --git a/pdata/go.mod b/pdata/go.mod index c2a39ce6970..5adab7efc2d 100644 --- a/pdata/go.mod +++ b/pdata/go.mod @@ -1,14 +1,15 @@ module go.opentelemetry.io/collector/pdata -go 1.20 +go 1.21 require ( github.com/gogo/protobuf v1.3.2 github.com/json-iterator/go v1.1.12 github.com/stretchr/testify v1.8.4 + go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 - google.golang.org/grpc v1.58.1 - google.golang.org/protobuf v1.31.0 + google.golang.org/grpc v1.62.0 + google.golang.org/protobuf v1.32.0 ) require ( @@ -19,10 +20,10 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // 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 b2401ef80ca..989737ec2ef 100644 --- a/pdata/go.sum +++ b/pdata/go.sum @@ -8,7 +8,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= @@ -38,6 +39,8 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -49,20 +52,20 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -71,14 +74,14 @@ 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-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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/internal/cmd/pdatagen/internal/base_fields.go b/pdata/internal/cmd/pdatagen/internal/base_fields.go index de5419c666d..7e0f60dd679 100644 --- a/pdata/internal/cmd/pdatagen/internal/base_fields.go +++ b/pdata/internal/cmd/pdatagen/internal/base_fields.go @@ -12,9 +12,15 @@ import ( const accessorSliceTemplate = `// {{ .fieldName }} returns the {{ .fieldName }} associated with this {{ .structName }}. func (ms {{ .structName }}) {{ .fieldName }}() {{ .packageName }}{{ .returnType }} { {{- if .isCommon }} - return {{ .packageName }}{{ .returnType }}(internal.New{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }})) + return {{ .packageName }}{{ .returnType }}(internal.New{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }} + {{- if .isBaseStructCommon -}} + , internal.Get{{ .structName }}State(internal.{{ .structName }}(ms)) + {{- else -}} + , ms.state + {{- end -}} + )) {{- else }} - return new{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }}) + return new{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }}, ms.state) {{- end }} }` @@ -36,14 +42,14 @@ const setTestValueTemplate = `{{ if .isCommon -}} {{- else -}} fillTest{{ .returnType }}(new {{- end -}} - {{ .returnType }}(&tv.orig.{{ .fieldName }}))` + {{ .returnType }}(&tv.orig.{{ .fieldName }}, tv.state))` const accessorsMessageValueTemplate = `// {{ .fieldName }} returns the {{ .lowerFieldName }} associated with this {{ .structName }}. func (ms {{ .structName }}) {{ .fieldName }}() {{ .packageName }}{{ .returnType }} { {{- if .isCommon }} - return {{ .packageName }}{{ .returnType }}(internal.New{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }})) + return {{ .packageName }}{{ .returnType }}(internal.New{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }}, ms.state)) {{- else }} - return new{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }}) + return new{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }}, ms.state) {{- end }} }` @@ -65,12 +71,13 @@ func (ms {{ .structName }}) {{ .fieldName }}() {{ .packageName }}{{ .returnType // Set{{ .fieldName }} replaces the {{ .lowerFieldName }} associated with this {{ .structName }}. func (ms {{ .structName }}) Set{{ .fieldName }}(v {{ .returnType }}) { + ms.{{ .stateAccessor }}.AssertMutable() ms.{{ .origAccessor }}.{{ .fieldName }} = v }` const accessorsPrimitiveSliceTemplate = `// {{ .fieldName }} returns the {{ .lowerFieldName }} associated with this {{ .structName }}. func (ms {{ .structName }}) {{ .fieldName }}() {{ .packageName }}{{ .returnType }} { - return {{ .packageName }}{{ .returnType }}(internal.New{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }})) + return {{ .packageName }}{{ .returnType }}(internal.New{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }}, ms.state)) }` const oneOfTypeAccessorTemplate = `// {{ .typeFuncName }} returns the type of the {{ .lowerOriginFieldName }} for this {{ .structName }}. @@ -78,7 +85,7 @@ const oneOfTypeAccessorTemplate = `// {{ .typeFuncName }} returns the type of th func (ms {{ .structName }}) {{ .typeFuncName }}() {{ .typeName }} { switch ms.{{ .origAccessor }}.{{ .originFieldName }}.(type) { {{- range .values }} - {{ .GenerateTypeSwitchCase $.oneOfField }} + {{ .GenerateTypeSwitchCase $.baseStruct $.oneOfField }} {{- end }} } return {{ .typeName }}Empty @@ -108,7 +115,7 @@ func (ms {{ .structName }}) {{ .fieldName }}() {{ .returnType }} { if !ok { return {{ .returnType }}{} } - return new{{ .returnType }}(v.{{ .fieldName }}) + return new{{ .returnType }}(v.{{ .fieldName }}, ms.state) } // SetEmpty{{ .fieldName }} sets an empty {{ .lowerFieldName }} to this {{ .structName }}. @@ -117,9 +124,10 @@ func (ms {{ .structName }}) {{ .fieldName }}() {{ .returnType }} { // // Calling this function on zero-initialized {{ .structName }} will cause a panic. func (ms {{ .structName }}) SetEmpty{{ .fieldName }}() {{ .returnType }} { + ms.state.AssertMutable() val := &{{ .originFieldPackageName }}.{{ .fieldName }}{} ms.orig.{{ .originOneOfFieldName }} = &{{ .originStructType }}{{ "{" }}{{ .fieldName }}: val} - return new{{ .returnType }}(val) + return new{{ .returnType }}(val, ms.state) }` const accessorsOneOfMessageTestTemplate = `func Test{{ .structName }}_{{ .fieldName }}(t *testing.T) { @@ -127,6 +135,8 @@ const accessorsOneOfMessageTestTemplate = `func Test{{ .structName }}_{{ .fieldN fillTest{{ .returnType }}(ms.SetEmpty{{ .fieldName }}()) assert.Equal(t, {{ .typeName }}, ms.{{ .originOneOfTypeFuncName }}()) assert.Equal(t, generateTest{{ .returnType }}(), ms.{{ .fieldName }}()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { new{{ .structName }}(&{{ .originStructName }}{}, &sharedState).SetEmpty{{ .fieldName }}() }) } func Test{{ .structName }}_CopyTo_{{ .fieldName }}(t *testing.T) { @@ -135,6 +145,8 @@ func Test{{ .structName }}_CopyTo_{{ .fieldName }}(t *testing.T) { dest := New{{ .structName }}() ms.CopyTo(dest) assert.Equal(t, ms, dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(new{{ .structName }}(&{{ .originStructName }}{}, &sharedState)) }) }` const copyToValueOneOfMessageTemplate = ` case {{ .typeName }}: @@ -147,6 +159,7 @@ func (ms {{ .structName }}) {{ .accessorFieldName }}() {{ .returnType }} { // Set{{ .accessorFieldName }} replaces the {{ .lowerFieldName }} associated with this {{ .structName }}. func (ms {{ .structName }}) Set{{ .accessorFieldName }}(v {{ .returnType }}) { + ms.state.AssertMutable() ms.orig.{{ .originOneOfFieldName }} = &{{ .originStructType }}{ {{ .originFieldName }}: v, } @@ -158,6 +171,8 @@ const accessorsOneOfPrimitiveTestTemplate = `func Test{{ .structName }}_{{ .acce ms.Set{{ .accessorFieldName }}({{ .testValue }}) assert.Equal(t, {{ .testValue }}, ms.{{ .accessorFieldName }}()) assert.Equal(t, {{ .typeName }}, ms.{{ .originOneOfTypeFuncName }}()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { new{{ .structName }}(&{{ .originStructName }}{}, &sharedState).Set{{ .accessorFieldName }}({{ .testValue }}) }) }` const accessorsPrimitiveTestTemplate = `func Test{{ .structName }}_{{ .fieldName }}(t *testing.T) { @@ -165,6 +180,8 @@ const accessorsPrimitiveTestTemplate = `func Test{{ .structName }}_{{ .fieldName assert.Equal(t, {{ .defaultVal }}, ms.{{ .fieldName }}()) ms.Set{{ .fieldName }}({{ .testValue }}) assert.Equal(t, {{ .testValue }}, ms.{{ .fieldName }}()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { new{{ .structName }}(&{{ .originStructName }}{}, &sharedState).Set{{ .fieldName }}({{ .testValue }}) }) }` const accessorsPrimitiveTypedTemplate = `// {{ .fieldName }} returns the {{ .lowerFieldName }} associated with this {{ .structName }}. @@ -174,6 +191,7 @@ func (ms {{ .structName }}) {{ .fieldName }}() {{ .packageName }}{{ .returnType // Set{{ .fieldName }} replaces the {{ .lowerFieldName }} associated with this {{ .structName }}. func (ms {{ .structName }}) Set{{ .fieldName }}(v {{ .packageName }}{{ .returnType }}) { + ms.state.AssertMutable() ms.orig.{{ .originFieldName }} = {{ .rawType }}(v) }` @@ -205,11 +223,13 @@ func (ms {{ .structName }}) Has{{ .fieldName }}() bool { // Set{{ .fieldName }} replaces the {{ .lowerFieldName }} associated with this {{ .structName }}. func (ms {{ .structName }}) Set{{ .fieldName }}(v {{ .returnType }}) { + ms.state.AssertMutable() ms.orig.{{ .fieldName }}_ = &{{ .originStructType }}{{ "{" }}{{ .fieldName }}: v} } // Remove{{ .fieldName }} removes the {{ .lowerFieldName }} associated with this {{ .structName }}. func (ms {{ .structName }}) Remove{{ .fieldName }}() { + ms.state.AssertMutable() ms.orig.{{ .fieldName }}_ = nil }` @@ -224,13 +244,13 @@ const accessorsOptionalPrimitiveTestTemplate = `func Test{{ .structName }}_{{ .f }` type baseField interface { - GenerateAccessors(ms baseStruct) string + GenerateAccessors(ms *messageValueStruct) string - GenerateAccessorsTest(ms baseStruct) string + GenerateAccessorsTest(ms *messageValueStruct) string - GenerateSetWithTestValue(ms baseStruct) string + GenerateSetWithTestValue(ms *messageValueStruct) string - GenerateCopyToValue(ms baseStruct) string + GenerateCopyToValue(ms *messageValueStruct) string } type sliceField struct { @@ -238,7 +258,7 @@ type sliceField struct { returnSlice baseSlice } -func (sf *sliceField) GenerateAccessors(ms baseStruct) string { +func (sf *sliceField) GenerateAccessors(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("accessorSliceTemplate").Parse(accessorSliceTemplate)) if err := t.Execute(sb, sf.templateFields(ms)); err != nil { @@ -247,7 +267,7 @@ func (sf *sliceField) GenerateAccessors(ms baseStruct) string { return sb.String() } -func (sf *sliceField) GenerateAccessorsTest(ms baseStruct) string { +func (sf *sliceField) GenerateAccessorsTest(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsSliceTestTemplate").Parse(accessorsSliceTestTemplate)) if err := t.Execute(sb, sf.templateFields(ms)); err != nil { @@ -256,7 +276,7 @@ func (sf *sliceField) GenerateAccessorsTest(ms baseStruct) string { return sb.String() } -func (sf *sliceField) GenerateSetWithTestValue(ms baseStruct) string { +func (sf *sliceField) GenerateSetWithTestValue(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("setTestValueTemplate").Parse(setTestValueTemplate)) if err := t.Execute(sb, sf.templateFields(ms)); err != nil { @@ -265,24 +285,25 @@ func (sf *sliceField) GenerateSetWithTestValue(ms baseStruct) string { return sb.String() } -func (sf *sliceField) GenerateCopyToValue(_ baseStruct) string { +func (sf *sliceField) GenerateCopyToValue(*messageValueStruct) string { return "\tms." + sf.fieldName + "().CopyTo(dest." + sf.fieldName + "())" } -func (sf *sliceField) templateFields(ms baseStruct) map[string]any { +func (sf *sliceField) templateFields(ms *messageValueStruct) map[string]any { return map[string]any{ "structName": ms.getName(), "fieldName": sf.fieldName, "packageName": func() string { - if sf.returnSlice.getPackageName() != ms.getPackageName() { + if sf.returnSlice.getPackageName() != ms.packageName { return sf.returnSlice.getPackageName() + "." } return "" }(), "returnType": sf.returnSlice.getName(), "origAccessor": origAccessor(ms), + "stateAccessor": stateAccessor(ms), "isCommon": usedByOtherDataTypes(sf.returnSlice.getPackageName()), - "isBaseStructCommon": usedByOtherDataTypes(ms.getPackageName()), + "isBaseStructCommon": usedByOtherDataTypes(ms.packageName), } } @@ -290,10 +311,10 @@ var _ baseField = (*sliceField)(nil) type messageValueField struct { fieldName string - returnMessage baseStruct + returnMessage *messageValueStruct } -func (mf *messageValueField) GenerateAccessors(ms baseStruct) string { +func (mf *messageValueField) GenerateAccessors(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsMessageValueTemplate").Parse(accessorsMessageValueTemplate)) if err := t.Execute(sb, mf.templateFields(ms)); err != nil { @@ -302,7 +323,7 @@ func (mf *messageValueField) GenerateAccessors(ms baseStruct) string { return sb.String() } -func (mf *messageValueField) GenerateAccessorsTest(ms baseStruct) string { +func (mf *messageValueField) GenerateAccessorsTest(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsMessageValueTestTemplate").Parse(accessorsMessageValueTestTemplate)) if err := t.Execute(sb, mf.templateFields(ms)); err != nil { @@ -311,7 +332,7 @@ func (mf *messageValueField) GenerateAccessorsTest(ms baseStruct) string { return sb.String() } -func (mf *messageValueField) GenerateSetWithTestValue(ms baseStruct) string { +func (mf *messageValueField) GenerateSetWithTestValue(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("setTestValueTemplate").Parse(setTestValueTemplate)) if err := t.Execute(sb, mf.templateFields(ms)); err != nil { @@ -320,24 +341,25 @@ func (mf *messageValueField) GenerateSetWithTestValue(ms baseStruct) string { return sb.String() } -func (mf *messageValueField) GenerateCopyToValue(_ baseStruct) string { +func (mf *messageValueField) GenerateCopyToValue(*messageValueStruct) string { return "\tms." + mf.fieldName + "().CopyTo(dest." + mf.fieldName + "())" } -func (mf *messageValueField) templateFields(ms baseStruct) map[string]any { +func (mf *messageValueField) templateFields(ms *messageValueStruct) map[string]any { return map[string]any{ - "isCommon": usedByOtherDataTypes(mf.returnMessage.getPackageName()), + "isCommon": usedByOtherDataTypes(mf.returnMessage.packageName), "structName": ms.getName(), "fieldName": mf.fieldName, "lowerFieldName": strings.ToLower(mf.fieldName), "returnType": mf.returnMessage.getName(), "packageName": func() string { - if mf.returnMessage.getPackageName() != ms.getPackageName() { - return mf.returnMessage.getPackageName() + "." + if mf.returnMessage.packageName != ms.packageName { + return mf.returnMessage.packageName + "." } return "" }(), - "origAccessor": origAccessor(ms), + "origAccessor": origAccessor(ms), + "stateAccessor": stateAccessor(ms), } } @@ -350,7 +372,7 @@ type primitiveField struct { testVal string } -func (pf *primitiveField) GenerateAccessors(ms baseStruct) string { +func (pf *primitiveField) GenerateAccessors(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsPrimitiveTemplate").Parse(accessorsPrimitiveTemplate)) if err := t.Execute(sb, pf.templateFields(ms)); err != nil { @@ -359,7 +381,7 @@ func (pf *primitiveField) GenerateAccessors(ms baseStruct) string { return sb.String() } -func (pf *primitiveField) GenerateAccessorsTest(ms baseStruct) string { +func (pf *primitiveField) GenerateAccessorsTest(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsPrimitiveTestTemplate").Parse(accessorsPrimitiveTestTemplate)) if err := t.Execute(sb, pf.templateFields(ms)); err != nil { @@ -368,24 +390,26 @@ func (pf *primitiveField) GenerateAccessorsTest(ms baseStruct) string { return sb.String() } -func (pf *primitiveField) GenerateSetWithTestValue(_ baseStruct) string { +func (pf *primitiveField) GenerateSetWithTestValue(*messageValueStruct) string { return "\ttv.orig." + pf.fieldName + " = " + pf.testVal } -func (pf *primitiveField) GenerateCopyToValue(_ baseStruct) string { +func (pf *primitiveField) GenerateCopyToValue(*messageValueStruct) string { return "\tdest.Set" + pf.fieldName + "(ms." + pf.fieldName + "())" } -func (pf *primitiveField) templateFields(ms baseStruct) map[string]any { +func (pf *primitiveField) templateFields(ms *messageValueStruct) map[string]any { return map[string]any{ - "structName": ms.getName(), - "packageName": "", - "defaultVal": pf.defaultVal, - "fieldName": pf.fieldName, - "lowerFieldName": strings.ToLower(pf.fieldName), - "testValue": pf.testVal, - "returnType": pf.returnType, - "origAccessor": origAccessor(ms), + "structName": ms.getName(), + "packageName": "", + "defaultVal": pf.defaultVal, + "fieldName": pf.fieldName, + "lowerFieldName": strings.ToLower(pf.fieldName), + "testValue": pf.testVal, + "returnType": pf.returnType, + "origAccessor": origAccessor(ms), + "stateAccessor": stateAccessor(ms), + "originStructName": ms.originFullName, } } @@ -406,7 +430,7 @@ type primitiveTypedField struct { returnType *primitiveType } -func (ptf *primitiveTypedField) GenerateAccessors(ms baseStruct) string { +func (ptf *primitiveTypedField) GenerateAccessors(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsPrimitiveTypedTemplate").Parse(accessorsPrimitiveTypedTemplate)) if err := t.Execute(sb, ptf.templateFields(ms)); err != nil { @@ -415,7 +439,7 @@ func (ptf *primitiveTypedField) GenerateAccessors(ms baseStruct) string { return sb.String() } -func (ptf *primitiveTypedField) GenerateAccessorsTest(ms baseStruct) string { +func (ptf *primitiveTypedField) GenerateAccessorsTest(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsPrimitiveTypedTestTemplate").Parse(accessorsPrimitiveTypedTestTemplate)) if err := t.Execute(sb, ptf.templateFields(ms)); err != nil { @@ -424,7 +448,7 @@ func (ptf *primitiveTypedField) GenerateAccessorsTest(ms baseStruct) string { return sb.String() } -func (ptf *primitiveTypedField) GenerateSetWithTestValue(_ baseStruct) string { +func (ptf *primitiveTypedField) GenerateSetWithTestValue(*messageValueStruct) string { originFieldName := ptf.fieldName if ptf.originFieldName != "" { originFieldName = ptf.originFieldName @@ -432,16 +456,16 @@ func (ptf *primitiveTypedField) GenerateSetWithTestValue(_ baseStruct) string { return "\ttv.orig." + originFieldName + " = " + ptf.returnType.testVal } -func (ptf *primitiveTypedField) GenerateCopyToValue(_ baseStruct) string { +func (ptf *primitiveTypedField) GenerateCopyToValue(*messageValueStruct) string { return "\tdest.Set" + ptf.fieldName + "(ms." + ptf.fieldName + "())" } -func (ptf *primitiveTypedField) templateFields(ms baseStruct) map[string]any { +func (ptf *primitiveTypedField) templateFields(ms *messageValueStruct) map[string]any { return map[string]any{ "structName": ms.getName(), "defaultVal": ptf.returnType.defaultVal, "packageName": func() string { - if ptf.returnType.packageName != ms.getPackageName() { + if ptf.returnType.packageName != ms.packageName { return ptf.returnType.packageName + "." } return "" @@ -472,7 +496,7 @@ type primitiveSliceField struct { testVal string } -func (psf *primitiveSliceField) GenerateAccessors(ms baseStruct) string { +func (psf *primitiveSliceField) GenerateAccessors(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsPrimitiveSliceTemplate").Parse(accessorsPrimitiveSliceTemplate)) if err := t.Execute(sb, psf.templateFields(ms)); err != nil { @@ -481,7 +505,7 @@ func (psf *primitiveSliceField) GenerateAccessors(ms baseStruct) string { return sb.String() } -func (psf *primitiveSliceField) GenerateAccessorsTest(ms baseStruct) string { +func (psf *primitiveSliceField) GenerateAccessorsTest(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsPrimitiveSliceTestTemplate").Parse(accessorsPrimitiveSliceTestTemplate)) if err := t.Execute(sb, psf.templateFields(ms)); err != nil { @@ -490,19 +514,19 @@ func (psf *primitiveSliceField) GenerateAccessorsTest(ms baseStruct) string { return sb.String() } -func (psf *primitiveSliceField) GenerateSetWithTestValue(_ baseStruct) string { +func (psf *primitiveSliceField) GenerateSetWithTestValue(*messageValueStruct) string { return "\ttv.orig." + psf.fieldName + " = " + psf.testVal } -func (psf *primitiveSliceField) GenerateCopyToValue(_ baseStruct) string { +func (psf *primitiveSliceField) GenerateCopyToValue(*messageValueStruct) string { return "\tms." + psf.fieldName + "().CopyTo(dest." + psf.fieldName + "())" } -func (psf *primitiveSliceField) templateFields(ms baseStruct) map[string]any { +func (psf *primitiveSliceField) templateFields(ms *messageValueStruct) map[string]any { return map[string]any{ "structName": ms.getName(), "packageName": func() string { - if psf.returnPackageName != ms.getPackageName() { + if psf.returnPackageName != ms.packageName { return psf.returnPackageName + "." } return "" @@ -513,13 +537,13 @@ func (psf *primitiveSliceField) templateFields(ms baseStruct) map[string]any { "lowerFieldName": strings.ToLower(psf.fieldName), "testValue": psf.testVal, "origAccessor": origAccessor(ms), + "stateAccessor": stateAccessor(ms), } } var _ baseField = (*primitiveSliceField)(nil) type oneOfField struct { - originTypePrefix string originFieldName string typeName string testValueIdx int @@ -527,7 +551,7 @@ type oneOfField struct { omitOriginFieldNameInNames bool } -func (of *oneOfField) GenerateAccessors(ms baseStruct) string { +func (of *oneOfField) GenerateAccessors(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("oneOfTypeAccessorTemplate").Parse(oneOfTypeAccessorTemplate)) if err := t.Execute(sb, of.templateFields(ms)); err != nil { @@ -544,7 +568,7 @@ func (of *oneOfField) typeFuncName() string { return of.originFieldName + typeSuffix } -func (of *oneOfField) GenerateAccessorsTest(ms baseStruct) string { +func (of *oneOfField) GenerateAccessorsTest(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("oneOfTypeAccessorTestTemplate").Parse(oneOfTypeAccessorTestTemplate)) if err := t.Execute(sb, of.templateFields(ms)); err != nil { @@ -553,11 +577,11 @@ func (of *oneOfField) GenerateAccessorsTest(ms baseStruct) string { return sb.String() } -func (of *oneOfField) GenerateSetWithTestValue(_ baseStruct) string { - return of.values[of.testValueIdx].GenerateSetWithTestValue(of) +func (of *oneOfField) GenerateSetWithTestValue(ms *messageValueStruct) string { + return of.values[of.testValueIdx].GenerateSetWithTestValue(ms, of) } -func (of *oneOfField) GenerateCopyToValue(ms baseStruct) string { +func (of *oneOfField) GenerateCopyToValue(ms *messageValueStruct) string { sb := &bytes.Buffer{} sb.WriteString("\tswitch ms." + of.typeFuncName() + "() {\n") for _, v := range of.values { @@ -567,7 +591,7 @@ func (of *oneOfField) GenerateCopyToValue(ms baseStruct) string { return sb.String() } -func (of *oneOfField) templateFields(ms baseStruct) map[string]any { +func (of *oneOfField) templateFields(ms *messageValueStruct) map[string]any { return map[string]any{ "baseStruct": ms, "oneOfField": of, @@ -577,19 +601,20 @@ func (of *oneOfField) templateFields(ms baseStruct) map[string]any { "originFieldName": of.originFieldName, "lowerOriginFieldName": strings.ToLower(of.originFieldName), "origAccessor": origAccessor(ms), + "stateAccessor": stateAccessor(ms), "values": of.values, - "originTypePrefix": of.originTypePrefix, + "originTypePrefix": ms.originFullName + "_", } } var _ baseField = (*oneOfField)(nil) type oneOfValue interface { - GenerateAccessors(ms baseStruct, of *oneOfField) string - GenerateTests(ms baseStruct, of *oneOfField) string - GenerateSetWithTestValue(of *oneOfField) string - GenerateCopyToValue(ms baseStruct, of *oneOfField, sb *bytes.Buffer) - GenerateTypeSwitchCase(of *oneOfField) string + GenerateAccessors(ms *messageValueStruct, of *oneOfField) string + GenerateTests(ms *messageValueStruct, of *oneOfField) string + GenerateSetWithTestValue(ms *messageValueStruct, of *oneOfField) string + GenerateCopyToValue(ms *messageValueStruct, of *oneOfField, sb *bytes.Buffer) + GenerateTypeSwitchCase(ms *messageValueStruct, of *oneOfField) string } type oneOfPrimitiveValue struct { @@ -600,7 +625,7 @@ type oneOfPrimitiveValue struct { originFieldName string } -func (opv *oneOfPrimitiveValue) GenerateAccessors(ms baseStruct, of *oneOfField) string { +func (opv *oneOfPrimitiveValue) GenerateAccessors(ms *messageValueStruct, of *oneOfField) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsOneOfPrimitiveTemplate").Parse(accessorsOneOfPrimitiveTemplate)) if err := t.Execute(sb, opv.templateFields(ms, of)); err != nil { @@ -609,7 +634,7 @@ func (opv *oneOfPrimitiveValue) GenerateAccessors(ms baseStruct, of *oneOfField) return sb.String() } -func (opv *oneOfPrimitiveValue) GenerateTests(ms baseStruct, of *oneOfField) string { +func (opv *oneOfPrimitiveValue) GenerateTests(ms *messageValueStruct, of *oneOfField) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsOneOfPrimitiveTestTemplate").Parse(accessorsOneOfPrimitiveTestTemplate)) if err := t.Execute(sb, opv.templateFields(ms, of)); err != nil { @@ -626,22 +651,22 @@ func (opv *oneOfPrimitiveValue) accessorFieldName(of *oneOfField) string { return opv.fieldName + of.originFieldName } -func (opv *oneOfPrimitiveValue) GenerateSetWithTestValue(of *oneOfField) string { - return "\ttv.orig." + of.originFieldName + " = &" + of.originTypePrefix + opv.originFieldName + "{" + opv. +func (opv *oneOfPrimitiveValue) GenerateSetWithTestValue(ms *messageValueStruct, of *oneOfField) string { + return "\ttv.orig." + of.originFieldName + " = &" + ms.originFullName + "_" + opv.originFieldName + "{" + opv. originFieldName + ":" + opv.testVal + "}" } -func (opv *oneOfPrimitiveValue) GenerateCopyToValue(_ baseStruct, of *oneOfField, sb *bytes.Buffer) { +func (opv *oneOfPrimitiveValue) GenerateCopyToValue(_ *messageValueStruct, of *oneOfField, sb *bytes.Buffer) { sb.WriteString("\tcase " + of.typeName + opv.fieldName + ":\n") sb.WriteString("\tdest.Set" + opv.accessorFieldName(of) + "(ms." + opv.accessorFieldName(of) + "())\n") } -func (opv *oneOfPrimitiveValue) GenerateTypeSwitchCase(of *oneOfField) string { - return "\tcase *" + of.originTypePrefix + opv.originFieldName + ":\n" + +func (opv *oneOfPrimitiveValue) GenerateTypeSwitchCase(ms *messageValueStruct, of *oneOfField) string { + return "\tcase *" + ms.originFullName + "_" + opv.originFieldName + ":\n" + "\t\treturn " + of.typeName + opv.fieldName } -func (opv *oneOfPrimitiveValue) templateFields(ms baseStruct, of *oneOfField) map[string]any { +func (opv *oneOfPrimitiveValue) templateFields(ms *messageValueStruct, of *oneOfField) map[string]any { return map[string]any{ "structName": ms.getName(), "defaultVal": opv.defaultVal, @@ -654,7 +679,8 @@ func (opv *oneOfPrimitiveValue) templateFields(ms baseStruct, of *oneOfField) ma "returnType": opv.returnType, "originFieldName": opv.originFieldName, "originOneOfFieldName": of.originFieldName, - "originStructType": of.originTypePrefix + opv.originFieldName, + "originStructName": ms.originFullName, + "originStructType": ms.originFullName + "_" + opv.originFieldName, } } @@ -666,7 +692,7 @@ type oneOfMessageValue struct { returnMessage *messageValueStruct } -func (omv *oneOfMessageValue) GenerateAccessors(ms baseStruct, of *oneOfField) string { +func (omv *oneOfMessageValue) GenerateAccessors(ms *messageValueStruct, of *oneOfField) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsOneOfMessageTemplate").Parse(accessorsOneOfMessageTemplate)) if err := t.Execute(sb, omv.templateFields(ms, of)); err != nil { @@ -675,7 +701,7 @@ func (omv *oneOfMessageValue) GenerateAccessors(ms baseStruct, of *oneOfField) s return sb.String() } -func (omv *oneOfMessageValue) GenerateTests(ms baseStruct, of *oneOfField) string { +func (omv *oneOfMessageValue) GenerateTests(ms *messageValueStruct, of *oneOfField) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsOneOfMessageTestTemplate").Parse(accessorsOneOfMessageTestTemplate)) if err := t.Execute(sb, omv.templateFields(ms, of)); err != nil { @@ -685,13 +711,13 @@ func (omv *oneOfMessageValue) GenerateTests(ms baseStruct, of *oneOfField) strin return sb.String() } -func (omv *oneOfMessageValue) GenerateSetWithTestValue(of *oneOfField) string { - return "\ttv.orig." + of.originFieldName + " = &" + of.originTypePrefix + omv.fieldName + "{" + omv. +func (omv *oneOfMessageValue) GenerateSetWithTestValue(ms *messageValueStruct, of *oneOfField) string { + return "\ttv.orig." + of.originFieldName + " = &" + ms.originFullName + "_" + omv.fieldName + "{" + omv. fieldName + ": &" + omv.originFieldPackageName + "." + omv.fieldName + "{}}\n" + - "\tfillTest" + omv.returnMessage.structName + "(new" + omv.fieldName + "(tv.orig.Get" + omv.fieldName + "()))" + "\tfillTest" + omv.returnMessage.structName + "(new" + omv.fieldName + "(tv.orig.Get" + omv.fieldName + "(), tv.state))" } -func (omv *oneOfMessageValue) GenerateCopyToValue(ms baseStruct, of *oneOfField, sb *bytes.Buffer) { +func (omv *oneOfMessageValue) GenerateCopyToValue(ms *messageValueStruct, of *oneOfField, sb *bytes.Buffer) { t := template.Must(template.New("copyToValueOneOfMessageTemplate").Parse(copyToValueOneOfMessageTemplate)) if err := t.Execute(sb, omv.templateFields(ms, of)); err != nil { panic(err) @@ -699,12 +725,12 @@ func (omv *oneOfMessageValue) GenerateCopyToValue(ms baseStruct, of *oneOfField, sb.WriteString("\n") } -func (omv *oneOfMessageValue) GenerateTypeSwitchCase(of *oneOfField) string { - return "\tcase *" + of.originTypePrefix + omv.fieldName + ":\n" + +func (omv *oneOfMessageValue) GenerateTypeSwitchCase(ms *messageValueStruct, of *oneOfField) string { + return "\tcase *" + ms.originFullName + "_" + omv.fieldName + ":\n" + "\t\treturn " + of.typeName + omv.fieldName } -func (omv *oneOfMessageValue) templateFields(ms baseStruct, of *oneOfField) map[string]any { +func (omv *oneOfMessageValue) templateFields(ms *messageValueStruct, of *oneOfField) map[string]any { return map[string]any{ "fieldName": omv.fieldName, "originOneOfFieldName": of.originFieldName, @@ -714,21 +740,21 @@ func (omv *oneOfMessageValue) templateFields(ms baseStruct, of *oneOfField) map[ "originOneOfTypeFuncName": of.typeFuncName(), "lowerFieldName": strings.ToLower(omv.fieldName), "originFieldPackageName": omv.originFieldPackageName, - "originStructType": of.originTypePrefix + omv.fieldName, + "originStructName": ms.originFullName, + "originStructType": ms.originFullName + "_" + omv.fieldName, } } var _ oneOfValue = (*oneOfMessageValue)(nil) type optionalPrimitiveValue struct { - fieldName string - defaultVal string - testVal string - returnType string - originTypePrefix string + fieldName string + defaultVal string + testVal string + returnType string } -func (opv *optionalPrimitiveValue) GenerateAccessors(ms baseStruct) string { +func (opv *optionalPrimitiveValue) GenerateAccessors(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsOptionalPrimitiveValueTemplate").Parse(accessorsOptionalPrimitiveValueTemplate)) if err := t.Execute(sb, opv.templateFields(ms)); err != nil { @@ -737,7 +763,7 @@ func (opv *optionalPrimitiveValue) GenerateAccessors(ms baseStruct) string { return sb.String() } -func (opv *optionalPrimitiveValue) GenerateAccessorsTest(ms baseStruct) string { +func (opv *optionalPrimitiveValue) GenerateAccessorsTest(ms *messageValueStruct) string { sb := &strings.Builder{} t := template.Must(template.New("accessorsOptionalPrimitiveTestTemplate").Parse(accessorsOptionalPrimitiveTestTemplate)) if err := t.Execute(sb, opv.templateFields(ms)); err != nil { @@ -747,17 +773,17 @@ func (opv *optionalPrimitiveValue) GenerateAccessorsTest(ms baseStruct) string { return sb.String() } -func (opv *optionalPrimitiveValue) GenerateSetWithTestValue(_ baseStruct) string { - return "\ttv.orig." + opv.fieldName + "_ = &" + opv.originTypePrefix + opv.fieldName + "{" + opv.fieldName + ":" + opv.testVal + "}" +func (opv *optionalPrimitiveValue) GenerateSetWithTestValue(ms *messageValueStruct) string { + return "\ttv.orig." + opv.fieldName + "_ = &" + ms.originFullName + "_" + opv.fieldName + "{" + opv.fieldName + ":" + opv.testVal + "}" } -func (opv *optionalPrimitiveValue) GenerateCopyToValue(_ baseStruct) string { +func (opv *optionalPrimitiveValue) GenerateCopyToValue(*messageValueStruct) string { return "if ms.Has" + opv.fieldName + "(){\n" + "\tdest.Set" + opv.fieldName + "(ms." + opv.fieldName + "())\n" + "}\n" } -func (opv *optionalPrimitiveValue) templateFields(ms baseStruct) map[string]any { +func (opv *optionalPrimitiveValue) templateFields(ms *messageValueStruct) map[string]any { return map[string]any{ "structName": ms.getName(), "packageName": "", @@ -766,15 +792,23 @@ func (opv *optionalPrimitiveValue) templateFields(ms baseStruct) map[string]any "lowerFieldName": strings.ToLower(opv.fieldName), "testValue": opv.testVal, "returnType": opv.returnType, - "originStructType": opv.originTypePrefix + opv.fieldName, + "originStructName": ms.originFullName, + "originStructType": ms.originFullName + "_" + opv.fieldName, } } var _ baseField = (*optionalPrimitiveValue)(nil) -func origAccessor(bs baseStruct) string { - if usedByOtherDataTypes(bs.getPackageName()) { +func origAccessor(bs *messageValueStruct) string { + if usedByOtherDataTypes(bs.packageName) { return "getOrig()" } return "orig" } + +func stateAccessor(bs *messageValueStruct) string { + if usedByOtherDataTypes(bs.packageName) { + return "getState()" + } + return "state" +} diff --git a/pdata/internal/cmd/pdatagen/internal/base_slices.go b/pdata/internal/cmd/pdatagen/internal/base_slices.go index 0521076d881..d556207163a 100644 --- a/pdata/internal/cmd/pdatagen/internal/base_slices.go +++ b/pdata/internal/cmd/pdatagen/internal/base_slices.go @@ -17,17 +17,19 @@ const sliceTemplate = `// {{ .structName }} logically represents a slice of {{ . // Important: zero-initialized instance is not valid for use. type {{ .structName }} struct { orig *[]{{ .originElementType }} + state *internal.State } -func new{{ .structName }}(orig *[]{{ .originElementType }}) {{ .structName }} { - return {{ .structName }}{orig} +func new{{ .structName }}(orig *[]{{ .originElementType }}, state *internal.State) {{ .structName }} { + return {{ .structName }}{orig: orig, state: state} } // New{{ .structName }} creates a {{ .structName }} with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func New{{ .structName }}() {{ .structName }} { orig := []{{ .originElementType }}(nil) - return new{{ .structName }}(&orig) + state := internal.StateMutable + return new{{ .structName }}(&orig, &state) } // Len returns the number of elements in the slice. @@ -60,6 +62,7 @@ func (es {{ .structName }}) At(i int) {{ .elementName }} { // // Here should set all the values for e. // } func (es {{ .structName }}) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -73,6 +76,7 @@ func (es {{ .structName }}) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty {{ .elementName }}. // It returns the newly added {{ .elementName }}. func (es {{ .structName }}) AppendEmpty() {{ .elementName }} { + es.state.AssertMutable() *es.orig = append(*es.orig, {{ .emptyOriginElement }}) return es.At(es.Len() - 1) } @@ -80,6 +84,8 @@ func (es {{ .structName }}) AppendEmpty() {{ .elementName }} { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es {{ .structName }}) MoveAndAppendTo(dest {{ .structName }}) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -92,6 +98,7 @@ func (es {{ .structName }}) MoveAndAppendTo(dest {{ .structName }}) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es {{ .structName }}) RemoveIf(f func({{ .elementName }}) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -105,13 +112,13 @@ func (es {{ .structName }}) RemoveIf(f func({{ .elementName }}) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es {{ .structName }}) CopyTo(dest {{ .structName }}) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { @@ -119,7 +126,7 @@ func (es {{ .structName }}) CopyTo(dest {{ .structName }}) { {{- if eq .type "sliceOfPtrs" }} for i := range *es.orig { - new{{ .elementName }}((*es.orig)[i]).CopyTo(new{{ .elementName }}((*dest.orig)[i])) + new{{ .elementName }}((*es.orig)[i], es.state).CopyTo(new{{ .elementName }}((*dest.orig)[i], dest.state)) } return } @@ -127,7 +134,7 @@ func (es {{ .structName }}) CopyTo(dest {{ .structName }}) { wrappers := make([]*{{ .originName }}, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - new{{ .elementName }}((*es.orig)[i]).CopyTo(new{{ .elementName }}(wrappers[i])) + new{{ .elementName }}((*es.orig)[i], es.state).CopyTo(new{{ .elementName }}(wrappers[i], dest.state)) } *dest.orig = wrappers @@ -136,7 +143,7 @@ func (es {{ .structName }}) CopyTo(dest {{ .structName }}) { (*dest.orig) = make([]{{ .originElementType }}, srcLen) } for i := range *es.orig { - {{ .newElement }}.CopyTo(new{{ .elementName }}(&(*dest.orig)[i])) + {{ .newElement }}.CopyTo(new{{ .elementName }}(&(*dest.orig)[i], dest.state)) } {{- end }} } @@ -146,6 +153,7 @@ func (es {{ .structName }}) CopyTo(dest {{ .structName }}) { // provided less function so that two instances of {{ .structName }} // can be compared. func (es {{ .structName }}) Sort(less func(a, b {{ .elementName }}) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } {{- end }}` @@ -153,7 +161,8 @@ func (es {{ .structName }}) Sort(less func(a, b {{ .elementName }}) bool) { const sliceTestTemplate = `func Test{{ .structName }}(t *testing.T) { es := New{{ .structName }}() assert.Equal(t, 0, es.Len()) - es = new{{ .structName }}(&[]{{ .originElementType }}{}) + state := internal.StateMutable + es = new{{ .structName }}(&[]{{ .originElementType }}{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := New{{ .elementName }}() @@ -167,6 +176,19 @@ const sliceTestTemplate = `func Test{{ .structName }}(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func Test{{ .structName }}ReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := new{{ .structName }}(&[]{{ .originElementType }}{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := New{{ .structName }}() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func Test{{ .structName }}_CopyTo(t *testing.T) { dest := New{{ .structName }}() // Test CopyTo to empty @@ -324,11 +346,11 @@ func (ss *sliceOfPtrs) templateFields() map[string]any { "originName": ss.element.originFullName, "originElementType": "*" + ss.element.originFullName, "emptyOriginElement": "&" + ss.element.originFullName + "{}", - "newElement": "new" + ss.element.structName + "((*es.orig)[i])", + "newElement": "new" + ss.element.structName + "((*es.orig)[i], es.state)", } } -func (ss *sliceOfPtrs) generateInternal(_ *bytes.Buffer) {} +func (ss *sliceOfPtrs) generateInternal(*bytes.Buffer) {} var _ baseStruct = (*sliceOfPtrs)(nil) @@ -376,10 +398,10 @@ func (ss *sliceOfValues) templateFields() map[string]any { "originName": ss.element.originFullName, "originElementType": ss.element.originFullName, "emptyOriginElement": ss.element.originFullName + "{}", - "newElement": "new" + ss.element.structName + "(&(*es.orig)[i])", + "newElement": "new" + ss.element.structName + "(&(*es.orig)[i], es.state)", } } -func (ss *sliceOfValues) generateInternal(_ *bytes.Buffer) {} +func (ss *sliceOfValues) generateInternal(*bytes.Buffer) {} var _ baseStruct = (*sliceOfValues)(nil) diff --git a/pdata/internal/cmd/pdatagen/internal/base_structs.go b/pdata/internal/cmd/pdatagen/internal/base_structs.go index d96657028a7..859bb4d7c05 100644 --- a/pdata/internal/cmd/pdatagen/internal/base_structs.go +++ b/pdata/internal/cmd/pdatagen/internal/base_structs.go @@ -21,14 +21,15 @@ type {{ .structName }} internal.{{ .structName }} {{- else }} type {{ .structName }} struct { orig *{{ .originName }} + state *internal.State } {{- end }} -func new{{ .structName }}(orig *{{ .originName }}) {{ .structName }} { +func new{{ .structName }}(orig *{{ .originName }}, state *internal.State) {{ .structName }} { {{- if .isCommon }} - return {{ .structName }}(internal.New{{ .structName }}(orig)) + return {{ .structName }}(internal.New{{ .structName }}(orig, state)) {{- else }} - return {{ .structName }}{orig} + return {{ .structName }}{orig: orig, state: state} {{- end }} } @@ -37,12 +38,15 @@ func new{{ .structName }}(orig *{{ .originName }}) {{ .structName }} { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func New{{ .structName }}() {{ .structName }} { - return new{{ .structName }}(&{{ .originName }}{}) + state := internal.StateMutable + return new{{ .structName }}(&{{ .originName }}{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms {{ .structName }}) MoveTo(dest {{ .structName }}) { + ms.{{- if .isCommon }}getState(){{ else }}state{{ end }}.AssertMutable() + dest.{{- if .isCommon }}getState(){{ else }}state{{ end }}.AssertMutable() *dest.{{ .origAccessor }} = *ms.{{ .origAccessor }} *ms.{{ .origAccessor }} = {{ .originName }}{} } @@ -51,6 +55,10 @@ func (ms {{ .structName }}) MoveTo(dest {{ .structName }}) { func (ms {{ .structName }}) getOrig() *{{ .originName }} { return internal.GetOrig{{ .structName }}(internal.{{ .structName }}(ms)) } + +func (ms {{ .structName }}) getState() *internal.State { + return internal.Get{{ .structName }}State(internal.{{ .structName }}(ms)) +} {{- end }} {{ range .fields -}} @@ -59,9 +67,10 @@ func (ms {{ .structName }}) getOrig() *{{ .originName }} { // CopyTo copies all properties from the current struct overriding the destination. func (ms {{ .structName }}) CopyTo(dest {{ .structName }}) { -{{- range .fields }} -{{ .GenerateCopyToValue $.messageStruct }} -{{- end }} + dest.{{- if .isCommon }}getState(){{ else }}state{{ end }}.AssertMutable() + {{- range .fields }} + {{ .GenerateCopyToValue $.messageStruct }} + {{- end }} }` const messageValueTestTemplate = ` @@ -71,6 +80,9 @@ func Test{{ .structName }}_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, New{{ .structName }}(), ms) assert.Equal(t, {{ .generateTestData }}, dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(new{{ .structName }}(&{{ .originName }}{}, &sharedState)) }) + assert.Panics(t, func() { new{{ .structName }}(&{{ .originName }}{}, &sharedState).MoveTo(dest) }) } func Test{{ .structName }}_CopyTo(t *testing.T) { @@ -81,6 +93,8 @@ func Test{{ .structName }}_CopyTo(t *testing.T) { orig = {{ .generateTestData }} orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(new{{ .structName }}(&{{ .originName }}{}, &sharedState)) }) } {{ range .fields }} @@ -90,8 +104,9 @@ func Test{{ .structName }}_CopyTo(t *testing.T) { const messageValueGenerateTestTemplate = `func {{ upperIfInternal "g" }}enerateTest{{ .structName }}() {{ .structName }} { {{- if .isCommon }} orig := {{ .originName }}{} + state := StateMutable {{- end }} - tv := New{{ .structName }}({{ if .isCommon }}&orig{{ end }}) + tv := New{{ .structName }}({{ if .isCommon }}&orig, &state{{ end }}) {{ upperIfInternal "f" }}illTest{{ .structName }}(tv) return tv } @@ -105,19 +120,23 @@ func {{ upperIfInternal "f" }}illTest{{ .structName }}(tv {{ .structName }}) { const messageValueAliasTemplate = ` type {{ .structName }} struct { orig *{{ .originName }} + state *State } func GetOrig{{ .structName }}(ms {{ .structName }}) *{{ .originName }} { return ms.orig } -func New{{ .structName }}(orig *{{ .originName }}) {{ .structName }} { - return {{ .structName }}{orig: orig} +func Get{{ .structName }}State(ms {{ .structName }}) *State { + return ms.state +} + +func New{{ .structName }}(orig *{{ .originName }}, state *State) {{ .structName }} { + return {{ .structName }}{orig: orig, state: state} }` type baseStruct interface { getName() string - getPackageName() string generateStruct(sb *bytes.Buffer) generateTests(sb *bytes.Buffer) generateTestValueHelpers(sb *bytes.Buffer) @@ -138,10 +157,6 @@ func (ms *messageValueStruct) getName() string { return ms.structName } -func (ms *messageValueStruct) getPackageName() string { - return ms.packageName -} - func (ms *messageValueStruct) generateStruct(sb *bytes.Buffer) { t := template.Must(template.New("messageValueTemplate").Parse(messageValueTemplate)) if err := t.Execute(sb, ms.templateFields()); err != nil { diff --git a/pdata/internal/cmd/pdatagen/internal/packages.go b/pdata/internal/cmd/pdatagen/internal/packages.go index b8c7fab272a..f44b597708a 100644 --- a/pdata/internal/cmd/pdatagen/internal/packages.go +++ b/pdata/internal/cmd/pdatagen/internal/packages.go @@ -119,6 +119,9 @@ func (p *Package) GenerateInternalFiles() error { // Add imports sb.WriteString("import (" + newLine) for _, imp := range p.imports { + if imp == `"go.opentelemetry.io/collector/pdata/internal"` { + continue + } if imp != "" { sb.WriteString("\t" + imp + newLine) } else { diff --git a/pdata/internal/cmd/pdatagen/internal/pmetric_package.go b/pdata/internal/cmd/pdatagen/internal/pmetric_package.go index 88dfc3a4dec..95487c00f8f 100644 --- a/pdata/internal/cmd/pdatagen/internal/pmetric_package.go +++ b/pdata/internal/cmd/pdatagen/internal/pmetric_package.go @@ -118,7 +118,6 @@ var metric = &messageValueStruct{ &oneOfField{ typeName: "MetricType", originFieldName: "Data", - originTypePrefix: "otlpmetrics.Metric_", testValueIdx: 1, // Sum omitOriginFieldNameInNames: true, values: []oneOfValue{ @@ -231,10 +230,9 @@ var numberDataPoint = &messageValueStruct{ startTimeField, timeField, &oneOfField{ - typeName: "NumberDataPointValueType", - originFieldName: "Value", - originTypePrefix: "otlpmetrics.NumberDataPoint_", - testValueIdx: 0, // Double + typeName: "NumberDataPointValueType", + originFieldName: "Value", + testValueIdx: 0, // Double values: []oneOfValue{ &oneOfPrimitiveValue{ fieldName: "Double", @@ -271,25 +269,13 @@ var histogramDataPoint = &messageValueStruct{ startTimeField, timeField, countField, - optionalDoubleSumField, bucketCountsField, explicitBoundsField, exemplarsField, dataPointFlagsField, - &optionalPrimitiveValue{ - fieldName: "Min", - originTypePrefix: "otlpmetrics.HistogramDataPoint_", - returnType: "float64", - defaultVal: "float64(0.0)", - testVal: "float64(9.23)", - }, - &optionalPrimitiveValue{ - fieldName: "Max", - originTypePrefix: "otlpmetrics.HistogramDataPoint_", - returnType: "float64", - defaultVal: "float64(0.0)", - testVal: "float64(182.55)", - }, + sumField, + minField, + maxField, }, } @@ -310,13 +296,6 @@ var exponentialHistogramDataPoint = &messageValueStruct{ startTimeField, timeField, countField, - &optionalPrimitiveValue{ - fieldName: "Sum", - originTypePrefix: "otlpmetrics.ExponentialHistogramDataPoint_", - returnType: "float64", - defaultVal: "float64(0.0)", - testVal: "float64(17.13)", - }, &primitiveField{ fieldName: "Scale", returnType: "int32", @@ -339,19 +318,14 @@ var exponentialHistogramDataPoint = &messageValueStruct{ }, exemplarsField, dataPointFlagsField, - &optionalPrimitiveValue{ - fieldName: "Min", - originTypePrefix: "otlpmetrics.ExponentialHistogramDataPoint_", - returnType: "float64", - defaultVal: "float64(0.0)", - testVal: "float64(9.23)", - }, - &optionalPrimitiveValue{ - fieldName: "Max", - originTypePrefix: "otlpmetrics.ExponentialHistogramDataPoint_", - returnType: "float64", - defaultVal: "float64(0.0)", - testVal: "float64(182.55)", + sumField, + minField, + maxField, + &primitiveField{ + fieldName: "ZeroThreshold", + returnType: "float64", + defaultVal: "float64(0.0)", + testVal: "float64(0.5)", }, }, } @@ -424,10 +398,9 @@ var exemplar = &messageValueStruct{ fields: []baseField{ timeField, &oneOfField{ - typeName: "ExemplarValueType", - originFieldName: "Value", - originTypePrefix: "otlpmetrics.Exemplar_", - testValueIdx: 1, // Int + typeName: "ExemplarValueType", + originFieldName: "Value", + testValueIdx: 1, // Int values: []oneOfValue{ &oneOfPrimitiveValue{ fieldName: "Double", @@ -532,10 +505,22 @@ var aggregationTemporalityField = &primitiveTypedField{ }, } -var optionalDoubleSumField = &optionalPrimitiveValue{ - fieldName: "Sum", - originTypePrefix: "otlpmetrics.HistogramDataPoint_", - returnType: "float64", - defaultVal: "float64(0.0)", - testVal: "float64(17.13)", +var sumField = &optionalPrimitiveValue{ + fieldName: "Sum", + returnType: "float64", + defaultVal: "float64(0.0)", + testVal: "float64(17.13)", +} +var minField = &optionalPrimitiveValue{ + fieldName: "Min", + returnType: "float64", + defaultVal: "float64(0.0)", + testVal: "float64(9.23)", +} + +var maxField = &optionalPrimitiveValue{ + fieldName: "Max", + returnType: "float64", + defaultVal: "float64(0.0)", + testVal: "float64(182.55)", } diff --git a/pdata/internal/cmd/pdatagen/internal/primitive_slice_structs.go b/pdata/internal/cmd/pdatagen/internal/primitive_slice_structs.go index cbca8c08355..6428e545c52 100644 --- a/pdata/internal/cmd/pdatagen/internal/primitive_slice_structs.go +++ b/pdata/internal/cmd/pdatagen/internal/primitive_slice_structs.go @@ -20,10 +20,15 @@ func (ms {{ .structName }}) getOrig() *[]{{ .itemType }} { return internal.GetOrig{{ .structName }}(internal.{{ .structName }}(ms)) } +func (ms {{ .structName }}) getState() *internal.State { + return internal.Get{{ .structName }}State(internal.{{ .structName }}(ms)) +} + // New{{ .structName }} creates a new empty {{ .structName }}. func New{{ .structName }}() {{ .structName }} { orig := []{{ .itemType }}(nil) - return {{ .structName }}(internal.New{{ .structName }}(&orig)) + state := internal.StateMutable + return {{ .structName }}(internal.New{{ .structName }}(&orig, &state)) } // AsRaw returns a copy of the []{{ .itemType }} slice. @@ -33,6 +38,7 @@ func (ms {{ .structName }}) AsRaw() []{{ .itemType }} { // FromRaw copies raw []{{ .itemType }} into the slice {{ .structName }}. func (ms {{ .structName }}) FromRaw(val []{{ .itemType }}) { + ms.getState().AssertMutable() *ms.getOrig() = copy{{ .structName }}(*ms.getOrig(), val) } @@ -51,6 +57,7 @@ func (ms {{ .structName }}) At(i int) {{ .itemType }} { // SetAt sets {{ .itemType }} item at particular index. // Equivalent of {{ .lowerStructName }}[i] = val func (ms {{ .structName }}) SetAt(i int, val {{ .itemType }}) { + ms.getState().AssertMutable() (*ms.getOrig())[i] = val } @@ -61,6 +68,7 @@ func (ms {{ .structName }}) SetAt(i int, val {{ .itemType }}) { // copy(buf, {{ .lowerStructName }}) // {{ .lowerStructName }} = buf func (ms {{ .structName }}) EnsureCapacity(newCap int) { + ms.getState().AssertMutable() oldCap := cap(*ms.getOrig()) if newCap <= oldCap { return @@ -74,18 +82,22 @@ func (ms {{ .structName }}) EnsureCapacity(newCap int) { // Append appends extra elements to {{ .structName }}. // Equivalent of {{ .lowerStructName }} = append({{ .lowerStructName }}, elms...) func (ms {{ .structName }}) Append(elms ...{{ .itemType }}) { + ms.getState().AssertMutable() *ms.getOrig() = append(*ms.getOrig(), elms...) } // MoveTo moves all elements from the current slice overriding the destination and // resetting the current instance to its zero value. func (ms {{ .structName }}) MoveTo(dest {{ .structName }}) { + ms.getState().AssertMutable() + dest.getState().AssertMutable() *dest.getOrig() = *ms.getOrig() *ms.getOrig() = nil } // CopyTo copies all elements from the current slice overriding the destination. func (ms {{ .structName }}) CopyTo(dest {{ .structName }}) { + dest.getState().AssertMutable() *dest.getOrig() = copy{{ .structName }}(*dest.getOrig(), *ms.getOrig()) } @@ -125,6 +137,27 @@ const immutableSliceTestTemplate = `func TestNew{{ .structName }}(t *testing.T) assert.Equal(t, {{ .itemType }}(1), mv.At(0)) } +func Test{{ .structName }}ReadOnly(t *testing.T) { + raw := []{{ .itemType }}{1, 2, 3} + state := internal.StateReadOnly + ms := {{ .structName }}(internal.New{{ .structName }}(&raw, &state)) + + assert.Equal(t, 3, ms.Len()) + assert.Equal(t, {{ .itemType }}(1), ms.At(0)) + assert.Panics(t, func() { ms.Append(1) }) + assert.Panics(t, func() { ms.EnsureCapacity(2) }) + assert.Equal(t, raw, ms.AsRaw()) + assert.Panics(t, func() { ms.FromRaw(raw) }) + + ms2 := New{{ .structName }}() + ms.CopyTo(ms2) + assert.Equal(t, ms.AsRaw(), ms2.AsRaw()) + assert.Panics(t, func() { ms2.CopyTo(ms) }) + + assert.Panics(t, func() { ms.MoveTo(ms2) }) + assert.Panics(t, func() { ms2.MoveTo(ms) }) +} + func Test{{ .structName }}Append(t *testing.T) { ms := New{{ .structName }}() ms.FromRaw([]{{ .itemType }}{1, 2, 3}) @@ -144,14 +177,19 @@ func Test{{ .structName }}EnsureCapacity(t *testing.T) { const primitiveSliceInternalTemplate = ` type {{ .structName }} struct { orig *[]{{ .itemType }} + state *State } func GetOrig{{ .structName }}(ms {{ .structName }}) *[]{{ .itemType }} { return ms.orig } -func New{{ .structName }}(orig *[]{{ .itemType }}) {{ .structName }} { - return {{ .structName }}{orig: orig} +func Get{{ .structName }}State(ms {{ .structName }}) *State { + return ms.state +} + +func New{{ .structName }}(orig *[]{{ .itemType }}, state *State) {{ .structName }} { + return {{ .structName }}{orig: orig, state: state} }` // primitiveSliceStruct generates a struct for a slice of primitive value elements. The structs are always generated diff --git a/pdata/internal/cmd/pdatagen/internal/ptrace_package.go b/pdata/internal/cmd/pdatagen/internal/ptrace_package.go index 74099adfda1..bb4345294d9 100644 --- a/pdata/internal/cmd/pdatagen/internal/ptrace_package.go +++ b/pdata/internal/cmd/pdatagen/internal/ptrace_package.go @@ -83,6 +83,13 @@ var spanSlice = &sliceOfPtrs{ element: span, } +var flagsField = &primitiveField{ + fieldName: "Flags", + returnType: "uint32", + defaultVal: `uint32(0)`, + testVal: `uint32(0xf)`, +} + var span = &messageValueStruct{ structName: "Span", description: "// Span represents a single operation within a trace.\n" + @@ -94,6 +101,7 @@ var span = &messageValueStruct{ traceStateField, parentSpanIDField, nameField, + flagsField, &primitiveTypedField{ fieldName: "Kind", returnType: &primitiveType{ @@ -167,6 +175,7 @@ var spanLink = &messageValueStruct{ traceIDField, spanIDField, traceStateField, + flagsField, attributes, droppedAttributesCount, }, diff --git a/pdata/internal/data/package_test.go b/pdata/internal/data/package_test.go new file mode 100644 index 00000000000..72cf48754c0 --- /dev/null +++ b/pdata/internal/data/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package data + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/pdata/internal/data/protogen/logs/v1/logs.pb.go b/pdata/internal/data/protogen/logs/v1/logs.pb.go index 240a4d1905a..65b11fbe286 100644 --- a/pdata/internal/data/protogen/logs/v1/logs.pb.go +++ b/pdata/internal/data/protogen/logs/v1/logs.pb.go @@ -125,9 +125,11 @@ func (SeverityNumber) EnumDescriptor() ([]byte, []int) { return fileDescriptor_d1c030a3ec7e961e, []int{0} } -// LogRecordFlags is defined as a protobuf 'uint32' type and is to be used as -// bit-fields. Each non-zero value defined in this enum is a bit-mask. -// To extract the bit-field, for example, use an expression like: +// LogRecordFlags represents constants used to interpret the +// LogRecord.flags field, which is protobuf 'fixed32' type and is to +// be used as bit-fields. Each non-zero value defined in this enum is +// a bit-mask. To extract the bit-field, for example, use an +// expression like: // // (logRecord.flags & LOG_RECORD_FLAGS_TRACE_FLAGS_MASK) type LogRecordFlags int32 @@ -225,6 +227,9 @@ type ResourceLogs struct { Resource v1.Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource"` // A list of ScopeLogs that originate from a resource. ScopeLogs []*ScopeLogs `protobuf:"bytes,2,rep,name=scope_logs,json=scopeLogs,proto3" json:"scope_logs,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the resource data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_logs" field which have their own schema_url field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` @@ -299,6 +304,9 @@ type ScopeLogs struct { Scope v11.InstrumentationScope `protobuf:"bytes,1,opt,name=scope,proto3" json:"scope"` // A list of log records. LogRecords []*LogRecord `protobuf:"bytes,2,rep,name=log_records,json=logRecords,proto3" json:"log_records,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the log data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all logs in the "logs" field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` } diff --git a/pdata/internal/data/protogen/metrics/v1/metrics.pb.go b/pdata/internal/data/protogen/metrics/v1/metrics.pb.go index 09cd8e712e8..4ef4f4d5f63 100644 --- a/pdata/internal/data/protogen/metrics/v1/metrics.pb.go +++ b/pdata/internal/data/protogen/metrics/v1/metrics.pb.go @@ -223,6 +223,9 @@ type ResourceMetrics struct { Resource v1.Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource"` // A list of metrics that originate from a resource. ScopeMetrics []*ScopeMetrics `protobuf:"bytes,2,rep,name=scope_metrics,json=scopeMetrics,proto3" json:"scope_metrics,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the resource data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_metrics" field which have their own schema_url field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` @@ -297,6 +300,9 @@ type ScopeMetrics struct { Scope v11.InstrumentationScope `protobuf:"bytes,1,opt,name=scope,proto3" json:"scope"` // A list of metrics that originate from an instrumentation library. Metrics []*Metric `protobuf:"bytes,2,rep,name=metrics,proto3" json:"metrics,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the metric data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all metrics in the "metrics" field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` } @@ -443,7 +449,7 @@ func (m *ScopeMetrics) GetSchemaUrl() string { // when the start time is truly unknown, setting StartTimeUnixNano is // strongly encouraged. type Metric struct { - // name of the metric, including its DNS name prefix. It must be unique. + // name of the metric. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // description of the metric, which can be used in documentation. Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` diff --git a/pdata/internal/data/protogen/trace/v1/trace.pb.go b/pdata/internal/data/protogen/trace/v1/trace.pb.go index b48ce226021..71f32df0f70 100644 --- a/pdata/internal/data/protogen/trace/v1/trace.pb.go +++ b/pdata/internal/data/protogen/trace/v1/trace.pb.go @@ -29,6 +29,48 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// SpanFlags represents constants used to interpret the +// Span.flags field, which is protobuf 'fixed32' type and is to +// be used as bit-fields. Each non-zero value defined in this enum is +// a bit-mask. To extract the bit-field, for example, use an +// expression like: +// +// (span.flags & SPAN_FLAGS_TRACE_FLAGS_MASK) +// +// See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. +// +// Note that Span flags were introduced in version 1.1 of the +// OpenTelemetry protocol. Older Span producers do not set this +// field, consequently consumers should not rely on the absence of a +// particular flag bit to indicate the presence of a particular feature. +type SpanFlags int32 + +const ( + // The zero value for the enum. Should not be used for comparisons. + // Instead use bitwise "and" with the appropriate mask as shown above. + SpanFlags_SPAN_FLAGS_DO_NOT_USE SpanFlags = 0 + // Bits 0-7 are used for trace flags. + SpanFlags_SPAN_FLAGS_TRACE_FLAGS_MASK SpanFlags = 255 +) + +var SpanFlags_name = map[int32]string{ + 0: "SPAN_FLAGS_DO_NOT_USE", + 255: "SPAN_FLAGS_TRACE_FLAGS_MASK", +} + +var SpanFlags_value = map[string]int32{ + "SPAN_FLAGS_DO_NOT_USE": 0, + "SPAN_FLAGS_TRACE_FLAGS_MASK": 255, +} + +func (x SpanFlags) String() string { + return proto.EnumName(SpanFlags_name, int32(x)) +} + +func (SpanFlags) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_5c407ac9c675a601, []int{0} +} + // SpanKind is the type of span. Can be used to specify additional relationships between spans // in addition to a parent/child relationship. type Span_SpanKind int32 @@ -183,6 +225,9 @@ type ResourceSpans struct { Resource v1.Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource"` // A list of ScopeSpans that originate from a resource. ScopeSpans []*ScopeSpans `protobuf:"bytes,2,rep,name=scope_spans,json=scopeSpans,proto3" json:"scope_spans,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the resource data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_spans" field which have their own schema_url field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` @@ -257,6 +302,9 @@ type ScopeSpans struct { Scope v11.InstrumentationScope `protobuf:"bytes,1,opt,name=scope,proto3" json:"scope"` // A list of Spans that originate from an instrumentation scope. Spans []*Span `protobuf:"bytes,2,rep,name=spans,proto3" json:"spans,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the span data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all spans and span events in the "spans" field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` } @@ -340,6 +388,21 @@ type Span struct { // The `span_id` of this span's parent span. If this is a root span, then this // field must be empty. The ID is an 8-byte array. ParentSpanId go_opentelemetry_io_collector_pdata_internal_data.SpanID `protobuf:"bytes,4,opt,name=parent_span_id,json=parentSpanId,proto3,customtype=go.opentelemetry.io/collector/pdata/internal/data.SpanID" json:"parent_span_id"` + // Flags, a bit field. 8 least significant bits are the trace + // flags as defined in W3C Trace Context specification. Readers + // MUST not assume that 24 most significant bits will be zero. + // To read the 8-bit W3C trace flag, use `flags & SPAN_FLAGS_TRACE_FLAGS_MASK`. + // + // When creating span messages, if the message is logically forwarded from another source + // with an equivalent flags fields (i.e., usually another OTLP span message), the field SHOULD + // be copied as-is. If creating from a source that does not have an equivalent flags field + // (such as a runtime representation of an OpenTelemetry span), the high 24 bits MUST + // be set to zero. + // + // [Optional]. + // + // See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. + Flags uint32 `protobuf:"fixed32,16,opt,name=flags,proto3" json:"flags,omitempty"` // A description of the span's operation. // // For example, the name can be a qualified method name or a file name @@ -443,6 +506,13 @@ func (m *Span) GetTraceState() string { return "" } +func (m *Span) GetFlags() uint32 { + if m != nil { + return m.Flags + } + return 0 +} + func (m *Span) GetName() string { if m != nil { return m.Name @@ -617,6 +687,15 @@ type Span_Link struct { // dropped_attributes_count is the number of dropped attributes. If the value is 0, // then no attributes were dropped. DroppedAttributesCount uint32 `protobuf:"varint,5,opt,name=dropped_attributes_count,json=droppedAttributesCount,proto3" json:"dropped_attributes_count,omitempty"` + // Flags, a bit field. 8 least significant bits are the trace + // flags as defined in W3C Trace Context specification. Readers + // MUST not assume that 24 most significant bits will be zero. + // When creating new spans, the most-significant 24-bits MUST be + // zero. To read the 8-bit W3C trace flag (use flags & + // SPAN_FLAGS_TRACE_FLAGS_MASK). [Optional]. + // + // See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. + Flags uint32 `protobuf:"fixed32,6,opt,name=flags,proto3" json:"flags,omitempty"` } func (m *Span_Link) Reset() { *m = Span_Link{} } @@ -673,6 +752,13 @@ func (m *Span_Link) GetDroppedAttributesCount() uint32 { return 0 } +func (m *Span_Link) GetFlags() uint32 { + if m != nil { + return m.Flags + } + return 0 +} + // The Status type defines a logical error model that is suitable for different // programming environments, including REST APIs and RPC APIs. type Status struct { @@ -730,6 +816,7 @@ func (m *Status) GetCode() Status_StatusCode { } func init() { + proto.RegisterEnum("opentelemetry.proto.trace.v1.SpanFlags", SpanFlags_name, SpanFlags_value) proto.RegisterEnum("opentelemetry.proto.trace.v1.Span_SpanKind", Span_SpanKind_name, Span_SpanKind_value) proto.RegisterEnum("opentelemetry.proto.trace.v1.Status_StatusCode", Status_StatusCode_name, Status_StatusCode_value) proto.RegisterType((*TracesData)(nil), "opentelemetry.proto.trace.v1.TracesData") @@ -746,70 +833,75 @@ func init() { } var fileDescriptor_5c407ac9c675a601 = []byte{ - // 1007 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x56, 0x4f, 0x6f, 0xe3, 0x44, - 0x14, 0xcf, 0xa4, 0x4e, 0xda, 0xbe, 0xb6, 0x59, 0x77, 0xe8, 0x56, 0xa6, 0x5a, 0xd2, 0x28, 0x5a, - 0x89, 0xc0, 0x4a, 0x09, 0xed, 0x5e, 0xca, 0x01, 0xb1, 0x6d, 0x62, 0x24, 0xd3, 0x6e, 0x52, 0x8d, - 0x93, 0x4a, 0x20, 0x24, 0x33, 0x1b, 0x0f, 0xc5, 0x6a, 0x32, 0xb6, 0xec, 0x49, 0xb5, 0x7b, 0xe3, - 0x23, 0x70, 0xe5, 0x13, 0x20, 0xc1, 0x9d, 0x1b, 0xf7, 0x15, 0xa7, 0x3d, 0x22, 0x0e, 0x2b, 0xd4, - 0x5e, 0xe0, 0x5b, 0xa0, 0x99, 0xb1, 0xf3, 0xa7, 0xaa, 0x92, 0xad, 0xc4, 0x5e, 0xf6, 0xd2, 0x4e, - 0xde, 0x7b, 0xbf, 0x3f, 0xef, 0xcd, 0xb3, 0x65, 0xa8, 0x85, 0x11, 0xe3, 0x82, 0x0d, 0xd8, 0x90, - 0x89, 0xf8, 0x45, 0x23, 0x8a, 0x43, 0x11, 0x36, 0x44, 0x4c, 0xfb, 0xac, 0x71, 0xb9, 0xa7, 0x0f, - 0x75, 0x15, 0xc4, 0x0f, 0x66, 0x2a, 0x75, 0xb0, 0xae, 0x0b, 0x2e, 0xf7, 0x76, 0xb6, 0xce, 0xc3, - 0xf3, 0x50, 0xa3, 0xe5, 0x49, 0xa7, 0x77, 0x3e, 0xbe, 0x8d, 0xbd, 0x1f, 0x0e, 0x87, 0x21, 0x97, - 0xf4, 0xfa, 0x94, 0xd6, 0xd6, 0x6f, 0xab, 0x8d, 0x59, 0x12, 0x8e, 0x62, 0x6d, 0x26, 0x3b, 0xeb, - 0xfa, 0xea, 0xb7, 0x00, 0x5d, 0xa9, 0x9e, 0xb4, 0xa8, 0xa0, 0x98, 0x40, 0x29, 0xcb, 0x7b, 0x49, - 0x44, 0x79, 0x62, 0xa1, 0xca, 0x52, 0x6d, 0x6d, 0xff, 0x51, 0x7d, 0x9e, 0xed, 0x3a, 0x49, 0x31, - 0xae, 0x84, 0x90, 0x8d, 0x78, 0xfa, 0x67, 0xf5, 0xe7, 0x3c, 0x6c, 0xcc, 0x14, 0x60, 0x0f, 0xb6, - 0x7d, 0x16, 0xc5, 0xac, 0x4f, 0x05, 0xf3, 0xbd, 0xa4, 0x1f, 0x46, 0x99, 0xda, 0x3f, 0xcb, 0x4a, - 0xae, 0x36, 0x5f, 0xce, 0x95, 0x08, 0xad, 0xb5, 0x35, 0x21, 0x9a, 0x44, 0xf1, 0x31, 0xac, 0x64, - 0x1e, 0x2c, 0x54, 0x41, 0xb5, 0xb5, 0xfd, 0x8f, 0x6e, 0x65, 0x1c, 0xcf, 0x62, 0xaa, 0x87, 0x23, - 0xe3, 0xe5, 0xeb, 0xdd, 0x1c, 0x19, 0x13, 0x60, 0x07, 0xd6, 0xa6, 0x2d, 0xe6, 0xef, 0xe8, 0x10, - 0x92, 0x89, 0xaf, 0x0f, 0x00, 0x92, 0xfe, 0xf7, 0x6c, 0x48, 0xbd, 0x51, 0x3c, 0xb0, 0x96, 0x2a, - 0xa8, 0xb6, 0x4a, 0x56, 0x75, 0xa4, 0x17, 0x0f, 0xaa, 0xbf, 0x21, 0x80, 0xa9, 0x2e, 0x3a, 0x50, - 0x50, 0xd8, 0xb4, 0x85, 0xc7, 0xb7, 0x4a, 0xa6, 0x97, 0x7f, 0xb9, 0x57, 0x77, 0x78, 0x22, 0xe2, - 0xd1, 0x90, 0x71, 0x41, 0x45, 0x10, 0x72, 0x45, 0x94, 0x36, 0xa3, 0x79, 0xf0, 0x01, 0x14, 0xa6, - 0x7b, 0xa8, 0x2e, 0xe8, 0x21, 0xa2, 0x9c, 0x68, 0xc0, 0x22, 0xe3, 0x3f, 0x6c, 0x80, 0x21, 0xcb, - 0xf1, 0x37, 0xb0, 0xa2, 0xf0, 0x5e, 0xe0, 0x2b, 0xd7, 0xeb, 0x47, 0x87, 0xd2, 0xc0, 0x5f, 0xaf, - 0x77, 0x3f, 0x3d, 0x0f, 0x6f, 0xc8, 0x05, 0x72, 0x87, 0x07, 0x03, 0xd6, 0x17, 0x61, 0xdc, 0x88, - 0x7c, 0x2a, 0x68, 0x23, 0xe0, 0x82, 0xc5, 0x9c, 0x0e, 0x1a, 0xf2, 0x57, 0x5d, 0xed, 0xa5, 0xd3, - 0x22, 0xcb, 0x8a, 0xd2, 0xf1, 0xf1, 0x57, 0xb0, 0x2c, 0xed, 0x48, 0xf2, 0xbc, 0x22, 0x7f, 0x92, - 0x92, 0x1f, 0xdc, 0x9d, 0x5c, 0xda, 0x75, 0x5a, 0xa4, 0x28, 0x09, 0x1d, 0x1f, 0xef, 0xc2, 0x9a, - 0x36, 0x9e, 0x08, 0x2a, 0x58, 0xda, 0x21, 0xa8, 0x90, 0x2b, 0x23, 0xf8, 0x3b, 0x28, 0x45, 0x34, - 0x66, 0x5c, 0x78, 0x99, 0x05, 0xe3, 0x7f, 0xb2, 0xb0, 0xae, 0x79, 0x5d, 0x6d, 0x04, 0x83, 0xc1, - 0xe9, 0x90, 0x59, 0x05, 0xe5, 0x40, 0x9d, 0xf1, 0xe7, 0x60, 0x5c, 0x04, 0xdc, 0xb7, 0x8a, 0x15, - 0x54, 0x2b, 0x2d, 0x7a, 0x16, 0x25, 0x8f, 0xfa, 0x73, 0x1c, 0x70, 0x9f, 0x28, 0x20, 0x6e, 0xc0, - 0x56, 0x22, 0x68, 0x2c, 0x3c, 0x11, 0x0c, 0x99, 0x37, 0xe2, 0xc1, 0x73, 0x8f, 0x53, 0x1e, 0x5a, - 0xcb, 0x15, 0x54, 0x2b, 0x92, 0x4d, 0x95, 0xeb, 0x06, 0x43, 0xd6, 0xe3, 0xc1, 0xf3, 0x36, 0xe5, - 0x21, 0x7e, 0x04, 0x98, 0x71, 0xff, 0x66, 0xf9, 0x8a, 0x2a, 0xbf, 0xc7, 0xb8, 0x3f, 0x53, 0xfc, - 0x14, 0x80, 0x0a, 0x11, 0x07, 0xcf, 0x46, 0x82, 0x25, 0xd6, 0xaa, 0xda, 0xad, 0x0f, 0x17, 0x2c, - 0xeb, 0x31, 0x7b, 0x71, 0x46, 0x07, 0xa3, 0x6c, 0x41, 0xa7, 0x08, 0xf0, 0x01, 0x58, 0x7e, 0x1c, - 0x46, 0x11, 0xf3, 0xbd, 0x49, 0xd4, 0xeb, 0x87, 0x23, 0x2e, 0x2c, 0xa8, 0xa0, 0xda, 0x06, 0xd9, - 0x4e, 0xf3, 0x87, 0xe3, 0x74, 0x53, 0x66, 0xf1, 0x13, 0x28, 0xb2, 0x4b, 0xc6, 0x45, 0x62, 0xad, - 0xbd, 0xd1, 0x43, 0x2a, 0x27, 0x65, 0x4b, 0x00, 0x49, 0x71, 0xf8, 0x13, 0xd8, 0xca, 0xb4, 0x75, - 0x24, 0xd5, 0x5d, 0x57, 0xba, 0x38, 0xcd, 0x29, 0x4c, 0xaa, 0xf9, 0x19, 0x14, 0x06, 0x01, 0xbf, - 0x48, 0xac, 0x8d, 0x39, 0x7d, 0xcf, 0x4a, 0x9e, 0x04, 0xfc, 0x82, 0x68, 0x14, 0xae, 0xc3, 0x7b, - 0x99, 0xa0, 0x0a, 0xa4, 0x7a, 0x25, 0xa5, 0xb7, 0x99, 0xa6, 0x24, 0x20, 0x95, 0x3b, 0x82, 0xa2, - 0xdc, 0xd0, 0x51, 0x62, 0xdd, 0x53, 0x2f, 0x85, 0x87, 0x0b, 0xf4, 0x54, 0x6d, 0x3a, 0xe4, 0x14, - 0xb9, 0xf3, 0x07, 0x82, 0x82, 0x6a, 0x01, 0x3f, 0x84, 0xd2, 0x8d, 0x2b, 0x46, 0xea, 0x8a, 0xd7, - 0xc5, 0xf4, 0xfd, 0x66, 0x2b, 0x99, 0x9f, 0x5a, 0xc9, 0xd9, 0x3b, 0x5f, 0x7a, 0x9b, 0x77, 0x6e, - 0xcc, 0xbb, 0xf3, 0x9d, 0x7f, 0xf3, 0x60, 0xc8, 0xf9, 0xbc, 0xc3, 0xaf, 0x9e, 0xd9, 0x59, 0x1b, - 0x6f, 0x73, 0xd6, 0x85, 0x79, 0xb3, 0xae, 0xfe, 0x84, 0x60, 0x25, 0x7b, 0xb3, 0xe0, 0xf7, 0xe1, - 0xbe, 0x7b, 0x7a, 0xd8, 0xf6, 0x8e, 0x9d, 0x76, 0xcb, 0xeb, 0xb5, 0xdd, 0x53, 0xbb, 0xe9, 0x7c, - 0xe1, 0xd8, 0x2d, 0x33, 0x87, 0xb7, 0x01, 0x4f, 0x52, 0x4e, 0xbb, 0x6b, 0x93, 0xf6, 0xe1, 0x89, - 0x89, 0xf0, 0x16, 0x98, 0x93, 0xb8, 0x6b, 0x93, 0x33, 0x9b, 0x98, 0xf9, 0xd9, 0x68, 0xf3, 0xc4, - 0xb1, 0xdb, 0x5d, 0x73, 0x69, 0x96, 0xe3, 0x94, 0x74, 0x5a, 0xbd, 0xa6, 0x4d, 0x4c, 0x63, 0x36, - 0xde, 0xec, 0xb4, 0xdd, 0xde, 0x53, 0x9b, 0x98, 0x85, 0xea, 0xef, 0x08, 0x8a, 0x7a, 0xdb, 0xb1, - 0x05, 0xcb, 0x43, 0x96, 0x24, 0xf4, 0x3c, 0x5b, 0xd9, 0xec, 0x27, 0x6e, 0x82, 0xd1, 0x0f, 0x7d, - 0x3d, 0xe3, 0xd2, 0x7e, 0xe3, 0x4d, 0x9e, 0x9d, 0xf4, 0x5f, 0x33, 0xf4, 0x19, 0x51, 0xe0, 0x6a, - 0x1b, 0x60, 0x12, 0xc3, 0xf7, 0x61, 0xd3, 0xed, 0x1e, 0x76, 0x7b, 0xae, 0xd7, 0xec, 0xb4, 0x6c, - 0x39, 0x08, 0xbb, 0x6b, 0xe6, 0x30, 0x86, 0xd2, 0x74, 0xb8, 0x73, 0x6c, 0xa2, 0x9b, 0xa5, 0x36, - 0x21, 0x1d, 0x62, 0xe6, 0xbf, 0x34, 0x56, 0x90, 0x99, 0x3f, 0xfa, 0x15, 0xbd, 0xbc, 0x2a, 0xa3, - 0x57, 0x57, 0x65, 0xf4, 0xf7, 0x55, 0x19, 0xfd, 0x78, 0x5d, 0xce, 0xbd, 0xba, 0x2e, 0xe7, 0xfe, - 0xbc, 0x2e, 0xe7, 0x60, 0x37, 0x08, 0xe7, 0x3a, 0x3d, 0xd2, 0x5f, 0x70, 0xa7, 0x32, 0x78, 0x8a, - 0xbe, 0x6e, 0xde, 0x79, 0x23, 0xf5, 0x57, 0xe2, 0x39, 0xe3, 0xe3, 0x4f, 0xd6, 0x5f, 0xf2, 0x0f, - 0x3a, 0x11, 0xe3, 0xdd, 0x31, 0x85, 0x22, 0xd7, 0x8f, 0x45, 0xfd, 0x6c, 0xef, 0x59, 0x51, 0x21, - 0x1e, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0xbb, 0xe9, 0x90, 0xbc, 0xf8, 0x0a, 0x00, 0x00, + // 1073 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x56, 0x4f, 0x6f, 0x1b, 0x45, + 0x14, 0xf7, 0x38, 0xfe, 0x93, 0xbc, 0x24, 0xee, 0x76, 0x70, 0xa3, 0x25, 0x14, 0xc7, 0xb2, 0x2a, + 0x61, 0x5a, 0xc9, 0x26, 0xe9, 0x25, 0x1c, 0x10, 0x75, 0xec, 0x0d, 0x18, 0x27, 0x76, 0x34, 0x6b, + 0x47, 0x02, 0x21, 0x2d, 0x5b, 0xef, 0xd4, 0xac, 0x62, 0xcf, 0xae, 0x76, 0xc7, 0x51, 0xfb, 0x2d, + 0xb8, 0xf2, 0x09, 0x90, 0x80, 0x33, 0x37, 0xee, 0x15, 0xa7, 0x1e, 0x11, 0x87, 0x0a, 0x25, 0x17, + 0xbe, 0x45, 0xd1, 0xcc, 0xec, 0xda, 0xeb, 0x28, 0x72, 0x1a, 0x89, 0x5e, 0xb8, 0x24, 0x33, 0xef, + 0xcf, 0xef, 0xf7, 0x7b, 0x6f, 0xde, 0x8c, 0x17, 0xaa, 0x9e, 0x4f, 0x19, 0xa7, 0x63, 0x3a, 0xa1, + 0x3c, 0x78, 0x51, 0xf7, 0x03, 0x8f, 0x7b, 0x75, 0x1e, 0xd8, 0x43, 0x5a, 0x3f, 0xdf, 0x55, 0x8b, + 0x9a, 0x34, 0xe2, 0xfb, 0x0b, 0x91, 0xca, 0x58, 0x53, 0x01, 0xe7, 0xbb, 0xdb, 0xc5, 0x91, 0x37, + 0xf2, 0x54, 0xb6, 0x58, 0x29, 0xf7, 0xf6, 0xc3, 0xeb, 0xd0, 0x87, 0xde, 0x64, 0xe2, 0x31, 0x01, + 0xaf, 0x56, 0x51, 0x6c, 0xed, 0xba, 0xd8, 0x80, 0x86, 0xde, 0x34, 0x50, 0x62, 0xe2, 0xb5, 0x8a, + 0xaf, 0x7c, 0x07, 0xd0, 0x17, 0xec, 0x61, 0xcb, 0xe6, 0x36, 0x26, 0x50, 0x88, 0xfd, 0x56, 0xe8, + 0xdb, 0x2c, 0xd4, 0x51, 0x79, 0xa5, 0xba, 0xbe, 0xf7, 0xa8, 0xb6, 0x4c, 0x76, 0x8d, 0x44, 0x39, + 0xa6, 0x48, 0x21, 0x9b, 0x41, 0x72, 0x5b, 0xf9, 0x29, 0x0d, 0x9b, 0x0b, 0x01, 0xd8, 0x82, 0x2d, + 0x87, 0xfa, 0x01, 0x1d, 0xda, 0x9c, 0x3a, 0x56, 0x38, 0xf4, 0xfc, 0x98, 0xed, 0x9f, 0xbc, 0xa4, + 0xab, 0x2e, 0xa7, 0x33, 0x45, 0x86, 0xe2, 0x2a, 0xce, 0x81, 0xe6, 0x56, 0xdc, 0x81, 0xd5, 0x58, + 0x83, 0x8e, 0xca, 0xa8, 0xba, 0xbe, 0xf7, 0xf1, 0xb5, 0x88, 0xb3, 0x5e, 0x24, 0x6a, 0x38, 0xc8, + 0xbc, 0x7c, 0xbd, 0x93, 0x22, 0x33, 0x00, 0xdc, 0x86, 0xf5, 0xa4, 0xc4, 0xf4, 0x2d, 0x15, 0x42, + 0x38, 0xd7, 0xf5, 0x21, 0x40, 0x38, 0xfc, 0x9e, 0x4e, 0x6c, 0x6b, 0x1a, 0x8c, 0xf5, 0x95, 0x32, + 0xaa, 0xae, 0x91, 0x35, 0x65, 0x19, 0x04, 0xe3, 0xca, 0x6f, 0x08, 0x20, 0x51, 0x45, 0x0f, 0xb2, + 0x32, 0x37, 0x2a, 0xe1, 0xf1, 0xb5, 0x94, 0xd1, 0xe1, 0x9f, 0xef, 0xd6, 0xda, 0x2c, 0xe4, 0xc1, + 0x74, 0x42, 0x19, 0xb7, 0xb9, 0xeb, 0x31, 0x09, 0x14, 0x15, 0xa3, 0x70, 0xf0, 0x3e, 0x64, 0x93, + 0x35, 0x54, 0x6e, 0xa8, 0xc1, 0xb7, 0x19, 0x51, 0x09, 0x37, 0x09, 0xff, 0x75, 0x13, 0x32, 0x22, + 0x1c, 0x7f, 0x0b, 0xab, 0x32, 0xdf, 0x72, 0x1d, 0xa9, 0x7a, 0xe3, 0xa0, 0x21, 0x04, 0xfc, 0xf5, + 0x7a, 0xe7, 0xd3, 0x91, 0x77, 0x85, 0xce, 0x15, 0x33, 0x3c, 0x1e, 0xd3, 0x21, 0xf7, 0x82, 0xba, + 0xef, 0xd8, 0xdc, 0xae, 0xbb, 0x8c, 0xd3, 0x80, 0xd9, 0xe3, 0xba, 0xd8, 0xd5, 0xe4, 0x5c, 0xb6, + 0x5b, 0x24, 0x2f, 0x21, 0xdb, 0x0e, 0xfe, 0x1a, 0xf2, 0x42, 0x8e, 0x00, 0x4f, 0x4b, 0xf0, 0x27, + 0x11, 0xf8, 0xfe, 0xed, 0xc1, 0x85, 0xdc, 0x76, 0x8b, 0xe4, 0x04, 0x60, 0xdb, 0xc1, 0x3b, 0xb0, + 0xae, 0x84, 0x87, 0xdc, 0xe6, 0x34, 0xaa, 0x10, 0xa4, 0xc9, 0x14, 0x16, 0xfc, 0x0c, 0x0a, 0xbe, + 0x1d, 0x50, 0xc6, 0xad, 0x58, 0x42, 0xe6, 0x3f, 0x92, 0xb0, 0xa1, 0x70, 0x4d, 0x25, 0xa4, 0x08, + 0xd9, 0x67, 0x63, 0x7b, 0x14, 0xea, 0x5a, 0x19, 0x55, 0xf3, 0x44, 0x6d, 0x30, 0x86, 0x0c, 0xb3, + 0x27, 0x54, 0xcf, 0x4a, 0x5d, 0x72, 0x8d, 0x3f, 0x87, 0xcc, 0x99, 0xcb, 0x1c, 0x3d, 0x57, 0x46, + 0xd5, 0xc2, 0x4d, 0x37, 0x54, 0xa0, 0xcb, 0x3f, 0x1d, 0x97, 0x39, 0x44, 0x26, 0xe2, 0x3a, 0x14, + 0x43, 0x6e, 0x07, 0xdc, 0xe2, 0xee, 0x84, 0x5a, 0x53, 0xe6, 0x3e, 0xb7, 0x98, 0xcd, 0x3c, 0x3d, + 0x5f, 0x46, 0xd5, 0x1c, 0xb9, 0x2b, 0x7d, 0x7d, 0x77, 0x42, 0x07, 0xcc, 0x7d, 0xde, 0xb5, 0x99, + 0x87, 0x1f, 0x01, 0xa6, 0xcc, 0xb9, 0x1a, 0xbe, 0x2a, 0xc3, 0xef, 0x50, 0xe6, 0x2c, 0x04, 0x1f, + 0x03, 0xd8, 0x9c, 0x07, 0xee, 0xd3, 0x29, 0xa7, 0xa1, 0xbe, 0x26, 0x27, 0xee, 0xa3, 0x1b, 0x46, + 0xb8, 0x43, 0x5f, 0x9c, 0xda, 0xe3, 0x69, 0x3c, 0xb6, 0x09, 0x00, 0xbc, 0x0f, 0xba, 0x13, 0x78, + 0xbe, 0x4f, 0x1d, 0x6b, 0x6e, 0xb5, 0x86, 0xde, 0x94, 0x71, 0x1d, 0xca, 0xa8, 0xba, 0x49, 0xb6, + 0x22, 0x7f, 0x63, 0xe6, 0x6e, 0x0a, 0x2f, 0x7e, 0x02, 0x39, 0x7a, 0x4e, 0x19, 0x0f, 0xf5, 0xf5, + 0xb7, 0xba, 0xba, 0xa2, 0x53, 0x86, 0x48, 0x20, 0x51, 0x1e, 0xfe, 0x04, 0x8a, 0x31, 0xb7, 0xb2, + 0x44, 0xbc, 0x1b, 0x92, 0x17, 0x47, 0x3e, 0x99, 0x13, 0x71, 0x7e, 0x06, 0xd9, 0xb1, 0xcb, 0xce, + 0x42, 0x7d, 0x73, 0x49, 0xdd, 0x8b, 0x94, 0x47, 0x2e, 0x3b, 0x23, 0x2a, 0x0b, 0xd7, 0xe0, 0xbd, + 0x98, 0x50, 0x1a, 0x22, 0xbe, 0x82, 0xe4, 0xbb, 0x1b, 0xb9, 0x44, 0x42, 0x44, 0x77, 0x00, 0x39, + 0x31, 0xb7, 0xd3, 0x50, 0xbf, 0x23, 0x9f, 0x8a, 0x07, 0x37, 0xf0, 0xc9, 0xd8, 0xa8, 0xc9, 0x51, + 0xe6, 0xf6, 0x1f, 0x08, 0xb2, 0xb2, 0x04, 0xfc, 0x00, 0x0a, 0x57, 0x8e, 0x18, 0xc9, 0x23, 0xde, + 0xe0, 0xc9, 0xf3, 0x8d, 0x47, 0x32, 0x9d, 0x18, 0xc9, 0xc5, 0x33, 0x5f, 0x79, 0x97, 0x67, 0x9e, + 0x59, 0x76, 0xe6, 0xdb, 0x6f, 0xd2, 0x90, 0x11, 0xfd, 0xf9, 0x1f, 0x3f, 0x48, 0x8b, 0xbd, 0xce, + 0xbc, 0xcb, 0x5e, 0x67, 0x97, 0xde, 0xaf, 0xd9, 0x8b, 0x95, 0x4b, 0xbc, 0x58, 0x95, 0x1f, 0x11, + 0xac, 0xc6, 0xef, 0x0d, 0x7e, 0x1f, 0xee, 0x99, 0x27, 0x8d, 0xae, 0xd5, 0x69, 0x77, 0x5b, 0xd6, + 0xa0, 0x6b, 0x9e, 0x18, 0xcd, 0xf6, 0x61, 0xdb, 0x68, 0x69, 0x29, 0xbc, 0x05, 0x78, 0xee, 0x6a, + 0x77, 0xfb, 0x06, 0xe9, 0x36, 0x8e, 0x34, 0x84, 0x8b, 0xa0, 0xcd, 0xed, 0xa6, 0x41, 0x4e, 0x0d, + 0xa2, 0xa5, 0x17, 0xad, 0xcd, 0xa3, 0xb6, 0xd1, 0xed, 0x6b, 0x2b, 0x8b, 0x18, 0x27, 0xa4, 0xd7, + 0x1a, 0x34, 0x0d, 0xa2, 0x65, 0x16, 0xed, 0xcd, 0x5e, 0xd7, 0x1c, 0x1c, 0x1b, 0x44, 0xcb, 0x56, + 0x7e, 0x47, 0x90, 0x53, 0x77, 0x00, 0xeb, 0x90, 0x9f, 0xd0, 0x30, 0xb4, 0x47, 0xf1, 0x20, 0xc7, + 0x5b, 0xdc, 0x84, 0xcc, 0xd0, 0x73, 0x54, 0xe7, 0x0b, 0x7b, 0xf5, 0xb7, 0xb9, 0x51, 0xd1, 0xbf, + 0xa6, 0xe7, 0x50, 0x22, 0x93, 0x2b, 0x5d, 0x80, 0xb9, 0x0d, 0xdf, 0x83, 0xbb, 0x66, 0xbf, 0xd1, + 0x1f, 0x98, 0x56, 0xb3, 0xd7, 0x32, 0x44, 0x23, 0x8c, 0xbe, 0x96, 0xc2, 0x18, 0x0a, 0x49, 0x73, + 0xaf, 0xa3, 0xa1, 0xab, 0xa1, 0x06, 0x21, 0x3d, 0xa2, 0xa5, 0xbf, 0xca, 0xac, 0x22, 0x2d, 0xfd, + 0xf0, 0x4b, 0x58, 0x13, 0xad, 0x3d, 0x94, 0x3f, 0x0d, 0x71, 0x6f, 0x0f, 0x8f, 0x1a, 0x5f, 0x98, + 0x56, 0xab, 0x67, 0x75, 0x7b, 0x7d, 0x6b, 0x60, 0x1a, 0x5a, 0x0a, 0x97, 0xe1, 0x83, 0x84, 0xab, + 0x4f, 0x1a, 0x4d, 0x23, 0x5a, 0x1f, 0x37, 0xcc, 0x8e, 0xf6, 0x06, 0x1d, 0xfc, 0x82, 0x5e, 0x5e, + 0x94, 0xd0, 0xab, 0x8b, 0x12, 0xfa, 0xfb, 0xa2, 0x84, 0x7e, 0xb8, 0x2c, 0xa5, 0x5e, 0x5d, 0x96, + 0x52, 0x7f, 0x5e, 0x96, 0x52, 0xb0, 0xe3, 0x7a, 0x4b, 0x6b, 0x3e, 0x50, 0xdf, 0x8d, 0x27, 0xc2, + 0x78, 0x82, 0xbe, 0x69, 0xde, 0x7a, 0xe2, 0xd5, 0xb7, 0xe9, 0x88, 0xb2, 0xd9, 0x87, 0xf2, 0xcf, + 0xe9, 0xfb, 0x3d, 0x9f, 0xb2, 0xfe, 0x0c, 0x42, 0x82, 0xab, 0x6b, 0x57, 0x3b, 0xdd, 0x7d, 0x9a, + 0x93, 0x19, 0x8f, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xd4, 0x18, 0xf8, 0x6e, 0x0b, 0x00, + 0x00, } func (m *TracesData) Marshal() (dAtA []byte, err error) { @@ -993,6 +1085,14 @@ func (m *Span) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Flags != 0 { + i -= 4 + encoding_binary.LittleEndian.PutUint32(dAtA[i:], uint32(m.Flags)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x85 + } { size, err := m.Status.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -1199,6 +1299,12 @@ func (m *Span_Link) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Flags != 0 { + i -= 4 + encoding_binary.LittleEndian.PutUint32(dAtA[i:], uint32(m.Flags)) + i-- + dAtA[i] = 0x35 + } if m.DroppedAttributesCount != 0 { i = encodeVarintTrace(dAtA, i, uint64(m.DroppedAttributesCount)) i-- @@ -1415,6 +1521,9 @@ func (m *Span) Size() (n int) { } l = m.Status.Size() n += 1 + l + sovTrace(uint64(l)) + if m.Flags != 0 { + n += 6 + } return n } @@ -1466,6 +1575,9 @@ func (m *Span_Link) Size() (n int) { if m.DroppedAttributesCount != 0 { n += 1 + sovTrace(uint64(m.DroppedAttributesCount)) } + if m.Flags != 0 { + n += 5 + } return n } @@ -2330,6 +2442,16 @@ func (m *Span) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 16: + if wireType != 5 { + return fmt.Errorf("proto: wrong wireType = %d for field Flags", wireType) + } + m.Flags = 0 + if (iNdEx + 4) > l { + return io.ErrUnexpectedEOF + } + m.Flags = uint32(encoding_binary.LittleEndian.Uint32(dAtA[iNdEx:])) + iNdEx += 4 default: iNdEx = preIndex skippy, err := skipTrace(dAtA[iNdEx:]) @@ -2676,6 +2798,16 @@ func (m *Span_Link) Unmarshal(dAtA []byte) error { break } } + case 6: + if wireType != 5 { + return fmt.Errorf("proto: wrong wireType = %d for field Flags", wireType) + } + m.Flags = 0 + if (iNdEx + 4) > l { + return io.ErrUnexpectedEOF + } + m.Flags = uint32(encoding_binary.LittleEndian.Uint32(dAtA[iNdEx:])) + iNdEx += 4 default: iNdEx = preIndex skippy, err := skipTrace(dAtA[iNdEx:]) diff --git a/pdata/internal/generated_wrapper_byteslice.go b/pdata/internal/generated_wrapper_byteslice.go index 83beaf9c6ab..ea3a3d95cd1 100644 --- a/pdata/internal/generated_wrapper_byteslice.go +++ b/pdata/internal/generated_wrapper_byteslice.go @@ -7,13 +7,18 @@ package internal type ByteSlice struct { - orig *[]byte + orig *[]byte + state *State } func GetOrigByteSlice(ms ByteSlice) *[]byte { return ms.orig } -func NewByteSlice(orig *[]byte) ByteSlice { - return ByteSlice{orig: orig} +func GetByteSliceState(ms ByteSlice) *State { + return ms.state +} + +func NewByteSlice(orig *[]byte, state *State) ByteSlice { + return ByteSlice{orig: orig, state: state} } diff --git a/pdata/internal/generated_wrapper_float64slice.go b/pdata/internal/generated_wrapper_float64slice.go index 1204adf5dd3..88d6c33d78e 100644 --- a/pdata/internal/generated_wrapper_float64slice.go +++ b/pdata/internal/generated_wrapper_float64slice.go @@ -7,13 +7,18 @@ package internal type Float64Slice struct { - orig *[]float64 + orig *[]float64 + state *State } func GetOrigFloat64Slice(ms Float64Slice) *[]float64 { return ms.orig } -func NewFloat64Slice(orig *[]float64) Float64Slice { - return Float64Slice{orig: orig} +func GetFloat64SliceState(ms Float64Slice) *State { + return ms.state +} + +func NewFloat64Slice(orig *[]float64, state *State) Float64Slice { + return Float64Slice{orig: orig, state: state} } diff --git a/pdata/internal/generated_wrapper_instrumentationscope.go b/pdata/internal/generated_wrapper_instrumentationscope.go index 951e60cea12..89b995bc98f 100644 --- a/pdata/internal/generated_wrapper_instrumentationscope.go +++ b/pdata/internal/generated_wrapper_instrumentationscope.go @@ -11,20 +11,26 @@ import ( ) type InstrumentationScope struct { - orig *otlpcommon.InstrumentationScope + orig *otlpcommon.InstrumentationScope + state *State } func GetOrigInstrumentationScope(ms InstrumentationScope) *otlpcommon.InstrumentationScope { return ms.orig } -func NewInstrumentationScope(orig *otlpcommon.InstrumentationScope) InstrumentationScope { - return InstrumentationScope{orig: orig} +func GetInstrumentationScopeState(ms InstrumentationScope) *State { + return ms.state +} + +func NewInstrumentationScope(orig *otlpcommon.InstrumentationScope, state *State) InstrumentationScope { + return InstrumentationScope{orig: orig, state: state} } func GenerateTestInstrumentationScope() InstrumentationScope { orig := otlpcommon.InstrumentationScope{} - tv := NewInstrumentationScope(&orig) + state := StateMutable + tv := NewInstrumentationScope(&orig, &state) FillTestInstrumentationScope(tv) return tv } @@ -32,6 +38,6 @@ func GenerateTestInstrumentationScope() InstrumentationScope { func FillTestInstrumentationScope(tv InstrumentationScope) { tv.orig.Name = "test_name" tv.orig.Version = "test_version" - FillTestMap(NewMap(&tv.orig.Attributes)) + FillTestMap(NewMap(&tv.orig.Attributes, tv.state)) tv.orig.DroppedAttributesCount = uint32(17) } diff --git a/pdata/internal/generated_wrapper_resource.go b/pdata/internal/generated_wrapper_resource.go index 0f91d02ede6..354b2457ba7 100644 --- a/pdata/internal/generated_wrapper_resource.go +++ b/pdata/internal/generated_wrapper_resource.go @@ -11,25 +11,31 @@ import ( ) type Resource struct { - orig *otlpresource.Resource + orig *otlpresource.Resource + state *State } func GetOrigResource(ms Resource) *otlpresource.Resource { return ms.orig } -func NewResource(orig *otlpresource.Resource) Resource { - return Resource{orig: orig} +func GetResourceState(ms Resource) *State { + return ms.state +} + +func NewResource(orig *otlpresource.Resource, state *State) Resource { + return Resource{orig: orig, state: state} } func GenerateTestResource() Resource { orig := otlpresource.Resource{} - tv := NewResource(&orig) + state := StateMutable + tv := NewResource(&orig, &state) FillTestResource(tv) return tv } func FillTestResource(tv Resource) { - FillTestMap(NewMap(&tv.orig.Attributes)) + FillTestMap(NewMap(&tv.orig.Attributes, tv.state)) tv.orig.DroppedAttributesCount = uint32(17) } diff --git a/pdata/internal/generated_wrapper_uint64slice.go b/pdata/internal/generated_wrapper_uint64slice.go index 6190251307a..fed633ae260 100644 --- a/pdata/internal/generated_wrapper_uint64slice.go +++ b/pdata/internal/generated_wrapper_uint64slice.go @@ -7,13 +7,18 @@ package internal type UInt64Slice struct { - orig *[]uint64 + orig *[]uint64 + state *State } func GetOrigUInt64Slice(ms UInt64Slice) *[]uint64 { return ms.orig } -func NewUInt64Slice(orig *[]uint64) UInt64Slice { - return UInt64Slice{orig: orig} +func GetUInt64SliceState(ms UInt64Slice) *State { + return ms.state +} + +func NewUInt64Slice(orig *[]uint64, state *State) UInt64Slice { + return UInt64Slice{orig: orig, state: state} } diff --git a/pdata/internal/json/package_test.go b/pdata/internal/json/package_test.go new file mode 100644 index 00000000000..0a3664f879a --- /dev/null +++ b/pdata/internal/json/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package json + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/pdata/internal/otlp/package_test.go b/pdata/internal/otlp/package_test.go new file mode 100644 index 00000000000..0e2ed9911ee --- /dev/null +++ b/pdata/internal/otlp/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package otlp + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/pdata/internal/state.go b/pdata/internal/state.go new file mode 100644 index 00000000000..f10de5eadf1 --- /dev/null +++ b/pdata/internal/state.go @@ -0,0 +1,22 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package internal // import "go.opentelemetry.io/collector/pdata/internal" + +// State defines an ownership state of pmetric.Metrics, plog.Logs or ptrace.Traces. +type State int32 + +const ( + // StateMutable indicates that the data is exclusive to the current consumer. + StateMutable State = iota + + // StateReadOnly indicates that the data is shared with other consumers. + StateReadOnly +) + +// AssertMutable panics if the state is not StateMutable. +func (state *State) AssertMutable() { + if *state != StateMutable { + panic("invalid access to shared data") + } +} diff --git a/pdata/internal/wrapper_logs.go b/pdata/internal/wrapper_logs.go index b102ff70489..6b6c076cca6 100644 --- a/pdata/internal/wrapper_logs.go +++ b/pdata/internal/wrapper_logs.go @@ -9,15 +9,24 @@ import ( ) type Logs struct { - orig *otlpcollectorlog.ExportLogsServiceRequest + orig *otlpcollectorlog.ExportLogsServiceRequest + state *State } func GetOrigLogs(ms Logs) *otlpcollectorlog.ExportLogsServiceRequest { return ms.orig } -func NewLogs(orig *otlpcollectorlog.ExportLogsServiceRequest) Logs { - return Logs{orig: orig} +func GetLogsState(ms Logs) *State { + return ms.state +} + +func SetLogsState(ms Logs, state State) { + *ms.state = state +} + +func NewLogs(orig *otlpcollectorlog.ExportLogsServiceRequest, state *State) Logs { + return Logs{orig: orig, state: state} } // LogsToProto internal helper to convert Logs to protobuf representation. @@ -28,8 +37,10 @@ func LogsToProto(l Logs) otlplogs.LogsData { } // LogsFromProto internal helper to convert protobuf representation to Logs. +// This function set exclusive state assuming that it's called only once per Logs. func LogsFromProto(orig otlplogs.LogsData) Logs { - return Logs{orig: &otlpcollectorlog.ExportLogsServiceRequest{ + state := StateMutable + return NewLogs(&otlpcollectorlog.ExportLogsServiceRequest{ ResourceLogs: orig.ResourceLogs, - }} + }, &state) } diff --git a/pdata/internal/wrapper_map.go b/pdata/internal/wrapper_map.go index 8eece9e7dbd..23a1c9056c8 100644 --- a/pdata/internal/wrapper_map.go +++ b/pdata/internal/wrapper_map.go @@ -8,20 +8,26 @@ import ( ) type Map struct { - orig *[]otlpcommon.KeyValue + orig *[]otlpcommon.KeyValue + state *State } func GetOrigMap(ms Map) *[]otlpcommon.KeyValue { return ms.orig } -func NewMap(orig *[]otlpcommon.KeyValue) Map { - return Map{orig: orig} +func GetMapState(ms Map) *State { + return ms.state +} + +func NewMap(orig *[]otlpcommon.KeyValue, state *State) Map { + return Map{orig: orig, state: state} } func GenerateTestMap() Map { var orig []otlpcommon.KeyValue - ms := NewMap(&orig) + state := StateMutable + ms := NewMap(&orig, &state) FillTestMap(ms) return ms } diff --git a/pdata/internal/wrapper_metrics.go b/pdata/internal/wrapper_metrics.go index 95b3001e77b..85be497ea5c 100644 --- a/pdata/internal/wrapper_metrics.go +++ b/pdata/internal/wrapper_metrics.go @@ -9,15 +9,24 @@ import ( ) type Metrics struct { - orig *otlpcollectormetrics.ExportMetricsServiceRequest + orig *otlpcollectormetrics.ExportMetricsServiceRequest + state *State } func GetOrigMetrics(ms Metrics) *otlpcollectormetrics.ExportMetricsServiceRequest { return ms.orig } -func NewMetrics(orig *otlpcollectormetrics.ExportMetricsServiceRequest) Metrics { - return Metrics{orig: orig} +func GetMetricsState(ms Metrics) *State { + return ms.state +} + +func SetMetricsState(ms Metrics, state State) { + *ms.state = state +} + +func NewMetrics(orig *otlpcollectormetrics.ExportMetricsServiceRequest, state *State) Metrics { + return Metrics{orig: orig, state: state} } // MetricsToProto internal helper to convert Metrics to protobuf representation. @@ -28,8 +37,10 @@ func MetricsToProto(l Metrics) otlpmetrics.MetricsData { } // MetricsFromProto internal helper to convert protobuf representation to Metrics. +// This function set exclusive state assuming that it's called only once per Metrics. func MetricsFromProto(orig otlpmetrics.MetricsData) Metrics { - return Metrics{orig: &otlpcollectormetrics.ExportMetricsServiceRequest{ + state := StateMutable + return NewMetrics(&otlpcollectormetrics.ExportMetricsServiceRequest{ ResourceMetrics: orig.ResourceMetrics, - }} + }, &state) } diff --git a/pdata/internal/wrapper_slice.go b/pdata/internal/wrapper_slice.go index cfeed739742..2f366199a25 100644 --- a/pdata/internal/wrapper_slice.go +++ b/pdata/internal/wrapper_slice.go @@ -8,20 +8,26 @@ import ( ) type Slice struct { - orig *[]otlpcommon.AnyValue + orig *[]otlpcommon.AnyValue + state *State } func GetOrigSlice(ms Slice) *[]otlpcommon.AnyValue { return ms.orig } -func NewSlice(orig *[]otlpcommon.AnyValue) Slice { - return Slice{orig: orig} +func GetSliceState(ms Slice) *State { + return ms.state +} + +func NewSlice(orig *[]otlpcommon.AnyValue, state *State) Slice { + return Slice{orig: orig, state: state} } func GenerateTestSlice() Slice { orig := []otlpcommon.AnyValue{} - tv := NewSlice(&orig) + state := StateMutable + tv := NewSlice(&orig, &state) FillTestSlice(tv) return tv } @@ -29,6 +35,7 @@ func GenerateTestSlice() Slice { func FillTestSlice(tv Slice) { *tv.orig = make([]otlpcommon.AnyValue, 7) for i := 0; i < 7; i++ { - FillTestValue(NewValue(&(*tv.orig)[i])) + state := StateMutable + FillTestValue(NewValue(&(*tv.orig)[i], &state)) } } diff --git a/pdata/internal/wrapper_traces.go b/pdata/internal/wrapper_traces.go index f8d29dba788..5a4cdadbde0 100644 --- a/pdata/internal/wrapper_traces.go +++ b/pdata/internal/wrapper_traces.go @@ -9,15 +9,24 @@ import ( ) type Traces struct { - orig *otlpcollectortrace.ExportTraceServiceRequest + orig *otlpcollectortrace.ExportTraceServiceRequest + state *State } func GetOrigTraces(ms Traces) *otlpcollectortrace.ExportTraceServiceRequest { return ms.orig } -func NewTraces(orig *otlpcollectortrace.ExportTraceServiceRequest) Traces { - return Traces{orig: orig} +func GetTracesState(ms Traces) *State { + return ms.state +} + +func SetTracesState(ms Traces, state State) { + *ms.state = state +} + +func NewTraces(orig *otlpcollectortrace.ExportTraceServiceRequest, state *State) Traces { + return Traces{orig: orig, state: state} } // TracesToProto internal helper to convert Traces to protobuf representation. @@ -28,8 +37,10 @@ func TracesToProto(l Traces) otlptrace.TracesData { } // TracesFromProto internal helper to convert protobuf representation to Traces. +// This function set exclusive state assuming that it's called only once per Traces. func TracesFromProto(orig otlptrace.TracesData) Traces { - return Traces{orig: &otlpcollectortrace.ExportTraceServiceRequest{ + state := StateMutable + return NewTraces(&otlpcollectortrace.ExportTraceServiceRequest{ ResourceSpans: orig.ResourceSpans, - }} + }, &state) } diff --git a/pdata/internal/wrapper_tracestate.go b/pdata/internal/wrapper_tracestate.go index 3a86a11848b..1a2f79f89d8 100644 --- a/pdata/internal/wrapper_tracestate.go +++ b/pdata/internal/wrapper_tracestate.go @@ -4,20 +4,26 @@ package internal // import "go.opentelemetry.io/collector/pdata/internal" type TraceState struct { - orig *string + orig *string + state *State } func GetOrigTraceState(ms TraceState) *string { return ms.orig } -func NewTraceState(orig *string) TraceState { - return TraceState{orig: orig} +func GetTraceStateState(ms TraceState) *State { + return ms.state +} + +func NewTraceState(orig *string, state *State) TraceState { + return TraceState{orig: orig, state: state} } func GenerateTestTraceState() TraceState { var orig string - ms := NewTraceState(&orig) + state := StateMutable + ms := NewTraceState(&orig, &state) FillTestTraceState(ms) return ms } diff --git a/pdata/internal/wrapper_value.go b/pdata/internal/wrapper_value.go index 9fd9064de67..0d5225052d5 100644 --- a/pdata/internal/wrapper_value.go +++ b/pdata/internal/wrapper_value.go @@ -8,15 +8,20 @@ import ( ) type Value struct { - orig *otlpcommon.AnyValue + orig *otlpcommon.AnyValue + state *State } func GetOrigValue(ms Value) *otlpcommon.AnyValue { return ms.orig } -func NewValue(orig *otlpcommon.AnyValue) Value { - return Value{orig: orig} +func GetValueState(ms Value) *State { + return ms.state +} + +func NewValue(orig *otlpcommon.AnyValue, state *State) Value { + return Value{orig: orig, state: state} } func FillTestValue(dest Value) { @@ -25,7 +30,8 @@ func FillTestValue(dest Value) { func GenerateTestValue() Value { var orig otlpcommon.AnyValue - ms := NewValue(&orig) + state := StateMutable + ms := NewValue(&orig, &state) FillTestValue(ms) return ms } diff --git a/pdata/pcommon/generated_byteslice.go b/pdata/pcommon/generated_byteslice.go index 34126d9d4e2..cbb64987d2b 100644 --- a/pdata/pcommon/generated_byteslice.go +++ b/pdata/pcommon/generated_byteslice.go @@ -21,10 +21,15 @@ func (ms ByteSlice) getOrig() *[]byte { return internal.GetOrigByteSlice(internal.ByteSlice(ms)) } +func (ms ByteSlice) getState() *internal.State { + return internal.GetByteSliceState(internal.ByteSlice(ms)) +} + // NewByteSlice creates a new empty ByteSlice. func NewByteSlice() ByteSlice { orig := []byte(nil) - return ByteSlice(internal.NewByteSlice(&orig)) + state := internal.StateMutable + return ByteSlice(internal.NewByteSlice(&orig, &state)) } // AsRaw returns a copy of the []byte slice. @@ -34,6 +39,7 @@ func (ms ByteSlice) AsRaw() []byte { // FromRaw copies raw []byte into the slice ByteSlice. func (ms ByteSlice) FromRaw(val []byte) { + ms.getState().AssertMutable() *ms.getOrig() = copyByteSlice(*ms.getOrig(), val) } @@ -52,6 +58,7 @@ func (ms ByteSlice) At(i int) byte { // SetAt sets byte item at particular index. // Equivalent of byteSlice[i] = val func (ms ByteSlice) SetAt(i int, val byte) { + ms.getState().AssertMutable() (*ms.getOrig())[i] = val } @@ -62,6 +69,7 @@ func (ms ByteSlice) SetAt(i int, val byte) { // copy(buf, byteSlice) // byteSlice = buf func (ms ByteSlice) EnsureCapacity(newCap int) { + ms.getState().AssertMutable() oldCap := cap(*ms.getOrig()) if newCap <= oldCap { return @@ -75,18 +83,22 @@ func (ms ByteSlice) EnsureCapacity(newCap int) { // Append appends extra elements to ByteSlice. // Equivalent of byteSlice = append(byteSlice, elms...) func (ms ByteSlice) Append(elms ...byte) { + ms.getState().AssertMutable() *ms.getOrig() = append(*ms.getOrig(), elms...) } // MoveTo moves all elements from the current slice overriding the destination and // resetting the current instance to its zero value. func (ms ByteSlice) MoveTo(dest ByteSlice) { + ms.getState().AssertMutable() + dest.getState().AssertMutable() *dest.getOrig() = *ms.getOrig() *ms.getOrig() = nil } // CopyTo copies all elements from the current slice overriding the destination. func (ms ByteSlice) CopyTo(dest ByteSlice) { + dest.getState().AssertMutable() *dest.getOrig() = copyByteSlice(*dest.getOrig(), *ms.getOrig()) } diff --git a/pdata/pcommon/generated_byteslice_test.go b/pdata/pcommon/generated_byteslice_test.go index b45c958bfc4..9594e0d11d5 100644 --- a/pdata/pcommon/generated_byteslice_test.go +++ b/pdata/pcommon/generated_byteslice_test.go @@ -10,6 +10,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/pdata/internal" ) func TestNewByteSlice(t *testing.T) { @@ -43,6 +45,27 @@ func TestNewByteSlice(t *testing.T) { assert.Equal(t, byte(1), mv.At(0)) } +func TestByteSliceReadOnly(t *testing.T) { + raw := []byte{1, 2, 3} + state := internal.StateReadOnly + ms := ByteSlice(internal.NewByteSlice(&raw, &state)) + + assert.Equal(t, 3, ms.Len()) + assert.Equal(t, byte(1), ms.At(0)) + assert.Panics(t, func() { ms.Append(1) }) + assert.Panics(t, func() { ms.EnsureCapacity(2) }) + assert.Equal(t, raw, ms.AsRaw()) + assert.Panics(t, func() { ms.FromRaw(raw) }) + + ms2 := NewByteSlice() + ms.CopyTo(ms2) + assert.Equal(t, ms.AsRaw(), ms2.AsRaw()) + assert.Panics(t, func() { ms2.CopyTo(ms) }) + + assert.Panics(t, func() { ms.MoveTo(ms2) }) + assert.Panics(t, func() { ms2.MoveTo(ms) }) +} + func TestByteSliceAppend(t *testing.T) { ms := NewByteSlice() ms.FromRaw([]byte{1, 2, 3}) diff --git a/pdata/pcommon/generated_float64slice.go b/pdata/pcommon/generated_float64slice.go index 54db0af8fa4..83a07ccf483 100644 --- a/pdata/pcommon/generated_float64slice.go +++ b/pdata/pcommon/generated_float64slice.go @@ -21,10 +21,15 @@ func (ms Float64Slice) getOrig() *[]float64 { return internal.GetOrigFloat64Slice(internal.Float64Slice(ms)) } +func (ms Float64Slice) getState() *internal.State { + return internal.GetFloat64SliceState(internal.Float64Slice(ms)) +} + // NewFloat64Slice creates a new empty Float64Slice. func NewFloat64Slice() Float64Slice { orig := []float64(nil) - return Float64Slice(internal.NewFloat64Slice(&orig)) + state := internal.StateMutable + return Float64Slice(internal.NewFloat64Slice(&orig, &state)) } // AsRaw returns a copy of the []float64 slice. @@ -34,6 +39,7 @@ func (ms Float64Slice) AsRaw() []float64 { // FromRaw copies raw []float64 into the slice Float64Slice. func (ms Float64Slice) FromRaw(val []float64) { + ms.getState().AssertMutable() *ms.getOrig() = copyFloat64Slice(*ms.getOrig(), val) } @@ -52,6 +58,7 @@ func (ms Float64Slice) At(i int) float64 { // SetAt sets float64 item at particular index. // Equivalent of float64Slice[i] = val func (ms Float64Slice) SetAt(i int, val float64) { + ms.getState().AssertMutable() (*ms.getOrig())[i] = val } @@ -62,6 +69,7 @@ func (ms Float64Slice) SetAt(i int, val float64) { // copy(buf, float64Slice) // float64Slice = buf func (ms Float64Slice) EnsureCapacity(newCap int) { + ms.getState().AssertMutable() oldCap := cap(*ms.getOrig()) if newCap <= oldCap { return @@ -75,18 +83,22 @@ func (ms Float64Slice) EnsureCapacity(newCap int) { // Append appends extra elements to Float64Slice. // Equivalent of float64Slice = append(float64Slice, elms...) func (ms Float64Slice) Append(elms ...float64) { + ms.getState().AssertMutable() *ms.getOrig() = append(*ms.getOrig(), elms...) } // MoveTo moves all elements from the current slice overriding the destination and // resetting the current instance to its zero value. func (ms Float64Slice) MoveTo(dest Float64Slice) { + ms.getState().AssertMutable() + dest.getState().AssertMutable() *dest.getOrig() = *ms.getOrig() *ms.getOrig() = nil } // CopyTo copies all elements from the current slice overriding the destination. func (ms Float64Slice) CopyTo(dest Float64Slice) { + dest.getState().AssertMutable() *dest.getOrig() = copyFloat64Slice(*dest.getOrig(), *ms.getOrig()) } diff --git a/pdata/pcommon/generated_float64slice_test.go b/pdata/pcommon/generated_float64slice_test.go index 72653c7281f..7d2dd87bece 100644 --- a/pdata/pcommon/generated_float64slice_test.go +++ b/pdata/pcommon/generated_float64slice_test.go @@ -10,6 +10,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/pdata/internal" ) func TestNewFloat64Slice(t *testing.T) { @@ -43,6 +45,27 @@ func TestNewFloat64Slice(t *testing.T) { assert.Equal(t, float64(1), mv.At(0)) } +func TestFloat64SliceReadOnly(t *testing.T) { + raw := []float64{1, 2, 3} + state := internal.StateReadOnly + ms := Float64Slice(internal.NewFloat64Slice(&raw, &state)) + + assert.Equal(t, 3, ms.Len()) + assert.Equal(t, float64(1), ms.At(0)) + assert.Panics(t, func() { ms.Append(1) }) + assert.Panics(t, func() { ms.EnsureCapacity(2) }) + assert.Equal(t, raw, ms.AsRaw()) + assert.Panics(t, func() { ms.FromRaw(raw) }) + + ms2 := NewFloat64Slice() + ms.CopyTo(ms2) + assert.Equal(t, ms.AsRaw(), ms2.AsRaw()) + assert.Panics(t, func() { ms2.CopyTo(ms) }) + + assert.Panics(t, func() { ms.MoveTo(ms2) }) + assert.Panics(t, func() { ms2.MoveTo(ms) }) +} + func TestFloat64SliceAppend(t *testing.T) { ms := NewFloat64Slice() ms.FromRaw([]float64{1, 2, 3}) diff --git a/pdata/pcommon/generated_instrumentationscope.go b/pdata/pcommon/generated_instrumentationscope.go index 4df1eeaed1d..8a5d23b549f 100644 --- a/pdata/pcommon/generated_instrumentationscope.go +++ b/pdata/pcommon/generated_instrumentationscope.go @@ -20,8 +20,8 @@ import ( // Important: zero-initialized instance is not valid for use. type InstrumentationScope internal.InstrumentationScope -func newInstrumentationScope(orig *otlpcommon.InstrumentationScope) InstrumentationScope { - return InstrumentationScope(internal.NewInstrumentationScope(orig)) +func newInstrumentationScope(orig *otlpcommon.InstrumentationScope, state *internal.State) InstrumentationScope { + return InstrumentationScope(internal.NewInstrumentationScope(orig, state)) } // NewInstrumentationScope creates a new empty InstrumentationScope. @@ -29,12 +29,15 @@ func newInstrumentationScope(orig *otlpcommon.InstrumentationScope) Instrumentat // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewInstrumentationScope() InstrumentationScope { - return newInstrumentationScope(&otlpcommon.InstrumentationScope{}) + state := internal.StateMutable + return newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms InstrumentationScope) MoveTo(dest InstrumentationScope) { + ms.getState().AssertMutable() + dest.getState().AssertMutable() *dest.getOrig() = *ms.getOrig() *ms.getOrig() = otlpcommon.InstrumentationScope{} } @@ -43,6 +46,10 @@ func (ms InstrumentationScope) getOrig() *otlpcommon.InstrumentationScope { return internal.GetOrigInstrumentationScope(internal.InstrumentationScope(ms)) } +func (ms InstrumentationScope) getState() *internal.State { + return internal.GetInstrumentationScopeState(internal.InstrumentationScope(ms)) +} + // Name returns the name associated with this InstrumentationScope. func (ms InstrumentationScope) Name() string { return ms.getOrig().Name @@ -50,6 +57,7 @@ func (ms InstrumentationScope) Name() string { // SetName replaces the name associated with this InstrumentationScope. func (ms InstrumentationScope) SetName(v string) { + ms.getState().AssertMutable() ms.getOrig().Name = v } @@ -60,12 +68,13 @@ func (ms InstrumentationScope) Version() string { // SetVersion replaces the version associated with this InstrumentationScope. func (ms InstrumentationScope) SetVersion(v string) { + ms.getState().AssertMutable() ms.getOrig().Version = v } // Attributes returns the Attributes associated with this InstrumentationScope. func (ms InstrumentationScope) Attributes() Map { - return Map(internal.NewMap(&ms.getOrig().Attributes)) + return Map(internal.NewMap(&ms.getOrig().Attributes, internal.GetInstrumentationScopeState(internal.InstrumentationScope(ms)))) } // DroppedAttributesCount returns the droppedattributescount associated with this InstrumentationScope. @@ -75,11 +84,13 @@ func (ms InstrumentationScope) DroppedAttributesCount() uint32 { // SetDroppedAttributesCount replaces the droppedattributescount associated with this InstrumentationScope. func (ms InstrumentationScope) SetDroppedAttributesCount(v uint32) { + ms.getState().AssertMutable() ms.getOrig().DroppedAttributesCount = v } // CopyTo copies all properties from the current struct overriding the destination. func (ms InstrumentationScope) CopyTo(dest InstrumentationScope) { + dest.getState().AssertMutable() dest.SetName(ms.Name()) dest.SetVersion(ms.Version()) ms.Attributes().CopyTo(dest.Attributes()) diff --git a/pdata/pcommon/generated_instrumentationscope_test.go b/pdata/pcommon/generated_instrumentationscope_test.go index 849b75e7bfb..8dc46fe69c4 100644 --- a/pdata/pcommon/generated_instrumentationscope_test.go +++ b/pdata/pcommon/generated_instrumentationscope_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/pdata/internal" + otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1" ) func TestInstrumentationScope_MoveTo(t *testing.T) { @@ -20,6 +21,9 @@ func TestInstrumentationScope_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewInstrumentationScope(), ms) assert.Equal(t, InstrumentationScope(internal.GenerateTestInstrumentationScope()), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &sharedState)) }) + assert.Panics(t, func() { newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &sharedState).MoveTo(dest) }) } func TestInstrumentationScope_CopyTo(t *testing.T) { @@ -30,6 +34,8 @@ func TestInstrumentationScope_CopyTo(t *testing.T) { orig = InstrumentationScope(internal.GenerateTestInstrumentationScope()) orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &sharedState)) }) } func TestInstrumentationScope_Name(t *testing.T) { @@ -37,6 +43,8 @@ func TestInstrumentationScope_Name(t *testing.T) { assert.Equal(t, "", ms.Name()) ms.SetName("test_name") assert.Equal(t, "test_name", ms.Name()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &sharedState).SetName("test_name") }) } func TestInstrumentationScope_Version(t *testing.T) { @@ -44,6 +52,10 @@ func TestInstrumentationScope_Version(t *testing.T) { assert.Equal(t, "", ms.Version()) ms.SetVersion("test_version") assert.Equal(t, "test_version", ms.Version()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &sharedState).SetVersion("test_version") + }) } func TestInstrumentationScope_Attributes(t *testing.T) { @@ -58,4 +70,8 @@ func TestInstrumentationScope_DroppedAttributesCount(t *testing.T) { assert.Equal(t, uint32(0), ms.DroppedAttributesCount()) ms.SetDroppedAttributesCount(uint32(17)) assert.Equal(t, uint32(17), ms.DroppedAttributesCount()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &sharedState).SetDroppedAttributesCount(uint32(17)) + }) } diff --git a/pdata/pcommon/generated_resource.go b/pdata/pcommon/generated_resource.go index c701fb5c55a..12e6cfa7f3b 100644 --- a/pdata/pcommon/generated_resource.go +++ b/pdata/pcommon/generated_resource.go @@ -20,8 +20,8 @@ import ( // Important: zero-initialized instance is not valid for use. type Resource internal.Resource -func newResource(orig *otlpresource.Resource) Resource { - return Resource(internal.NewResource(orig)) +func newResource(orig *otlpresource.Resource, state *internal.State) Resource { + return Resource(internal.NewResource(orig, state)) } // NewResource creates a new empty Resource. @@ -29,12 +29,15 @@ func newResource(orig *otlpresource.Resource) Resource { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewResource() Resource { - return newResource(&otlpresource.Resource{}) + state := internal.StateMutable + return newResource(&otlpresource.Resource{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms Resource) MoveTo(dest Resource) { + ms.getState().AssertMutable() + dest.getState().AssertMutable() *dest.getOrig() = *ms.getOrig() *ms.getOrig() = otlpresource.Resource{} } @@ -43,9 +46,13 @@ func (ms Resource) getOrig() *otlpresource.Resource { return internal.GetOrigResource(internal.Resource(ms)) } +func (ms Resource) getState() *internal.State { + return internal.GetResourceState(internal.Resource(ms)) +} + // Attributes returns the Attributes associated with this Resource. func (ms Resource) Attributes() Map { - return Map(internal.NewMap(&ms.getOrig().Attributes)) + return Map(internal.NewMap(&ms.getOrig().Attributes, internal.GetResourceState(internal.Resource(ms)))) } // DroppedAttributesCount returns the droppedattributescount associated with this Resource. @@ -55,11 +62,13 @@ func (ms Resource) DroppedAttributesCount() uint32 { // SetDroppedAttributesCount replaces the droppedattributescount associated with this Resource. func (ms Resource) SetDroppedAttributesCount(v uint32) { + ms.getState().AssertMutable() ms.getOrig().DroppedAttributesCount = v } // CopyTo copies all properties from the current struct overriding the destination. func (ms Resource) CopyTo(dest Resource) { + dest.getState().AssertMutable() ms.Attributes().CopyTo(dest.Attributes()) dest.SetDroppedAttributesCount(ms.DroppedAttributesCount()) } diff --git a/pdata/pcommon/generated_resource_test.go b/pdata/pcommon/generated_resource_test.go index b806227b617..a7af5300fe8 100644 --- a/pdata/pcommon/generated_resource_test.go +++ b/pdata/pcommon/generated_resource_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/pdata/internal" + otlpresource "go.opentelemetry.io/collector/pdata/internal/data/protogen/resource/v1" ) func TestResource_MoveTo(t *testing.T) { @@ -20,6 +21,9 @@ func TestResource_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewResource(), ms) assert.Equal(t, Resource(internal.GenerateTestResource()), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newResource(&otlpresource.Resource{}, &sharedState)) }) + assert.Panics(t, func() { newResource(&otlpresource.Resource{}, &sharedState).MoveTo(dest) }) } func TestResource_CopyTo(t *testing.T) { @@ -30,6 +34,8 @@ func TestResource_CopyTo(t *testing.T) { orig = Resource(internal.GenerateTestResource()) orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newResource(&otlpresource.Resource{}, &sharedState)) }) } func TestResource_Attributes(t *testing.T) { @@ -44,4 +50,6 @@ func TestResource_DroppedAttributesCount(t *testing.T) { assert.Equal(t, uint32(0), ms.DroppedAttributesCount()) ms.SetDroppedAttributesCount(uint32(17)) assert.Equal(t, uint32(17), ms.DroppedAttributesCount()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newResource(&otlpresource.Resource{}, &sharedState).SetDroppedAttributesCount(uint32(17)) }) } diff --git a/pdata/pcommon/generated_uint64slice.go b/pdata/pcommon/generated_uint64slice.go index f3656929ccc..1344ca35bcf 100644 --- a/pdata/pcommon/generated_uint64slice.go +++ b/pdata/pcommon/generated_uint64slice.go @@ -21,10 +21,15 @@ func (ms UInt64Slice) getOrig() *[]uint64 { return internal.GetOrigUInt64Slice(internal.UInt64Slice(ms)) } +func (ms UInt64Slice) getState() *internal.State { + return internal.GetUInt64SliceState(internal.UInt64Slice(ms)) +} + // NewUInt64Slice creates a new empty UInt64Slice. func NewUInt64Slice() UInt64Slice { orig := []uint64(nil) - return UInt64Slice(internal.NewUInt64Slice(&orig)) + state := internal.StateMutable + return UInt64Slice(internal.NewUInt64Slice(&orig, &state)) } // AsRaw returns a copy of the []uint64 slice. @@ -34,6 +39,7 @@ func (ms UInt64Slice) AsRaw() []uint64 { // FromRaw copies raw []uint64 into the slice UInt64Slice. func (ms UInt64Slice) FromRaw(val []uint64) { + ms.getState().AssertMutable() *ms.getOrig() = copyUInt64Slice(*ms.getOrig(), val) } @@ -52,6 +58,7 @@ func (ms UInt64Slice) At(i int) uint64 { // SetAt sets uint64 item at particular index. // Equivalent of uInt64Slice[i] = val func (ms UInt64Slice) SetAt(i int, val uint64) { + ms.getState().AssertMutable() (*ms.getOrig())[i] = val } @@ -62,6 +69,7 @@ func (ms UInt64Slice) SetAt(i int, val uint64) { // copy(buf, uInt64Slice) // uInt64Slice = buf func (ms UInt64Slice) EnsureCapacity(newCap int) { + ms.getState().AssertMutable() oldCap := cap(*ms.getOrig()) if newCap <= oldCap { return @@ -75,18 +83,22 @@ func (ms UInt64Slice) EnsureCapacity(newCap int) { // Append appends extra elements to UInt64Slice. // Equivalent of uInt64Slice = append(uInt64Slice, elms...) func (ms UInt64Slice) Append(elms ...uint64) { + ms.getState().AssertMutable() *ms.getOrig() = append(*ms.getOrig(), elms...) } // MoveTo moves all elements from the current slice overriding the destination and // resetting the current instance to its zero value. func (ms UInt64Slice) MoveTo(dest UInt64Slice) { + ms.getState().AssertMutable() + dest.getState().AssertMutable() *dest.getOrig() = *ms.getOrig() *ms.getOrig() = nil } // CopyTo copies all elements from the current slice overriding the destination. func (ms UInt64Slice) CopyTo(dest UInt64Slice) { + dest.getState().AssertMutable() *dest.getOrig() = copyUInt64Slice(*dest.getOrig(), *ms.getOrig()) } diff --git a/pdata/pcommon/generated_uint64slice_test.go b/pdata/pcommon/generated_uint64slice_test.go index e2cc4ccf774..9120f84b5e2 100644 --- a/pdata/pcommon/generated_uint64slice_test.go +++ b/pdata/pcommon/generated_uint64slice_test.go @@ -10,6 +10,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/pdata/internal" ) func TestNewUInt64Slice(t *testing.T) { @@ -43,6 +45,27 @@ func TestNewUInt64Slice(t *testing.T) { assert.Equal(t, uint64(1), mv.At(0)) } +func TestUInt64SliceReadOnly(t *testing.T) { + raw := []uint64{1, 2, 3} + state := internal.StateReadOnly + ms := UInt64Slice(internal.NewUInt64Slice(&raw, &state)) + + assert.Equal(t, 3, ms.Len()) + assert.Equal(t, uint64(1), ms.At(0)) + assert.Panics(t, func() { ms.Append(1) }) + assert.Panics(t, func() { ms.EnsureCapacity(2) }) + assert.Equal(t, raw, ms.AsRaw()) + assert.Panics(t, func() { ms.FromRaw(raw) }) + + ms2 := NewUInt64Slice() + ms.CopyTo(ms2) + assert.Equal(t, ms.AsRaw(), ms2.AsRaw()) + assert.Panics(t, func() { ms2.CopyTo(ms) }) + + assert.Panics(t, func() { ms.MoveTo(ms2) }) + assert.Panics(t, func() { ms2.MoveTo(ms) }) +} + func TestUInt64SliceAppend(t *testing.T) { ms := NewUInt64Slice() ms.FromRaw([]uint64{1, 2, 3}) diff --git a/pdata/pcommon/map.go b/pdata/pcommon/map.go index 8e1b2bbccb6..5bbfab962b0 100644 --- a/pdata/pcommon/map.go +++ b/pdata/pcommon/map.go @@ -11,30 +11,40 @@ import ( ) // Map stores a map of string keys to elements of Value type. +// +// Must use NewMap function to create new instances. +// Important: zero-initialized instance is not valid for use. type Map internal.Map // NewMap creates a Map with 0 elements. func NewMap() Map { orig := []otlpcommon.KeyValue(nil) - return Map(internal.NewMap(&orig)) + state := internal.StateMutable + return Map(internal.NewMap(&orig, &state)) } func (m Map) getOrig() *[]otlpcommon.KeyValue { return internal.GetOrigMap(internal.Map(m)) } -func newMap(orig *[]otlpcommon.KeyValue) Map { - return Map(internal.NewMap(orig)) +func (m Map) getState() *internal.State { + return internal.GetMapState(internal.Map(m)) +} + +func newMap(orig *[]otlpcommon.KeyValue, state *internal.State) Map { + return Map(internal.NewMap(orig, state)) } // Clear erases any existing entries in this Map instance. func (m Map) Clear() { + m.getState().AssertMutable() *m.getOrig() = nil } // EnsureCapacity increases the capacity of this Map instance, if necessary, // to ensure that it can hold at least the number of elements specified by the capacity argument. func (m Map) EnsureCapacity(capacity int) { + m.getState().AssertMutable() oldOrig := *m.getOrig() if capacity <= cap(oldOrig) { return @@ -48,21 +58,22 @@ func (m Map) EnsureCapacity(capacity int) { // It is allowed to modify the returned value using Value.Set* functions. // Such modification will be applied to the value stored in this map. // -// If the key does not exist returns an invalid instance of the KeyValue and false. -// Calling any functions on the returned invalid instance will cause a panic. +// If the key does not exist returns a zero-initialized KeyValue and false. +// Calling any functions on the returned invalid instance may cause a panic. func (m Map) Get(key string) (Value, bool) { for i := range *m.getOrig() { akv := &(*m.getOrig())[i] if akv.Key == key { - return newValue(&akv.Value), true + return newValue(&akv.Value, m.getState()), true } } - return newValue(nil), false + return newValue(nil, m.getState()), false } // Remove removes the entry associated with the key and returns true if the key // was present in the map, otherwise returns false. func (m Map) Remove(key string) bool { + m.getState().AssertMutable() for i := range *m.getOrig() { akv := &(*m.getOrig())[i] if akv.Key == key { @@ -76,10 +87,11 @@ func (m Map) Remove(key string) bool { // RemoveIf removes the entries for which the function in question returns true func (m Map) RemoveIf(f func(string, Value) bool) { + m.getState().AssertMutable() newLen := 0 for i := 0; i < len(*m.getOrig()); i++ { akv := &(*m.getOrig())[i] - if f(akv.Key, newValue(&akv.Value)) { + if f(akv.Key, newValue(&akv.Value, m.getState())) { continue } if newLen == i { @@ -96,18 +108,20 @@ func (m Map) RemoveIf(f func(string, Value) bool) { // PutEmpty inserts or updates an empty value to the map under given key // and return the updated/inserted value. func (m Map) PutEmpty(k string) Value { + m.getState().AssertMutable() if av, existing := m.Get(k); existing { av.getOrig().Value = nil - return newValue(av.getOrig()) + return newValue(av.getOrig(), m.getState()) } *m.getOrig() = append(*m.getOrig(), otlpcommon.KeyValue{Key: k}) - return newValue(&(*m.getOrig())[len(*m.getOrig())-1].Value) + return newValue(&(*m.getOrig())[len(*m.getOrig())-1].Value, m.getState()) } // PutStr performs the Insert or Update action. The Value is // inserted to the map that did not originally have the key. The key/value is // updated to the map where the key already existed. func (m Map) PutStr(k string, v string) { + m.getState().AssertMutable() if av, existing := m.Get(k); existing { av.SetStr(v) } else { @@ -119,6 +133,7 @@ func (m Map) PutStr(k string, v string) { // inserted to the map that did not originally have the key. The key/value is // updated to the map where the key already existed. func (m Map) PutInt(k string, v int64) { + m.getState().AssertMutable() if av, existing := m.Get(k); existing { av.SetInt(v) } else { @@ -130,6 +145,7 @@ func (m Map) PutInt(k string, v int64) { // inserted to the map that did not originally have the key. The key/value is // updated to the map where the key already existed. func (m Map) PutDouble(k string, v float64) { + m.getState().AssertMutable() if av, existing := m.Get(k); existing { av.SetDouble(v) } else { @@ -141,6 +157,7 @@ func (m Map) PutDouble(k string, v float64) { // inserted to the map that did not originally have the key. The key/value is // updated to the map where the key already existed. func (m Map) PutBool(k string, v bool) { + m.getState().AssertMutable() if av, existing := m.Get(k); existing { av.SetBool(v) } else { @@ -150,35 +167,38 @@ func (m Map) PutBool(k string, v bool) { // PutEmptyBytes inserts or updates an empty byte slice under given key and returns it. func (m Map) PutEmptyBytes(k string) ByteSlice { + m.getState().AssertMutable() bv := otlpcommon.AnyValue_BytesValue{} if av, existing := m.Get(k); existing { av.getOrig().Value = &bv } else { *m.getOrig() = append(*m.getOrig(), otlpcommon.KeyValue{Key: k, Value: otlpcommon.AnyValue{Value: &bv}}) } - return ByteSlice(internal.NewByteSlice(&bv.BytesValue)) + return ByteSlice(internal.NewByteSlice(&bv.BytesValue, m.getState())) } // PutEmptyMap inserts or updates an empty map under given key and returns it. func (m Map) PutEmptyMap(k string) Map { + m.getState().AssertMutable() kvl := otlpcommon.AnyValue_KvlistValue{KvlistValue: &otlpcommon.KeyValueList{Values: []otlpcommon.KeyValue(nil)}} if av, existing := m.Get(k); existing { av.getOrig().Value = &kvl } else { *m.getOrig() = append(*m.getOrig(), otlpcommon.KeyValue{Key: k, Value: otlpcommon.AnyValue{Value: &kvl}}) } - return Map(internal.NewMap(&kvl.KvlistValue.Values)) + return Map(internal.NewMap(&kvl.KvlistValue.Values, m.getState())) } // PutEmptySlice inserts or updates an empty slice under given key and returns it. func (m Map) PutEmptySlice(k string) Slice { + m.getState().AssertMutable() vl := otlpcommon.AnyValue_ArrayValue{ArrayValue: &otlpcommon.ArrayValue{Values: []otlpcommon.AnyValue(nil)}} if av, existing := m.Get(k); existing { av.getOrig().Value = &vl } else { *m.getOrig() = append(*m.getOrig(), otlpcommon.KeyValue{Key: k, Value: otlpcommon.AnyValue{Value: &vl}}) } - return Slice(internal.NewSlice(&vl.ArrayValue.Values)) + return Slice(internal.NewSlice(&vl.ArrayValue.Values, m.getState())) } // Len returns the length of this map. @@ -199,7 +219,7 @@ func (m Map) Len() int { func (m Map) Range(f func(k string, v Value) bool) { for i := range *m.getOrig() { kv := &(*m.getOrig())[i] - if !f(kv.Key, Value(internal.NewValue(&kv.Value))) { + if !f(kv.Key, Value(internal.NewValue(&kv.Value, m.getState()))) { break } } @@ -207,6 +227,7 @@ func (m Map) Range(f func(k string, v Value) bool) { // CopyTo copies all elements from the current map overriding the destination. func (m Map) CopyTo(dest Map) { + dest.getState().AssertMutable() newLen := len(*m.getOrig()) oldCap := cap(*dest.getOrig()) if newLen <= oldCap { @@ -216,7 +237,7 @@ func (m Map) CopyTo(dest Map) { akv := &(*m.getOrig())[i] destAkv := &(*dest.getOrig())[i] destAkv.Key = akv.Key - newValue(&akv.Value).CopyTo(newValue(&destAkv.Value)) + newValue(&akv.Value, m.getState()).CopyTo(newValue(&destAkv.Value, dest.getState())) } return } @@ -226,7 +247,7 @@ func (m Map) CopyTo(dest Map) { for i := range *m.getOrig() { akv := &(*m.getOrig())[i] origs[i].Key = akv.Key - newValue(&akv.Value).CopyTo(newValue(&origs[i].Value)) + newValue(&akv.Value, m.getState()).CopyTo(newValue(&origs[i].Value, dest.getState())) } *dest.getOrig() = origs } @@ -243,6 +264,7 @@ func (m Map) AsRaw() map[string]any { // FromRaw overrides this Map instance from a standard go map. func (m Map) FromRaw(rawMap map[string]any) error { + m.getState().AssertMutable() if len(rawMap) == 0 { *m.getOrig() = nil return nil @@ -253,7 +275,7 @@ func (m Map) FromRaw(rawMap map[string]any) error { ix := 0 for k, iv := range rawMap { origs[ix].Key = k - errs = multierr.Append(errs, newValue(&origs[ix].Value).FromRaw(iv)) + errs = multierr.Append(errs, newValue(&origs[ix].Value, m.getState()).FromRaw(iv)) ix++ } *m.getOrig() = origs diff --git a/pdata/pcommon/map_test.go b/pdata/pcommon/map_test.go index 28f5a600906..2e4f864f6bf 100644 --- a/pdata/pcommon/map_test.go +++ b/pdata/pcommon/map_test.go @@ -17,7 +17,8 @@ func TestMap(t *testing.T) { val, exist := NewMap().Get("test_key") assert.False(t, exist) - assert.EqualValues(t, newValue(nil), val) + state := internal.StateMutable + assert.EqualValues(t, newValue(nil, &state), val) putString := NewMap() putString.PutStr("k", "v") @@ -52,6 +53,44 @@ func TestMap(t *testing.T) { assert.EqualValues(t, NewMap(), removeMap) } +func TestMapReadOnly(t *testing.T) { + state := internal.StateReadOnly + m := newMap(&[]otlpcommon.KeyValue{ + {Key: "k1", Value: otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_StringValue{StringValue: "v1"}}}, + }, &state) + + assert.Equal(t, 1, m.Len()) + + v, ok := m.Get("k1") + assert.True(t, ok) + assert.EqualValues(t, "v1", v.Str()) + + m.Range(func(k string, v Value) bool { + assert.Equal(t, "k1", k) + assert.Equal(t, "v1", v.Str()) + return true + }) + + assert.Panics(t, func() { m.PutStr("k2", "v2") }) + assert.Panics(t, func() { m.PutInt("k2", 123) }) + assert.Panics(t, func() { m.PutDouble("k2", 1.23) }) + assert.Panics(t, func() { m.PutBool("k2", true) }) + assert.Panics(t, func() { m.PutEmptyBytes("k2") }) + assert.Panics(t, func() { m.PutEmptyMap("k2") }) + assert.Panics(t, func() { m.PutEmptySlice("k2") }) + assert.Panics(t, func() { m.Remove("k1") }) + assert.Panics(t, func() { m.RemoveIf(func(string, Value) bool { return true }) }) + assert.Panics(t, func() { m.EnsureCapacity(2) }) + + m2 := NewMap() + m.CopyTo(m2) + assert.Equal(t, m2.AsRaw(), m.AsRaw()) + assert.Panics(t, func() { NewMap().CopyTo(m) }) + + assert.Equal(t, map[string]any{"k1": "v1"}, m.AsRaw()) + assert.Panics(t, func() { _ = m.FromRaw(map[string]any{"k1": "v1"}) }) +} + func TestMapPutEmpty(t *testing.T) { m := NewMap() v := m.PutEmpty("k1") @@ -148,7 +187,8 @@ func TestMapWithEmpty(t *testing.T) { Value: otlpcommon.AnyValue{Value: nil}, }, } - sm := newMap(&origWithNil) + state := internal.StateMutable + sm := newMap(&origWithNil, &state) val, exist := sm.Get("test_key") assert.True(t, exist) assert.EqualValues(t, ValueTypeStr, val.Type()) @@ -249,7 +289,7 @@ func TestMapWithEmpty(t *testing.T) { } func TestMapIterationNil(t *testing.T) { - NewMap().Range(func(k string, v Value) bool { + NewMap().Range(func(string, Value) bool { // Fail if any element is returned t.Fail() return true @@ -269,7 +309,7 @@ func TestMap_Range(t *testing.T) { assert.Equal(t, 5, am.Len()) calls := 0 - am.Range(func(k string, v Value) bool { + am.Range(func(string, Value) bool { calls++ return false }) @@ -479,3 +519,30 @@ func generateTestBytesMap(t *testing.T) Map { assert.NoError(t, m.FromRaw(map[string]any{"k": []byte{1, 2, 3, 4, 5}})) return m } + +func TestInvalidMap(t *testing.T) { + v := Map{} + + testFunc := func(string, Value) bool { + return true + } + + assert.Panics(t, func() { v.Clear() }) + assert.Panics(t, func() { v.EnsureCapacity(1) }) + assert.Panics(t, func() { v.Get("foo") }) + assert.Panics(t, func() { v.Remove("foo") }) + assert.Panics(t, func() { v.RemoveIf(testFunc) }) + assert.Panics(t, func() { v.PutEmpty("foo") }) + assert.Panics(t, func() { v.PutStr("foo", "bar") }) + assert.Panics(t, func() { v.PutInt("foo", 1) }) + assert.Panics(t, func() { v.PutDouble("foo", 1.1) }) + assert.Panics(t, func() { v.PutBool("foo", true) }) + assert.Panics(t, func() { v.PutEmptyBytes("foo") }) + assert.Panics(t, func() { v.PutEmptyMap("foo") }) + assert.Panics(t, func() { v.PutEmptySlice("foo") }) + assert.Panics(t, func() { v.Len() }) + assert.Panics(t, func() { v.Range(testFunc) }) + assert.Panics(t, func() { v.CopyTo(NewMap()) }) + assert.Panics(t, func() { v.AsRaw() }) + assert.Panics(t, func() { _ = v.FromRaw(map[string]any{"foo": "bar"}) }) +} diff --git a/pdata/pcommon/package_test.go b/pdata/pcommon/package_test.go new file mode 100644 index 00000000000..fee39a8a49b --- /dev/null +++ b/pdata/pcommon/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package pcommon + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/pdata/pcommon/slice.go b/pdata/pcommon/slice.go index 97e0cf777d1..7434f467aed 100644 --- a/pdata/pcommon/slice.go +++ b/pdata/pcommon/slice.go @@ -19,19 +19,24 @@ import ( // Important: zero-initialized instance is not valid for use. type Slice internal.Slice -func newSlice(orig *[]otlpcommon.AnyValue) Slice { - return Slice(internal.NewSlice(orig)) +func newSlice(orig *[]otlpcommon.AnyValue, state *internal.State) Slice { + return Slice(internal.NewSlice(orig, state)) } func (es Slice) getOrig() *[]otlpcommon.AnyValue { return internal.GetOrigSlice(internal.Slice(es)) } +func (es Slice) getState() *internal.State { + return internal.GetSliceState(internal.Slice(es)) +} + // NewSlice creates a Slice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewSlice() Slice { orig := []otlpcommon.AnyValue(nil) - return Slice(internal.NewSlice(&orig)) + state := internal.StateMutable + return Slice(internal.NewSlice(&orig, &state)) } // Len returns the number of elements in the slice. @@ -50,11 +55,12 @@ func (es Slice) Len() int { // ... // Do something with the element // } func (es Slice) At(ix int) Value { - return newValue(&(*es.getOrig())[ix]) + return newValue(&(*es.getOrig())[ix], es.getState()) } // CopyTo copies all elements from the current slice overriding the destination. func (es Slice) CopyTo(dest Slice) { + dest.getState().AssertMutable() srcLen := es.Len() destCap := cap(*dest.getOrig()) if srcLen <= destCap { @@ -64,7 +70,7 @@ func (es Slice) CopyTo(dest Slice) { } for i := range *es.getOrig() { - newValue(&(*es.getOrig())[i]).CopyTo(newValue(&(*dest.getOrig())[i])) + newValue(&(*es.getOrig())[i], es.getState()).CopyTo(newValue(&(*dest.getOrig())[i], dest.getState())) } } @@ -81,6 +87,7 @@ func (es Slice) CopyTo(dest Slice) { // // Here should set all the values for e. // } func (es Slice) EnsureCapacity(newCap int) { + es.getState().AssertMutable() oldCap := cap(*es.getOrig()) if newCap <= oldCap { return @@ -94,6 +101,7 @@ func (es Slice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty Value. // It returns the newly added Value. func (es Slice) AppendEmpty() Value { + es.getState().AssertMutable() *es.getOrig() = append(*es.getOrig(), otlpcommon.AnyValue{}) return es.At(es.Len() - 1) } @@ -101,6 +109,8 @@ func (es Slice) AppendEmpty() Value { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es Slice) MoveAndAppendTo(dest Slice) { + es.getState().AssertMutable() + dest.getState().AssertMutable() if *dest.getOrig() == nil { // We can simply move the entire vector and avoid any allocations. *dest.getOrig() = *es.getOrig() @@ -113,6 +123,7 @@ func (es Slice) MoveAndAppendTo(dest Slice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es Slice) RemoveIf(f func(Value) bool) { + es.getState().AssertMutable() newLen := 0 for i := 0; i < len(*es.getOrig()); i++ { if f(es.At(i)) { @@ -126,7 +137,6 @@ func (es Slice) RemoveIf(f func(Value) bool) { (*es.getOrig())[newLen] = (*es.getOrig())[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.getOrig() = (*es.getOrig())[:newLen] } @@ -141,6 +151,7 @@ func (es Slice) AsRaw() []any { // FromRaw copies []any into the Slice. func (es Slice) FromRaw(rawSlice []any) error { + es.getState().AssertMutable() if len(rawSlice) == 0 { *es.getOrig() = nil return nil @@ -148,7 +159,7 @@ func (es Slice) FromRaw(rawSlice []any) error { var errs error origs := make([]otlpcommon.AnyValue, len(rawSlice)) for ix, iv := range rawSlice { - errs = multierr.Append(errs, newValue(&origs[ix]).FromRaw(iv)) + errs = multierr.Append(errs, newValue(&origs[ix], es.getState()).FromRaw(iv)) } *es.getOrig() = origs return errs diff --git a/pdata/pcommon/slice_test.go b/pdata/pcommon/slice_test.go index 181ab8fc433..705f10f88e7 100644 --- a/pdata/pcommon/slice_test.go +++ b/pdata/pcommon/slice_test.go @@ -15,11 +15,12 @@ import ( func TestSlice(t *testing.T) { es := NewSlice() assert.Equal(t, 0, es.Len()) - es = newSlice(&[]otlpcommon.AnyValue{}) + state := internal.StateMutable + es = newSlice(&[]otlpcommon.AnyValue{}, &state) assert.Equal(t, 0, es.Len()) es.EnsureCapacity(7) - emptyVal := newValue(&otlpcommon.AnyValue{}) + emptyVal := newValue(&otlpcommon.AnyValue{}, &state) testVal := Value(internal.GenerateTestValue()) assert.Equal(t, 7, cap(*es.getOrig())) for i := 0; i < es.Len(); i++ { @@ -30,6 +31,29 @@ func TestSlice(t *testing.T) { } } +func TestSliceReadOnly(t *testing.T) { + state := internal.StateReadOnly + es := newSlice(&[]otlpcommon.AnyValue{{Value: &otlpcommon.AnyValue_IntValue{IntValue: 3}}}, &state) + + assert.Equal(t, 1, es.Len()) + assert.Equal(t, int64(3), es.At(0).Int()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + + es2 := NewSlice() + es.CopyTo(es2) + assert.Equal(t, es.AsRaw(), es2.AsRaw()) + assert.Panics(t, func() { es2.CopyTo(es) }) + + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) + + assert.Panics(t, func() { es.RemoveIf(func(Value) bool { return false }) }) + + assert.Equal(t, []any{int64(3)}, es.AsRaw()) + assert.Panics(t, func() { _ = es.FromRaw([]any{3}) }) +} + func TestSlice_CopyTo(t *testing.T) { dest := NewSlice() // Test CopyTo to empty @@ -98,7 +122,7 @@ func TestSlice_MoveAndAppendTo(t *testing.T) { func TestSlice_RemoveIf(t *testing.T) { // Test RemoveIf on empty slice emptySlice := NewSlice() - emptySlice.RemoveIf(func(el Value) bool { + emptySlice.RemoveIf(func(Value) bool { t.Fail() return false }) @@ -106,9 +130,23 @@ func TestSlice_RemoveIf(t *testing.T) { // Test RemoveIf filtered := Slice(internal.GenerateTestSlice()) pos := 0 - filtered.RemoveIf(func(el Value) bool { + filtered.RemoveIf(func(Value) bool { pos++ return pos%3 == 0 }) assert.Equal(t, 5, filtered.Len()) } + +func TestInvalidSlice(t *testing.T) { + es := Slice{} + + assert.Panics(t, func() { es.Len() }) + assert.Panics(t, func() { es.At(0) }) + assert.Panics(t, func() { es.CopyTo(Slice{}) }) + assert.Panics(t, func() { es.EnsureCapacity(1) }) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.MoveAndAppendTo(Slice{}) }) + assert.Panics(t, func() { es.RemoveIf(func(Value) bool { return false }) }) + assert.Panics(t, func() { es.AsRaw() }) + assert.Panics(t, func() { _ = es.FromRaw([]any{3}) }) +} diff --git a/pdata/pcommon/trace_state.go b/pdata/pcommon/trace_state.go index 440b4b1ade5..c8f84217e0d 100644 --- a/pdata/pcommon/trace_state.go +++ b/pdata/pcommon/trace_state.go @@ -8,16 +8,24 @@ import ( ) // TraceState represents the trace state from the w3c-trace-context. +// +// Must use NewTraceState function to create new instances. +// Important: zero-initialized instance is not valid for use. type TraceState internal.TraceState func NewTraceState() TraceState { - return TraceState(internal.NewTraceState(new(string))) + state := internal.StateMutable + return TraceState(internal.NewTraceState(new(string), &state)) } func (ms TraceState) getOrig() *string { return internal.GetOrigTraceState(internal.TraceState(ms)) } +func (ms TraceState) getState() *internal.State { + return internal.GetTraceStateState(internal.TraceState(ms)) +} + // AsRaw returns the string representation of the tracestate in w3c-trace-context format: https://www.w3.org/TR/trace-context/#tracestate-header func (ms TraceState) AsRaw() string { return *ms.getOrig() @@ -25,17 +33,21 @@ func (ms TraceState) AsRaw() string { // FromRaw copies the string representation in w3c-trace-context format of the tracestate into this TraceState. func (ms TraceState) FromRaw(v string) { + ms.getState().AssertMutable() *ms.getOrig() = v } // MoveTo moves the TraceState instance overriding the destination // and resetting the current instance to its zero value. func (ms TraceState) MoveTo(dest TraceState) { + ms.getState().AssertMutable() + dest.getState().AssertMutable() *dest.getOrig() = *ms.getOrig() *ms.getOrig() = "" } // CopyTo copies the TraceState instance overriding the destination. func (ms TraceState) CopyTo(dest TraceState) { + dest.getState().AssertMutable() *dest.getOrig() = *ms.getOrig() } diff --git a/pdata/pcommon/trace_state_test.go b/pdata/pcommon/trace_state_test.go index 74627a70c39..4e56dffa119 100644 --- a/pdata/pcommon/trace_state_test.go +++ b/pdata/pcommon/trace_state_test.go @@ -35,3 +35,12 @@ func TestTraceState_FromRaw_AsRaw(t *testing.T) { ms.FromRaw("congo=t61rcWkgMzE") assert.Equal(t, "congo=t61rcWkgMzE", ms.AsRaw()) } + +func TestInvalidTraceState(t *testing.T) { + v := TraceState{} + + assert.Panics(t, func() { v.AsRaw() }) + assert.Panics(t, func() { v.FromRaw("") }) + assert.Panics(t, func() { v.MoveTo(TraceState{}) }) + assert.Panics(t, func() { v.CopyTo(TraceState{}) }) +} diff --git a/pdata/pcommon/value.go b/pdata/pcommon/value.go index f59b708695f..77a84e51758 100644 --- a/pdata/pcommon/value.go +++ b/pdata/pcommon/value.go @@ -71,52 +71,66 @@ type Value internal.Value // NewValueEmpty creates a new Value with an empty value. func NewValueEmpty() Value { - return newValue(&otlpcommon.AnyValue{}) + state := internal.StateMutable + return newValue(&otlpcommon.AnyValue{}, &state) } // NewValueStr creates a new Value with the given string value. func NewValueStr(v string) Value { - return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_StringValue{StringValue: v}}) + state := internal.StateMutable + return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_StringValue{StringValue: v}}, &state) } // NewValueInt creates a new Value with the given int64 value. func NewValueInt(v int64) Value { - return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_IntValue{IntValue: v}}) + state := internal.StateMutable + return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_IntValue{IntValue: v}}, &state) } // NewValueDouble creates a new Value with the given float64 value. func NewValueDouble(v float64) Value { - return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_DoubleValue{DoubleValue: v}}) + state := internal.StateMutable + return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_DoubleValue{DoubleValue: v}}, &state) } // NewValueBool creates a new Value with the given bool value. func NewValueBool(v bool) Value { - return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_BoolValue{BoolValue: v}}) + state := internal.StateMutable + return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_BoolValue{BoolValue: v}}, &state) } // NewValueMap creates a new Value of map type. func NewValueMap() Value { - return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_KvlistValue{KvlistValue: &otlpcommon.KeyValueList{}}}) + state := internal.StateMutable + return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_KvlistValue{KvlistValue: &otlpcommon.KeyValueList{}}}, &state) } // NewValueSlice creates a new Value of array type. func NewValueSlice() Value { - return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_ArrayValue{ArrayValue: &otlpcommon.ArrayValue{}}}) + state := internal.StateMutable + return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_ArrayValue{ArrayValue: &otlpcommon.ArrayValue{}}}, &state) } // NewValueBytes creates a new empty Value of byte type. func NewValueBytes() Value { - return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_BytesValue{BytesValue: nil}}) + state := internal.StateMutable + return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_BytesValue{BytesValue: nil}}, &state) } -func newValue(orig *otlpcommon.AnyValue) Value { - return Value(internal.NewValue(orig)) +func newValue(orig *otlpcommon.AnyValue, state *internal.State) Value { + return Value(internal.NewValue(orig, state)) } func (v Value) getOrig() *otlpcommon.AnyValue { return internal.GetOrigValue(internal.Value(v)) } +func (v Value) getState() *internal.State { + return internal.GetValueState(internal.Value(v)) +} + +// FromRaw sets the value from the given raw value. +// Calling this function on zero-initialized Value will cause a panic. func (v Value) FromRaw(iv any) error { switch tv := iv.(type) { case nil: @@ -186,69 +200,59 @@ func (v Value) Type() ValueType { // Str returns the string value associated with this Value. // The shorter name is used instead of String to avoid implementing fmt.Stringer interface. // If the Type() is not ValueTypeStr then returns empty string. -// Calling this function on zero-initialized Value will cause a panic. func (v Value) Str() string { return v.getOrig().GetStringValue() } // Int returns the int64 value associated with this Value. // If the Type() is not ValueTypeInt then returns int64(0). -// Calling this function on zero-initialized Value will cause a panic. func (v Value) Int() int64 { return v.getOrig().GetIntValue() } // Double returns the float64 value associated with this Value. // If the Type() is not ValueTypeDouble then returns float64(0). -// Calling this function on zero-initialized Value will cause a panic. func (v Value) Double() float64 { return v.getOrig().GetDoubleValue() } // Bool returns the bool value associated with this Value. // If the Type() is not ValueTypeBool then returns false. -// Calling this function on zero-initialized Value will cause a panic. func (v Value) Bool() bool { return v.getOrig().GetBoolValue() } // Map returns the map value associated with this Value. -// If the Type() is not ValueTypeMap then returns an invalid map. Note that using -// such map can cause panic. -// -// Calling this function on zero-initialized Value will cause a panic. +// If the function is called on zero-initialized Value or if the Type() is not ValueTypeMap +// then it returns an invalid map. Note that using such map can cause panic. func (v Value) Map() Map { kvlist := v.getOrig().GetKvlistValue() if kvlist == nil { return Map{} } - return newMap(&kvlist.Values) + return newMap(&kvlist.Values, internal.GetValueState(internal.Value(v))) } // Slice returns the slice value associated with this Value. -// If the Type() is not ValueTypeSlice then returns an invalid slice. Note that using -// such slice can cause panic. -// -// Calling this function on zero-initialized Value will cause a panic. +// If the function is called on zero-initialized Value or if the Type() is not ValueTypeSlice +// then returns an invalid slice. Note that using such slice can cause panic. func (v Value) Slice() Slice { arr := v.getOrig().GetArrayValue() if arr == nil { return Slice{} } - return newSlice(&arr.Values) + return newSlice(&arr.Values, internal.GetValueState(internal.Value(v))) } // Bytes returns the ByteSlice value associated with this Value. -// If the Type() is not ValueTypeBytes then returns an invalid ByteSlice object. Note that using -// such slice can cause panic. -// -// Calling this function on zero-initialized Value will cause a panic. +// If the function is called on zero-initialized Value or if the Type() is not ValueTypeBytes +// then returns an invalid ByteSlice object. Note that using such slice can cause panic. func (v Value) Bytes() ByteSlice { bv, ok := v.getOrig().GetValue().(*otlpcommon.AnyValue_BytesValue) if !ok { return ByteSlice{} } - return ByteSlice(internal.NewByteSlice(&bv.BytesValue)) + return ByteSlice(internal.NewByteSlice(&bv.BytesValue, internal.GetValueState(internal.Value(v)))) } // SetStr replaces the string value associated with this Value, @@ -257,6 +261,7 @@ func (v Value) Bytes() ByteSlice { // fmt.Stringer interface by the corresponding getter method. // Calling this function on zero-initialized Value will cause a panic. func (v Value) SetStr(sv string) { + v.getState().AssertMutable() v.getOrig().Value = &otlpcommon.AnyValue_StringValue{StringValue: sv} } @@ -264,6 +269,7 @@ func (v Value) SetStr(sv string) { // it also changes the type to be ValueTypeInt. // Calling this function on zero-initialized Value will cause a panic. func (v Value) SetInt(iv int64) { + v.getState().AssertMutable() v.getOrig().Value = &otlpcommon.AnyValue_IntValue{IntValue: iv} } @@ -271,6 +277,7 @@ func (v Value) SetInt(iv int64) { // it also changes the type to be ValueTypeDouble. // Calling this function on zero-initialized Value will cause a panic. func (v Value) SetDouble(dv float64) { + v.getState().AssertMutable() v.getOrig().Value = &otlpcommon.AnyValue_DoubleValue{DoubleValue: dv} } @@ -278,35 +285,41 @@ func (v Value) SetDouble(dv float64) { // it also changes the type to be ValueTypeBool. // Calling this function on zero-initialized Value will cause a panic. func (v Value) SetBool(bv bool) { + v.getState().AssertMutable() v.getOrig().Value = &otlpcommon.AnyValue_BoolValue{BoolValue: bv} } // SetEmptyBytes sets value to an empty byte slice and returns it. // Calling this function on zero-initialized Value will cause a panic. func (v Value) SetEmptyBytes() ByteSlice { + v.getState().AssertMutable() bv := otlpcommon.AnyValue_BytesValue{BytesValue: nil} v.getOrig().Value = &bv - return ByteSlice(internal.NewByteSlice(&bv.BytesValue)) + return ByteSlice(internal.NewByteSlice(&bv.BytesValue, v.getState())) } // SetEmptyMap sets value to an empty map and returns it. // Calling this function on zero-initialized Value will cause a panic. func (v Value) SetEmptyMap() Map { + v.getState().AssertMutable() kv := &otlpcommon.AnyValue_KvlistValue{KvlistValue: &otlpcommon.KeyValueList{}} v.getOrig().Value = kv - return newMap(&kv.KvlistValue.Values) + return newMap(&kv.KvlistValue.Values, v.getState()) } // SetEmptySlice sets value to an empty slice and returns it. // Calling this function on zero-initialized Value will cause a panic. func (v Value) SetEmptySlice() Slice { + v.getState().AssertMutable() av := &otlpcommon.AnyValue_ArrayValue{ArrayValue: &otlpcommon.ArrayValue{}} v.getOrig().Value = av - return newSlice(&av.ArrayValue.Values) + return newSlice(&av.ArrayValue.Values, v.getState()) } // CopyTo copies the Value instance overriding the destination. +// Calling this function on zero-initialized Value will cause a panic. func (v Value) CopyTo(dest Value) { + dest.getState().AssertMutable() destOrig := dest.getOrig() switch ov := v.getOrig().Value.(type) { case *otlpcommon.AnyValue_KvlistValue: @@ -320,7 +333,7 @@ func (v Value) CopyTo(dest Value) { return } // Deep copy to dest. - newMap(&ov.KvlistValue.Values).CopyTo(newMap(&kv.KvlistValue.Values)) + newMap(&ov.KvlistValue.Values, v.getState()).CopyTo(newMap(&kv.KvlistValue.Values, dest.getState())) case *otlpcommon.AnyValue_ArrayValue: av, ok := destOrig.Value.(*otlpcommon.AnyValue_ArrayValue) if !ok { @@ -332,7 +345,7 @@ func (v Value) CopyTo(dest Value) { return } // Deep copy to dest. - newSlice(&ov.ArrayValue.Values).CopyTo(newSlice(&av.ArrayValue.Values)) + newSlice(&ov.ArrayValue.Values, v.getState()).CopyTo(newSlice(&av.ArrayValue.Values, dest.getState())) case *otlpcommon.AnyValue_BytesValue: bv, ok := destOrig.Value.(*otlpcommon.AnyValue_BytesValue) if !ok { @@ -350,6 +363,7 @@ func (v Value) CopyTo(dest Value) { // AsString converts an OTLP Value object of any type to its equivalent string // representation. This differs from Str which only returns a non-empty value // if the ValueType is ValueTypeStr. +// Calling this function on zero-initialized Value will cause a panic. func (v Value) AsString() string { switch v.Type() { case ValueTypeEmpty: @@ -438,28 +452,32 @@ func (v Value) AsRaw() any { func newKeyValueString(k string, v string) otlpcommon.KeyValue { orig := otlpcommon.KeyValue{Key: k} - akv := newValue(&orig.Value) + state := internal.StateMutable + akv := newValue(&orig.Value, &state) akv.SetStr(v) return orig } func newKeyValueInt(k string, v int64) otlpcommon.KeyValue { orig := otlpcommon.KeyValue{Key: k} - akv := newValue(&orig.Value) + state := internal.StateMutable + akv := newValue(&orig.Value, &state) akv.SetInt(v) return orig } func newKeyValueDouble(k string, v float64) otlpcommon.KeyValue { orig := otlpcommon.KeyValue{Key: k} - akv := newValue(&orig.Value) + state := internal.StateMutable + akv := newValue(&orig.Value, &state) akv.SetDouble(v) return orig } func newKeyValueBool(k string, v bool) otlpcommon.KeyValue { orig := otlpcommon.KeyValue{Key: k} - akv := newValue(&orig.Value) + state := internal.StateMutable + akv := newValue(&orig.Value, &state) akv.SetBool(v) return orig } diff --git a/pdata/pcommon/value_test.go b/pdata/pcommon/value_test.go index 1a4ed8fea4d..920bd0b6e96 100644 --- a/pdata/pcommon/value_test.go +++ b/pdata/pcommon/value_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/pdata/internal" otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1" ) @@ -44,6 +45,36 @@ func TestValue(t *testing.T) { assert.EqualValues(t, ValueTypeSlice, v.Type()) } +func TestValueReadOnly(t *testing.T) { + state := internal.StateReadOnly + v := newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_StringValue{StringValue: "v"}}, &state) + + assert.EqualValues(t, ValueTypeStr, v.Type()) + assert.EqualValues(t, "v", v.Str()) + assert.EqualValues(t, 0, v.Int()) + assert.EqualValues(t, 0, v.Double()) + assert.False(t, v.Bool()) + assert.EqualValues(t, ByteSlice{}, v.Bytes()) + assert.EqualValues(t, Map{}, v.Map()) + assert.EqualValues(t, Slice{}, v.Slice()) + + assert.EqualValues(t, "v", v.AsString()) + + assert.Panics(t, func() { v.SetStr("abc") }) + assert.Panics(t, func() { v.SetInt(123) }) + assert.Panics(t, func() { v.SetDouble(3.4) }) + assert.Panics(t, func() { v.SetBool(true) }) + assert.Panics(t, func() { v.SetEmptyBytes() }) + assert.Panics(t, func() { v.SetEmptyMap() }) + assert.Panics(t, func() { v.SetEmptySlice() }) + + v2 := NewValueEmpty() + v.CopyTo(v2) + assert.Equal(t, v.AsRaw(), v2.AsRaw()) + assert.Panics(t, func() { v2.CopyTo(v) }) + +} + func TestValueType(t *testing.T) { assert.EqualValues(t, "Empty", ValueTypeEmpty.String()) assert.EqualValues(t, "Str", ValueTypeStr.String()) @@ -128,7 +159,8 @@ func TestValueMap(t *testing.T) { // Test nil KvlistValue case for Map() func. orig := &otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_KvlistValue{KvlistValue: nil}} - m1 = newValue(orig) + state := internal.StateMutable + m1 = newValue(orig, &state) assert.EqualValues(t, Map{}, m1.Map()) } @@ -165,8 +197,9 @@ func TestValueSlice(t *testing.T) { assert.EqualValues(t, "somestr", v.Str()) // Test nil values case for Slice() func. - a1 = newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_ArrayValue{ArrayValue: nil}}) - assert.EqualValues(t, newSlice(nil), a1.Slice()) + state := internal.StateMutable + a1 = newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_ArrayValue{ArrayValue: nil}}, &state) + assert.EqualValues(t, newSlice(nil, nil), a1.Slice()) } func TestNilOrigSetValue(t *testing.T) { @@ -200,26 +233,28 @@ func TestNilOrigSetValue(t *testing.T) { } func TestValue_CopyTo(t *testing.T) { + state := internal.StateMutable + // Test nil KvlistValue case for Map() func. dest := NewValueEmpty() orig := &otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_KvlistValue{KvlistValue: nil}} - newValue(orig).CopyTo(dest) + newValue(orig, &state).CopyTo(dest) assert.Nil(t, dest.getOrig().Value.(*otlpcommon.AnyValue_KvlistValue).KvlistValue) // Test nil ArrayValue case for Slice() func. dest = NewValueEmpty() orig = &otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_ArrayValue{ArrayValue: nil}} - newValue(orig).CopyTo(dest) + newValue(orig, &state).CopyTo(dest) assert.Nil(t, dest.getOrig().Value.(*otlpcommon.AnyValue_ArrayValue).ArrayValue) // Test copy empty value. orig = &otlpcommon.AnyValue{} - newValue(orig).CopyTo(dest) + newValue(orig, &state).CopyTo(dest) assert.Nil(t, dest.getOrig().Value) av := NewValueEmpty() destVal := otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_IntValue{}} - av.CopyTo(newValue(&destVal)) + av.CopyTo(newValue(&destVal, &state)) assert.EqualValues(t, nil, destVal.Value) } @@ -228,7 +263,8 @@ func TestSliceWithNilValues(t *testing.T) { {}, {Value: &otlpcommon.AnyValue_StringValue{StringValue: "test_value"}}, } - sm := newSlice(&origWithNil) + state := internal.StateMutable + sm := newSlice(&origWithNil, &state) val := sm.At(0) assert.EqualValues(t, ValueTypeEmpty, val.Type()) @@ -520,6 +556,29 @@ func TestNewValueFromRawInvalid(t *testing.T) { assert.EqualError(t, actual.FromRaw(ValueTypeDouble), "") } +func TestInvalidValue(t *testing.T) { + v := Value{} + assert.Equal(t, false, v.Bool()) + assert.Equal(t, int64(0), v.Int()) + assert.Equal(t, float64(0), v.Double()) + assert.Equal(t, "", v.Str()) + assert.Equal(t, ByteSlice{}, v.Bytes()) + assert.Equal(t, Map{}, v.Map()) + assert.Equal(t, Slice{}, v.Slice()) + assert.Panics(t, func() { v.AsString() }) + assert.Panics(t, func() { v.AsRaw() }) + assert.Panics(t, func() { _ = v.FromRaw(1) }) + assert.Panics(t, func() { v.Type() }) + assert.Panics(t, func() { v.SetStr("") }) + assert.Panics(t, func() { v.SetInt(0) }) + assert.Panics(t, func() { v.SetDouble(0) }) + assert.Panics(t, func() { v.SetBool(false) }) + assert.Panics(t, func() { v.SetEmptyBytes() }) + assert.Panics(t, func() { v.SetEmptyMap() }) + assert.Panics(t, func() { v.SetEmptySlice() }) + assert.Panics(t, func() { v.CopyTo(NewValueEmpty()) }) +} + func generateTestValueMap() Value { ret := NewValueMap() attrMap := ret.Map() diff --git a/pdata/plog/generated_logrecord.go b/pdata/plog/generated_logrecord.go index a20f3027b0b..5e9984a244c 100644 --- a/pdata/plog/generated_logrecord.go +++ b/pdata/plog/generated_logrecord.go @@ -21,11 +21,12 @@ import ( // Must use NewLogRecord function to create new instances. // Important: zero-initialized instance is not valid for use. type LogRecord struct { - orig *otlplogs.LogRecord + orig *otlplogs.LogRecord + state *internal.State } -func newLogRecord(orig *otlplogs.LogRecord) LogRecord { - return LogRecord{orig} +func newLogRecord(orig *otlplogs.LogRecord, state *internal.State) LogRecord { + return LogRecord{orig: orig, state: state} } // NewLogRecord creates a new empty LogRecord. @@ -33,12 +34,15 @@ func newLogRecord(orig *otlplogs.LogRecord) LogRecord { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewLogRecord() LogRecord { - return newLogRecord(&otlplogs.LogRecord{}) + state := internal.StateMutable + return newLogRecord(&otlplogs.LogRecord{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms LogRecord) MoveTo(dest LogRecord) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlplogs.LogRecord{} } @@ -50,6 +54,7 @@ func (ms LogRecord) ObservedTimestamp() pcommon.Timestamp { // SetObservedTimestamp replaces the observedtimestamp associated with this LogRecord. func (ms LogRecord) SetObservedTimestamp(v pcommon.Timestamp) { + ms.state.AssertMutable() ms.orig.ObservedTimeUnixNano = uint64(v) } @@ -60,6 +65,7 @@ func (ms LogRecord) Timestamp() pcommon.Timestamp { // SetTimestamp replaces the timestamp associated with this LogRecord. func (ms LogRecord) SetTimestamp(v pcommon.Timestamp) { + ms.state.AssertMutable() ms.orig.TimeUnixNano = uint64(v) } @@ -70,6 +76,7 @@ func (ms LogRecord) TraceID() pcommon.TraceID { // SetTraceID replaces the traceid associated with this LogRecord. func (ms LogRecord) SetTraceID(v pcommon.TraceID) { + ms.state.AssertMutable() ms.orig.TraceId = data.TraceID(v) } @@ -80,6 +87,7 @@ func (ms LogRecord) SpanID() pcommon.SpanID { // SetSpanID replaces the spanid associated with this LogRecord. func (ms LogRecord) SetSpanID(v pcommon.SpanID) { + ms.state.AssertMutable() ms.orig.SpanId = data.SpanID(v) } @@ -90,6 +98,7 @@ func (ms LogRecord) Flags() LogRecordFlags { // SetFlags replaces the flags associated with this LogRecord. func (ms LogRecord) SetFlags(v LogRecordFlags) { + ms.state.AssertMutable() ms.orig.Flags = uint32(v) } @@ -100,6 +109,7 @@ func (ms LogRecord) SeverityText() string { // SetSeverityText replaces the severitytext associated with this LogRecord. func (ms LogRecord) SetSeverityText(v string) { + ms.state.AssertMutable() ms.orig.SeverityText = v } @@ -110,17 +120,18 @@ func (ms LogRecord) SeverityNumber() SeverityNumber { // SetSeverityNumber replaces the severitynumber associated with this LogRecord. func (ms LogRecord) SetSeverityNumber(v SeverityNumber) { + ms.state.AssertMutable() ms.orig.SeverityNumber = otlplogs.SeverityNumber(v) } // Body returns the body associated with this LogRecord. func (ms LogRecord) Body() pcommon.Value { - return pcommon.Value(internal.NewValue(&ms.orig.Body)) + return pcommon.Value(internal.NewValue(&ms.orig.Body, ms.state)) } // Attributes returns the Attributes associated with this LogRecord. func (ms LogRecord) Attributes() pcommon.Map { - return pcommon.Map(internal.NewMap(&ms.orig.Attributes)) + return pcommon.Map(internal.NewMap(&ms.orig.Attributes, ms.state)) } // DroppedAttributesCount returns the droppedattributescount associated with this LogRecord. @@ -130,11 +141,13 @@ func (ms LogRecord) DroppedAttributesCount() uint32 { // SetDroppedAttributesCount replaces the droppedattributescount associated with this LogRecord. func (ms LogRecord) SetDroppedAttributesCount(v uint32) { + ms.state.AssertMutable() ms.orig.DroppedAttributesCount = v } // CopyTo copies all properties from the current struct overriding the destination. func (ms LogRecord) CopyTo(dest LogRecord) { + dest.state.AssertMutable() dest.SetObservedTimestamp(ms.ObservedTimestamp()) dest.SetTimestamp(ms.Timestamp()) dest.SetTraceID(ms.TraceID()) diff --git a/pdata/plog/generated_logrecord_test.go b/pdata/plog/generated_logrecord_test.go index 9ff261d1044..81447572ac3 100644 --- a/pdata/plog/generated_logrecord_test.go +++ b/pdata/plog/generated_logrecord_test.go @@ -23,6 +23,9 @@ func TestLogRecord_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewLogRecord(), ms) assert.Equal(t, generateTestLogRecord(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newLogRecord(&otlplogs.LogRecord{}, &sharedState)) }) + assert.Panics(t, func() { newLogRecord(&otlplogs.LogRecord{}, &sharedState).MoveTo(dest) }) } func TestLogRecord_CopyTo(t *testing.T) { @@ -33,6 +36,8 @@ func TestLogRecord_CopyTo(t *testing.T) { orig = generateTestLogRecord() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newLogRecord(&otlplogs.LogRecord{}, &sharedState)) }) } func TestLogRecord_ObservedTimestamp(t *testing.T) { @@ -80,6 +85,8 @@ func TestLogRecord_SeverityText(t *testing.T) { assert.Equal(t, "", ms.SeverityText()) ms.SetSeverityText("INFO") assert.Equal(t, "INFO", ms.SeverityText()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newLogRecord(&otlplogs.LogRecord{}, &sharedState).SetSeverityText("INFO") }) } func TestLogRecord_SeverityNumber(t *testing.T) { @@ -108,6 +115,8 @@ func TestLogRecord_DroppedAttributesCount(t *testing.T) { assert.Equal(t, uint32(0), ms.DroppedAttributesCount()) ms.SetDroppedAttributesCount(uint32(17)) assert.Equal(t, uint32(17), ms.DroppedAttributesCount()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newLogRecord(&otlplogs.LogRecord{}, &sharedState).SetDroppedAttributesCount(uint32(17)) }) } func generateTestLogRecord() LogRecord { @@ -124,7 +133,7 @@ func fillTestLogRecord(tv LogRecord) { tv.orig.Flags = 1 tv.orig.SeverityText = "INFO" tv.orig.SeverityNumber = otlplogs.SeverityNumber(5) - internal.FillTestValue(internal.NewValue(&tv.orig.Body)) - internal.FillTestMap(internal.NewMap(&tv.orig.Attributes)) + internal.FillTestValue(internal.NewValue(&tv.orig.Body, tv.state)) + internal.FillTestMap(internal.NewMap(&tv.orig.Attributes, tv.state)) tv.orig.DroppedAttributesCount = uint32(17) } diff --git a/pdata/plog/generated_logrecordslice.go b/pdata/plog/generated_logrecordslice.go index 6c564822d6e..a900b4e1c7e 100644 --- a/pdata/plog/generated_logrecordslice.go +++ b/pdata/plog/generated_logrecordslice.go @@ -9,6 +9,7 @@ package plog import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewLogRecordSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type LogRecordSlice struct { - orig *[]*otlplogs.LogRecord + orig *[]*otlplogs.LogRecord + state *internal.State } -func newLogRecordSlice(orig *[]*otlplogs.LogRecord) LogRecordSlice { - return LogRecordSlice{orig} +func newLogRecordSlice(orig *[]*otlplogs.LogRecord, state *internal.State) LogRecordSlice { + return LogRecordSlice{orig: orig, state: state} } // NewLogRecordSlice creates a LogRecordSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewLogRecordSlice() LogRecordSlice { orig := []*otlplogs.LogRecord(nil) - return newLogRecordSlice(&orig) + state := internal.StateMutable + return newLogRecordSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es LogRecordSlice) Len() int { // ... // Do something with the element // } func (es LogRecordSlice) At(i int) LogRecord { - return newLogRecord((*es.orig)[i]) + return newLogRecord((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es LogRecordSlice) At(i int) LogRecord { // // Here should set all the values for e. // } func (es LogRecordSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es LogRecordSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty LogRecord. // It returns the newly added LogRecord. func (es LogRecordSlice) AppendEmpty() LogRecord { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlplogs.LogRecord{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es LogRecordSlice) AppendEmpty() LogRecord { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es LogRecordSlice) MoveAndAppendTo(dest LogRecordSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es LogRecordSlice) MoveAndAppendTo(dest LogRecordSlice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es LogRecordSlice) RemoveIf(f func(LogRecord) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es LogRecordSlice) RemoveIf(f func(LogRecord) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es LogRecordSlice) CopyTo(dest LogRecordSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newLogRecord((*es.orig)[i]).CopyTo(newLogRecord((*dest.orig)[i])) + newLogRecord((*es.orig)[i], es.state).CopyTo(newLogRecord((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es LogRecordSlice) CopyTo(dest LogRecordSlice) { wrappers := make([]*otlplogs.LogRecord, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newLogRecord((*es.orig)[i]).CopyTo(newLogRecord(wrappers[i])) + newLogRecord((*es.orig)[i], es.state).CopyTo(newLogRecord(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es LogRecordSlice) CopyTo(dest LogRecordSlice) { // provided less function so that two instances of LogRecordSlice // can be compared. func (es LogRecordSlice) Sort(less func(a, b LogRecord) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/plog/generated_logrecordslice_test.go b/pdata/plog/generated_logrecordslice_test.go index 183b88601b2..ff47a245987 100644 --- a/pdata/plog/generated_logrecordslice_test.go +++ b/pdata/plog/generated_logrecordslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" ) func TestLogRecordSlice(t *testing.T) { es := NewLogRecordSlice() assert.Equal(t, 0, es.Len()) - es = newLogRecordSlice(&[]*otlplogs.LogRecord{}) + state := internal.StateMutable + es = newLogRecordSlice(&[]*otlplogs.LogRecord{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewLogRecord() @@ -32,6 +34,19 @@ func TestLogRecordSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestLogRecordSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newLogRecordSlice(&[]*otlplogs.LogRecord{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewLogRecordSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestLogRecordSlice_CopyTo(t *testing.T) { dest := NewLogRecordSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestLogRecordSlice(es LogRecordSlice) { *es.orig = make([]*otlplogs.LogRecord, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlplogs.LogRecord{} - fillTestLogRecord(newLogRecord((*es.orig)[i])) + fillTestLogRecord(newLogRecord((*es.orig)[i], es.state)) } } diff --git a/pdata/plog/generated_resourcelogs.go b/pdata/plog/generated_resourcelogs.go index 870d53a6373..1d240e03975 100644 --- a/pdata/plog/generated_resourcelogs.go +++ b/pdata/plog/generated_resourcelogs.go @@ -20,11 +20,12 @@ import ( // Must use NewResourceLogs function to create new instances. // Important: zero-initialized instance is not valid for use. type ResourceLogs struct { - orig *otlplogs.ResourceLogs + orig *otlplogs.ResourceLogs + state *internal.State } -func newResourceLogs(orig *otlplogs.ResourceLogs) ResourceLogs { - return ResourceLogs{orig} +func newResourceLogs(orig *otlplogs.ResourceLogs, state *internal.State) ResourceLogs { + return ResourceLogs{orig: orig, state: state} } // NewResourceLogs creates a new empty ResourceLogs. @@ -32,19 +33,22 @@ func newResourceLogs(orig *otlplogs.ResourceLogs) ResourceLogs { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewResourceLogs() ResourceLogs { - return newResourceLogs(&otlplogs.ResourceLogs{}) + state := internal.StateMutable + return newResourceLogs(&otlplogs.ResourceLogs{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms ResourceLogs) MoveTo(dest ResourceLogs) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlplogs.ResourceLogs{} } // Resource returns the resource associated with this ResourceLogs. func (ms ResourceLogs) Resource() pcommon.Resource { - return pcommon.Resource(internal.NewResource(&ms.orig.Resource)) + return pcommon.Resource(internal.NewResource(&ms.orig.Resource, ms.state)) } // SchemaUrl returns the schemaurl associated with this ResourceLogs. @@ -54,16 +58,18 @@ func (ms ResourceLogs) SchemaUrl() string { // SetSchemaUrl replaces the schemaurl associated with this ResourceLogs. func (ms ResourceLogs) SetSchemaUrl(v string) { + ms.state.AssertMutable() ms.orig.SchemaUrl = v } // ScopeLogs returns the ScopeLogs associated with this ResourceLogs. func (ms ResourceLogs) ScopeLogs() ScopeLogsSlice { - return newScopeLogsSlice(&ms.orig.ScopeLogs) + return newScopeLogsSlice(&ms.orig.ScopeLogs, ms.state) } // CopyTo copies all properties from the current struct overriding the destination. func (ms ResourceLogs) CopyTo(dest ResourceLogs) { + dest.state.AssertMutable() ms.Resource().CopyTo(dest.Resource()) dest.SetSchemaUrl(ms.SchemaUrl()) ms.ScopeLogs().CopyTo(dest.ScopeLogs()) diff --git a/pdata/plog/generated_resourcelogs_test.go b/pdata/plog/generated_resourcelogs_test.go index c0c051ba292..8f705a26816 100644 --- a/pdata/plog/generated_resourcelogs_test.go +++ b/pdata/plog/generated_resourcelogs_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/pdata/internal" + otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -21,6 +22,9 @@ func TestResourceLogs_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewResourceLogs(), ms) assert.Equal(t, generateTestResourceLogs(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newResourceLogs(&otlplogs.ResourceLogs{}, &sharedState)) }) + assert.Panics(t, func() { newResourceLogs(&otlplogs.ResourceLogs{}, &sharedState).MoveTo(dest) }) } func TestResourceLogs_CopyTo(t *testing.T) { @@ -31,6 +35,8 @@ func TestResourceLogs_CopyTo(t *testing.T) { orig = generateTestResourceLogs() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newResourceLogs(&otlplogs.ResourceLogs{}, &sharedState)) }) } func TestResourceLogs_Resource(t *testing.T) { @@ -44,6 +50,10 @@ func TestResourceLogs_SchemaUrl(t *testing.T) { assert.Equal(t, "", ms.SchemaUrl()) ms.SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0") assert.Equal(t, "https://opentelemetry.io/schemas/1.5.0", ms.SchemaUrl()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newResourceLogs(&otlplogs.ResourceLogs{}, &sharedState).SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0") + }) } func TestResourceLogs_ScopeLogs(t *testing.T) { @@ -60,7 +70,7 @@ func generateTestResourceLogs() ResourceLogs { } func fillTestResourceLogs(tv ResourceLogs) { - internal.FillTestResource(internal.NewResource(&tv.orig.Resource)) + internal.FillTestResource(internal.NewResource(&tv.orig.Resource, tv.state)) tv.orig.SchemaUrl = "https://opentelemetry.io/schemas/1.5.0" - fillTestScopeLogsSlice(newScopeLogsSlice(&tv.orig.ScopeLogs)) + fillTestScopeLogsSlice(newScopeLogsSlice(&tv.orig.ScopeLogs, tv.state)) } diff --git a/pdata/plog/generated_resourcelogsslice.go b/pdata/plog/generated_resourcelogsslice.go index 19bd2e58ddc..d2fc54de80b 100644 --- a/pdata/plog/generated_resourcelogsslice.go +++ b/pdata/plog/generated_resourcelogsslice.go @@ -9,6 +9,7 @@ package plog import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewResourceLogsSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type ResourceLogsSlice struct { - orig *[]*otlplogs.ResourceLogs + orig *[]*otlplogs.ResourceLogs + state *internal.State } -func newResourceLogsSlice(orig *[]*otlplogs.ResourceLogs) ResourceLogsSlice { - return ResourceLogsSlice{orig} +func newResourceLogsSlice(orig *[]*otlplogs.ResourceLogs, state *internal.State) ResourceLogsSlice { + return ResourceLogsSlice{orig: orig, state: state} } // NewResourceLogsSlice creates a ResourceLogsSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewResourceLogsSlice() ResourceLogsSlice { orig := []*otlplogs.ResourceLogs(nil) - return newResourceLogsSlice(&orig) + state := internal.StateMutable + return newResourceLogsSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es ResourceLogsSlice) Len() int { // ... // Do something with the element // } func (es ResourceLogsSlice) At(i int) ResourceLogs { - return newResourceLogs((*es.orig)[i]) + return newResourceLogs((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es ResourceLogsSlice) At(i int) ResourceLogs { // // Here should set all the values for e. // } func (es ResourceLogsSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es ResourceLogsSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty ResourceLogs. // It returns the newly added ResourceLogs. func (es ResourceLogsSlice) AppendEmpty() ResourceLogs { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlplogs.ResourceLogs{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es ResourceLogsSlice) AppendEmpty() ResourceLogs { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es ResourceLogsSlice) MoveAndAppendTo(dest ResourceLogsSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es ResourceLogsSlice) MoveAndAppendTo(dest ResourceLogsSlice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es ResourceLogsSlice) RemoveIf(f func(ResourceLogs) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es ResourceLogsSlice) RemoveIf(f func(ResourceLogs) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es ResourceLogsSlice) CopyTo(dest ResourceLogsSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newResourceLogs((*es.orig)[i]).CopyTo(newResourceLogs((*dest.orig)[i])) + newResourceLogs((*es.orig)[i], es.state).CopyTo(newResourceLogs((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es ResourceLogsSlice) CopyTo(dest ResourceLogsSlice) { wrappers := make([]*otlplogs.ResourceLogs, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newResourceLogs((*es.orig)[i]).CopyTo(newResourceLogs(wrappers[i])) + newResourceLogs((*es.orig)[i], es.state).CopyTo(newResourceLogs(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es ResourceLogsSlice) CopyTo(dest ResourceLogsSlice) { // provided less function so that two instances of ResourceLogsSlice // can be compared. func (es ResourceLogsSlice) Sort(less func(a, b ResourceLogs) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/plog/generated_resourcelogsslice_test.go b/pdata/plog/generated_resourcelogsslice_test.go index 3c4d2ba81fc..993a597f119 100644 --- a/pdata/plog/generated_resourcelogsslice_test.go +++ b/pdata/plog/generated_resourcelogsslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" ) func TestResourceLogsSlice(t *testing.T) { es := NewResourceLogsSlice() assert.Equal(t, 0, es.Len()) - es = newResourceLogsSlice(&[]*otlplogs.ResourceLogs{}) + state := internal.StateMutable + es = newResourceLogsSlice(&[]*otlplogs.ResourceLogs{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewResourceLogs() @@ -32,6 +34,19 @@ func TestResourceLogsSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestResourceLogsSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newResourceLogsSlice(&[]*otlplogs.ResourceLogs{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewResourceLogsSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestResourceLogsSlice_CopyTo(t *testing.T) { dest := NewResourceLogsSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestResourceLogsSlice(es ResourceLogsSlice) { *es.orig = make([]*otlplogs.ResourceLogs, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlplogs.ResourceLogs{} - fillTestResourceLogs(newResourceLogs((*es.orig)[i])) + fillTestResourceLogs(newResourceLogs((*es.orig)[i], es.state)) } } diff --git a/pdata/plog/generated_scopelogs.go b/pdata/plog/generated_scopelogs.go index c4d399103b2..6e45a9627f8 100644 --- a/pdata/plog/generated_scopelogs.go +++ b/pdata/plog/generated_scopelogs.go @@ -20,11 +20,12 @@ import ( // Must use NewScopeLogs function to create new instances. // Important: zero-initialized instance is not valid for use. type ScopeLogs struct { - orig *otlplogs.ScopeLogs + orig *otlplogs.ScopeLogs + state *internal.State } -func newScopeLogs(orig *otlplogs.ScopeLogs) ScopeLogs { - return ScopeLogs{orig} +func newScopeLogs(orig *otlplogs.ScopeLogs, state *internal.State) ScopeLogs { + return ScopeLogs{orig: orig, state: state} } // NewScopeLogs creates a new empty ScopeLogs. @@ -32,19 +33,22 @@ func newScopeLogs(orig *otlplogs.ScopeLogs) ScopeLogs { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewScopeLogs() ScopeLogs { - return newScopeLogs(&otlplogs.ScopeLogs{}) + state := internal.StateMutable + return newScopeLogs(&otlplogs.ScopeLogs{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms ScopeLogs) MoveTo(dest ScopeLogs) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlplogs.ScopeLogs{} } // Scope returns the scope associated with this ScopeLogs. func (ms ScopeLogs) Scope() pcommon.InstrumentationScope { - return pcommon.InstrumentationScope(internal.NewInstrumentationScope(&ms.orig.Scope)) + return pcommon.InstrumentationScope(internal.NewInstrumentationScope(&ms.orig.Scope, ms.state)) } // SchemaUrl returns the schemaurl associated with this ScopeLogs. @@ -54,16 +58,18 @@ func (ms ScopeLogs) SchemaUrl() string { // SetSchemaUrl replaces the schemaurl associated with this ScopeLogs. func (ms ScopeLogs) SetSchemaUrl(v string) { + ms.state.AssertMutable() ms.orig.SchemaUrl = v } // LogRecords returns the LogRecords associated with this ScopeLogs. func (ms ScopeLogs) LogRecords() LogRecordSlice { - return newLogRecordSlice(&ms.orig.LogRecords) + return newLogRecordSlice(&ms.orig.LogRecords, ms.state) } // CopyTo copies all properties from the current struct overriding the destination. func (ms ScopeLogs) CopyTo(dest ScopeLogs) { + dest.state.AssertMutable() ms.Scope().CopyTo(dest.Scope()) dest.SetSchemaUrl(ms.SchemaUrl()) ms.LogRecords().CopyTo(dest.LogRecords()) diff --git a/pdata/plog/generated_scopelogs_test.go b/pdata/plog/generated_scopelogs_test.go index 5b58c00dd80..181513ffa59 100644 --- a/pdata/plog/generated_scopelogs_test.go +++ b/pdata/plog/generated_scopelogs_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/pdata/internal" + otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -21,6 +22,9 @@ func TestScopeLogs_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewScopeLogs(), ms) assert.Equal(t, generateTestScopeLogs(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newScopeLogs(&otlplogs.ScopeLogs{}, &sharedState)) }) + assert.Panics(t, func() { newScopeLogs(&otlplogs.ScopeLogs{}, &sharedState).MoveTo(dest) }) } func TestScopeLogs_CopyTo(t *testing.T) { @@ -31,6 +35,8 @@ func TestScopeLogs_CopyTo(t *testing.T) { orig = generateTestScopeLogs() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newScopeLogs(&otlplogs.ScopeLogs{}, &sharedState)) }) } func TestScopeLogs_Scope(t *testing.T) { @@ -44,6 +50,10 @@ func TestScopeLogs_SchemaUrl(t *testing.T) { assert.Equal(t, "", ms.SchemaUrl()) ms.SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0") assert.Equal(t, "https://opentelemetry.io/schemas/1.5.0", ms.SchemaUrl()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newScopeLogs(&otlplogs.ScopeLogs{}, &sharedState).SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0") + }) } func TestScopeLogs_LogRecords(t *testing.T) { @@ -60,7 +70,7 @@ func generateTestScopeLogs() ScopeLogs { } func fillTestScopeLogs(tv ScopeLogs) { - internal.FillTestInstrumentationScope(internal.NewInstrumentationScope(&tv.orig.Scope)) + internal.FillTestInstrumentationScope(internal.NewInstrumentationScope(&tv.orig.Scope, tv.state)) tv.orig.SchemaUrl = "https://opentelemetry.io/schemas/1.5.0" - fillTestLogRecordSlice(newLogRecordSlice(&tv.orig.LogRecords)) + fillTestLogRecordSlice(newLogRecordSlice(&tv.orig.LogRecords, tv.state)) } diff --git a/pdata/plog/generated_scopelogsslice.go b/pdata/plog/generated_scopelogsslice.go index be34e05f135..5bae8d9f9c9 100644 --- a/pdata/plog/generated_scopelogsslice.go +++ b/pdata/plog/generated_scopelogsslice.go @@ -9,6 +9,7 @@ package plog import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewScopeLogsSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type ScopeLogsSlice struct { - orig *[]*otlplogs.ScopeLogs + orig *[]*otlplogs.ScopeLogs + state *internal.State } -func newScopeLogsSlice(orig *[]*otlplogs.ScopeLogs) ScopeLogsSlice { - return ScopeLogsSlice{orig} +func newScopeLogsSlice(orig *[]*otlplogs.ScopeLogs, state *internal.State) ScopeLogsSlice { + return ScopeLogsSlice{orig: orig, state: state} } // NewScopeLogsSlice creates a ScopeLogsSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewScopeLogsSlice() ScopeLogsSlice { orig := []*otlplogs.ScopeLogs(nil) - return newScopeLogsSlice(&orig) + state := internal.StateMutable + return newScopeLogsSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es ScopeLogsSlice) Len() int { // ... // Do something with the element // } func (es ScopeLogsSlice) At(i int) ScopeLogs { - return newScopeLogs((*es.orig)[i]) + return newScopeLogs((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es ScopeLogsSlice) At(i int) ScopeLogs { // // Here should set all the values for e. // } func (es ScopeLogsSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es ScopeLogsSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty ScopeLogs. // It returns the newly added ScopeLogs. func (es ScopeLogsSlice) AppendEmpty() ScopeLogs { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlplogs.ScopeLogs{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es ScopeLogsSlice) AppendEmpty() ScopeLogs { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es ScopeLogsSlice) MoveAndAppendTo(dest ScopeLogsSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es ScopeLogsSlice) MoveAndAppendTo(dest ScopeLogsSlice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es ScopeLogsSlice) RemoveIf(f func(ScopeLogs) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es ScopeLogsSlice) RemoveIf(f func(ScopeLogs) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es ScopeLogsSlice) CopyTo(dest ScopeLogsSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newScopeLogs((*es.orig)[i]).CopyTo(newScopeLogs((*dest.orig)[i])) + newScopeLogs((*es.orig)[i], es.state).CopyTo(newScopeLogs((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es ScopeLogsSlice) CopyTo(dest ScopeLogsSlice) { wrappers := make([]*otlplogs.ScopeLogs, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newScopeLogs((*es.orig)[i]).CopyTo(newScopeLogs(wrappers[i])) + newScopeLogs((*es.orig)[i], es.state).CopyTo(newScopeLogs(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es ScopeLogsSlice) CopyTo(dest ScopeLogsSlice) { // provided less function so that two instances of ScopeLogsSlice // can be compared. func (es ScopeLogsSlice) Sort(less func(a, b ScopeLogs) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/plog/generated_scopelogsslice_test.go b/pdata/plog/generated_scopelogsslice_test.go index a18b1e9e34c..12678c7b4fc 100644 --- a/pdata/plog/generated_scopelogsslice_test.go +++ b/pdata/plog/generated_scopelogsslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" ) func TestScopeLogsSlice(t *testing.T) { es := NewScopeLogsSlice() assert.Equal(t, 0, es.Len()) - es = newScopeLogsSlice(&[]*otlplogs.ScopeLogs{}) + state := internal.StateMutable + es = newScopeLogsSlice(&[]*otlplogs.ScopeLogs{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewScopeLogs() @@ -32,6 +34,19 @@ func TestScopeLogsSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestScopeLogsSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newScopeLogsSlice(&[]*otlplogs.ScopeLogs{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewScopeLogsSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestScopeLogsSlice_CopyTo(t *testing.T) { dest := NewScopeLogsSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestScopeLogsSlice(es ScopeLogsSlice) { *es.orig = make([]*otlplogs.ScopeLogs, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlplogs.ScopeLogs{} - fillTestScopeLogs(newScopeLogs((*es.orig)[i])) + fillTestScopeLogs(newScopeLogs((*es.orig)[i], es.state)) } } diff --git a/pdata/plog/json.go b/pdata/plog/json.go index 1a877c68b30..373985e7090 100644 --- a/pdata/plog/json.go +++ b/pdata/plog/json.go @@ -15,8 +15,10 @@ import ( "go.opentelemetry.io/collector/pdata/internal/otlp" ) +// JSONMarshaler marshals pdata.Logs to JSON bytes using the OTLP/JSON format. type JSONMarshaler struct{} +// MarshalLogs to the OTLP/JSON format. func (*JSONMarshaler) MarshalLogs(ld Logs) ([]byte, error) { buf := bytes.Buffer{} pb := internal.LogsToProto(internal.Logs(ld)) @@ -26,8 +28,10 @@ func (*JSONMarshaler) MarshalLogs(ld Logs) ([]byte, error) { var _ Unmarshaler = (*JSONUnmarshaler)(nil) +// JSONUnmarshaler unmarshals OTLP/JSON formatted-bytes to pdata.Logs. type JSONUnmarshaler struct{} +// UnmarshalLogs from OTLP/JSON format into pdata.Logs. func (*JSONUnmarshaler) UnmarshalLogs(buf []byte) (Logs, error) { iter := jsoniter.ConfigFastest.BorrowIterator(buf) defer jsoniter.ConfigFastest.ReturnIterator(iter) @@ -44,7 +48,7 @@ func (ms Logs) unmarshalJsoniter(iter *jsoniter.Iterator) { iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { switch f { case "resource_logs", "resourceLogs": - iter.ReadArrayCB(func(iterator *jsoniter.Iterator) bool { + iter.ReadArrayCB(func(*jsoniter.Iterator) bool { ms.ResourceLogs().AppendEmpty().unmarshalJsoniter(iter) return true }) diff --git a/pdata/plog/logs.go b/pdata/plog/logs.go index f637077ddb4..490526090f8 100644 --- a/pdata/plog/logs.go +++ b/pdata/plog/logs.go @@ -13,18 +13,28 @@ import ( type Logs internal.Logs func newLogs(orig *otlpcollectorlog.ExportLogsServiceRequest) Logs { - return Logs(internal.NewLogs(orig)) + state := internal.StateMutable + return Logs(internal.NewLogs(orig, &state)) } func (ms Logs) getOrig() *otlpcollectorlog.ExportLogsServiceRequest { return internal.GetOrigLogs(internal.Logs(ms)) } +func (ms Logs) getState() *internal.State { + return internal.GetLogsState(internal.Logs(ms)) +} + // NewLogs creates a new Logs struct. func NewLogs() Logs { return newLogs(&otlpcollectorlog.ExportLogsServiceRequest{}) } +// IsReadOnly returns true if this Logs instance is read-only. +func (ms Logs) IsReadOnly() bool { + return *ms.getState() == internal.StateReadOnly +} + // CopyTo copies the Logs instance overriding the destination. func (ms Logs) CopyTo(dest Logs) { ms.ResourceLogs().CopyTo(dest.ResourceLogs()) @@ -47,5 +57,10 @@ func (ms Logs) LogRecordCount() int { // ResourceLogs returns the ResourceLogsSlice associated with this Logs. func (ms Logs) ResourceLogs() ResourceLogsSlice { - return newResourceLogsSlice(&ms.getOrig().ResourceLogs) + return newResourceLogsSlice(&ms.getOrig().ResourceLogs, internal.GetLogsState(internal.Logs(ms))) +} + +// MarkReadOnly marks the Logs as shared so that no further modifications can be done on it. +func (ms Logs) MarkReadOnly() { + internal.SetLogsState(internal.Logs(ms), internal.StateReadOnly) } diff --git a/pdata/plog/logs_test.go b/pdata/plog/logs_test.go index f2ec1bb78b1..9d3feef4d98 100644 --- a/pdata/plog/logs_test.go +++ b/pdata/plog/logs_test.go @@ -5,6 +5,7 @@ package plog import ( "testing" + "time" gogoproto "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/assert" @@ -13,6 +14,7 @@ import ( otlpcollectorlog "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/logs/v1" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" + "go.opentelemetry.io/collector/pdata/pcommon" ) func TestLogRecordCount(t *testing.T) { @@ -112,3 +114,60 @@ func TestLogsCopyTo(t *testing.T) { logs.CopyTo(logsCopy) assert.EqualValues(t, logs, logsCopy) } + +func TestReadOnlyLogsInvalidUsage(t *testing.T) { + logs := NewLogs() + assert.False(t, logs.IsReadOnly()) + res := logs.ResourceLogs().AppendEmpty().Resource() + res.Attributes().PutStr("k1", "v1") + logs.MarkReadOnly() + assert.True(t, logs.IsReadOnly()) + assert.Panics(t, func() { res.Attributes().PutStr("k2", "v2") }) +} + +func BenchmarkLogsUsage(b *testing.B) { + logs := NewLogs() + fillTestResourceLogsSlice(logs.ResourceLogs()) + + ts := pcommon.NewTimestampFromTime(time.Now()) + + b.ReportAllocs() + b.ResetTimer() + + for bb := 0; bb < b.N; bb++ { + for i := 0; i < logs.ResourceLogs().Len(); i++ { + rl := logs.ResourceLogs().At(i) + res := rl.Resource() + res.Attributes().PutStr("foo", "bar") + v, ok := res.Attributes().Get("foo") + assert.True(b, ok) + assert.Equal(b, "bar", v.Str()) + v.SetStr("new-bar") + assert.Equal(b, "new-bar", v.Str()) + res.Attributes().Remove("foo") + for j := 0; j < rl.ScopeLogs().Len(); j++ { + sl := rl.ScopeLogs().At(j) + sl.Scope().SetName("new_test_name") + assert.Equal(b, "new_test_name", sl.Scope().Name()) + for k := 0; k < sl.LogRecords().Len(); k++ { + lr := sl.LogRecords().At(k) + lr.Body().SetStr("new_body") + assert.Equal(b, "new_body", lr.Body().Str()) + lr.SetTimestamp(ts) + assert.Equal(b, ts, lr.Timestamp()) + } + lr := sl.LogRecords().AppendEmpty() + lr.Body().SetStr("another_log_record") + lr.SetTimestamp(ts) + lr.SetObservedTimestamp(ts) + lr.SetSeverityText("info") + lr.SetSeverityNumber(SeverityNumberInfo) + lr.Attributes().PutStr("foo", "bar") + lr.SetSpanID([8]byte{1, 2, 3, 4, 5, 6, 7, 8}) + sl.LogRecords().RemoveIf(func(lr LogRecord) bool { + return lr.Body().Str() == "another_log_record" + }) + } + } + } +} diff --git a/pdata/plog/package_test.go b/pdata/plog/package_test.go new file mode 100644 index 00000000000..16a438ebb3d --- /dev/null +++ b/pdata/plog/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package plog + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/pdata/plog/plogotlp/generated_exportpartialsuccess.go b/pdata/plog/plogotlp/generated_exportpartialsuccess.go index 5ab21e08897..bcf420c9120 100644 --- a/pdata/plog/plogotlp/generated_exportpartialsuccess.go +++ b/pdata/plog/plogotlp/generated_exportpartialsuccess.go @@ -7,6 +7,7 @@ package plogotlp import ( + "go.opentelemetry.io/collector/pdata/internal" otlpcollectorlog "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/logs/v1" ) @@ -18,11 +19,12 @@ import ( // Must use NewExportPartialSuccess function to create new instances. // Important: zero-initialized instance is not valid for use. type ExportPartialSuccess struct { - orig *otlpcollectorlog.ExportLogsPartialSuccess + orig *otlpcollectorlog.ExportLogsPartialSuccess + state *internal.State } -func newExportPartialSuccess(orig *otlpcollectorlog.ExportLogsPartialSuccess) ExportPartialSuccess { - return ExportPartialSuccess{orig} +func newExportPartialSuccess(orig *otlpcollectorlog.ExportLogsPartialSuccess, state *internal.State) ExportPartialSuccess { + return ExportPartialSuccess{orig: orig, state: state} } // NewExportPartialSuccess creates a new empty ExportPartialSuccess. @@ -30,12 +32,15 @@ func newExportPartialSuccess(orig *otlpcollectorlog.ExportLogsPartialSuccess) Ex // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewExportPartialSuccess() ExportPartialSuccess { - return newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{}) + state := internal.StateMutable + return newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms ExportPartialSuccess) MoveTo(dest ExportPartialSuccess) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpcollectorlog.ExportLogsPartialSuccess{} } @@ -47,6 +52,7 @@ func (ms ExportPartialSuccess) RejectedLogRecords() int64 { // SetRejectedLogRecords replaces the rejectedlogrecords associated with this ExportPartialSuccess. func (ms ExportPartialSuccess) SetRejectedLogRecords(v int64) { + ms.state.AssertMutable() ms.orig.RejectedLogRecords = v } @@ -57,11 +63,13 @@ func (ms ExportPartialSuccess) ErrorMessage() string { // SetErrorMessage replaces the errormessage associated with this ExportPartialSuccess. func (ms ExportPartialSuccess) SetErrorMessage(v string) { + ms.state.AssertMutable() ms.orig.ErrorMessage = v } // CopyTo copies all properties from the current struct overriding the destination. func (ms ExportPartialSuccess) CopyTo(dest ExportPartialSuccess) { + dest.state.AssertMutable() dest.SetRejectedLogRecords(ms.RejectedLogRecords()) dest.SetErrorMessage(ms.ErrorMessage()) } diff --git a/pdata/plog/plogotlp/generated_exportpartialsuccess_test.go b/pdata/plog/plogotlp/generated_exportpartialsuccess_test.go index 9df7e89b7d3..9b0fee581a1 100644 --- a/pdata/plog/plogotlp/generated_exportpartialsuccess_test.go +++ b/pdata/plog/plogotlp/generated_exportpartialsuccess_test.go @@ -10,6 +10,9 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/pdata/internal" + otlpcollectorlog "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/logs/v1" ) func TestExportPartialSuccess_MoveTo(t *testing.T) { @@ -18,6 +21,11 @@ func TestExportPartialSuccess_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewExportPartialSuccess(), ms) assert.Equal(t, generateTestExportPartialSuccess(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{}, &sharedState)) }) + assert.Panics(t, func() { + newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{}, &sharedState).MoveTo(dest) + }) } func TestExportPartialSuccess_CopyTo(t *testing.T) { @@ -28,6 +36,8 @@ func TestExportPartialSuccess_CopyTo(t *testing.T) { orig = generateTestExportPartialSuccess() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{}, &sharedState)) }) } func TestExportPartialSuccess_RejectedLogRecords(t *testing.T) { @@ -35,6 +45,10 @@ func TestExportPartialSuccess_RejectedLogRecords(t *testing.T) { assert.Equal(t, int64(0), ms.RejectedLogRecords()) ms.SetRejectedLogRecords(int64(13)) assert.Equal(t, int64(13), ms.RejectedLogRecords()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{}, &sharedState).SetRejectedLogRecords(int64(13)) + }) } func TestExportPartialSuccess_ErrorMessage(t *testing.T) { @@ -42,6 +56,10 @@ func TestExportPartialSuccess_ErrorMessage(t *testing.T) { assert.Equal(t, "", ms.ErrorMessage()) ms.SetErrorMessage("error message") assert.Equal(t, "error message", ms.ErrorMessage()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{}, &sharedState).SetErrorMessage("error message") + }) } func generateTestExportPartialSuccess() ExportPartialSuccess { diff --git a/pdata/plog/plogotlp/grpc.go b/pdata/plog/plogotlp/grpc.go index 4a7e66cb852..35d9fd85fcd 100644 --- a/pdata/plog/plogotlp/grpc.go +++ b/pdata/plog/plogotlp/grpc.go @@ -10,6 +10,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "go.opentelemetry.io/collector/pdata/internal" otlpcollectorlog "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/logs/v1" "go.opentelemetry.io/collector/pdata/internal/otlp" ) @@ -39,7 +40,11 @@ type grpcClient struct { func (c *grpcClient) Export(ctx context.Context, request ExportRequest, opts ...grpc.CallOption) (ExportResponse, error) { rsp, err := c.rawClient.Export(ctx, request.orig, opts...) - return ExportResponse{orig: rsp}, err + if err != nil { + return ExportResponse{}, err + } + state := internal.StateMutable + return ExportResponse{orig: rsp, state: &state}, err } func (c *grpcClient) unexported() {} @@ -79,6 +84,7 @@ type rawLogsServer struct { func (s rawLogsServer) Export(ctx context.Context, request *otlpcollectorlog.ExportLogsServiceRequest) (*otlpcollectorlog.ExportLogsServiceResponse, error) { otlp.MigrateLogs(request.ResourceLogs) - rsp, err := s.srv.Export(ctx, ExportRequest{orig: request}) + state := internal.StateMutable + rsp, err := s.srv.Export(ctx, ExportRequest{orig: request, state: &state}) return rsp.orig, err } diff --git a/pdata/plog/plogotlp/package_test.go b/pdata/plog/plogotlp/package_test.go new file mode 100644 index 00000000000..b8cef1c0a76 --- /dev/null +++ b/pdata/plog/plogotlp/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package plogotlp + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/pdata/plog/plogotlp/request.go b/pdata/plog/plogotlp/request.go index 786d83b7c44..0401846ab2e 100644 --- a/pdata/plog/plogotlp/request.go +++ b/pdata/plog/plogotlp/request.go @@ -18,19 +18,27 @@ var jsonUnmarshaler = &plog.JSONUnmarshaler{} // ExportRequest represents the request for gRPC/HTTP client/server. // It's a wrapper for plog.Logs data. type ExportRequest struct { - orig *otlpcollectorlog.ExportLogsServiceRequest + orig *otlpcollectorlog.ExportLogsServiceRequest + state *internal.State } // NewExportRequest returns an empty ExportRequest. func NewExportRequest() ExportRequest { - return ExportRequest{orig: &otlpcollectorlog.ExportLogsServiceRequest{}} + state := internal.StateMutable + return ExportRequest{ + orig: &otlpcollectorlog.ExportLogsServiceRequest{}, + state: &state, + } } // NewExportRequestFromLogs returns a ExportRequest from plog.Logs. // Because ExportRequest is a wrapper for plog.Logs, // any changes to the provided Logs struct will be reflected in the ExportRequest and vice versa. func NewExportRequestFromLogs(ld plog.Logs) ExportRequest { - return ExportRequest{orig: internal.GetOrigLogs(internal.Logs(ld))} + return ExportRequest{ + orig: internal.GetOrigLogs(internal.Logs(ld)), + state: internal.GetLogsState(internal.Logs(ld)), + } } // MarshalProto marshals ExportRequest into proto bytes. @@ -67,5 +75,5 @@ func (ms ExportRequest) UnmarshalJSON(data []byte) error { } func (ms ExportRequest) Logs() plog.Logs { - return plog.Logs(internal.NewLogs(ms.orig)) + return plog.Logs(internal.NewLogs(ms.orig, ms.state)) } diff --git a/pdata/plog/plogotlp/response.go b/pdata/plog/plogotlp/response.go index 439c2560ffa..293d2d2cf84 100644 --- a/pdata/plog/plogotlp/response.go +++ b/pdata/plog/plogotlp/response.go @@ -8,18 +8,24 @@ import ( jsoniter "github.com/json-iterator/go" + "go.opentelemetry.io/collector/pdata/internal" otlpcollectorlog "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/logs/v1" "go.opentelemetry.io/collector/pdata/internal/json" ) // ExportResponse represents the response for gRPC/HTTP client/server. type ExportResponse struct { - orig *otlpcollectorlog.ExportLogsServiceResponse + orig *otlpcollectorlog.ExportLogsServiceResponse + state *internal.State } // NewExportResponse returns an empty ExportResponse. func NewExportResponse() ExportResponse { - return ExportResponse{orig: &otlpcollectorlog.ExportLogsServiceResponse{}} + state := internal.StateMutable + return ExportResponse{ + orig: &otlpcollectorlog.ExportLogsServiceResponse{}, + state: &state, + } } // MarshalProto marshals ExportResponse into proto bytes. @@ -51,7 +57,7 @@ func (ms ExportResponse) UnmarshalJSON(data []byte) error { // PartialSuccess returns the ExportPartialSuccess associated with this ExportResponse. func (ms ExportResponse) PartialSuccess() ExportPartialSuccess { - return newExportPartialSuccess(&ms.orig.PartialSuccess) + return newExportPartialSuccess(&ms.orig.PartialSuccess, ms.state) } func (ms ExportResponse) unmarshalJsoniter(iter *jsoniter.Iterator) { @@ -67,7 +73,7 @@ func (ms ExportResponse) unmarshalJsoniter(iter *jsoniter.Iterator) { } func (ms ExportPartialSuccess) unmarshalJsoniter(iter *jsoniter.Iterator) { - iter.ReadObjectCB(func(iterator *jsoniter.Iterator, f string) bool { + iter.ReadObjectCB(func(_ *jsoniter.Iterator, f string) bool { switch f { case "rejected_log_records", "rejectedLogRecords": ms.orig.RejectedLogRecords = json.ReadInt64(iter) diff --git a/pdata/pmetric/generated_exemplar.go b/pdata/pmetric/generated_exemplar.go index 461ddb21056..9937a1b500f 100644 --- a/pdata/pmetric/generated_exemplar.go +++ b/pdata/pmetric/generated_exemplar.go @@ -24,11 +24,12 @@ import ( // Must use NewExemplar function to create new instances. // Important: zero-initialized instance is not valid for use. type Exemplar struct { - orig *otlpmetrics.Exemplar + orig *otlpmetrics.Exemplar + state *internal.State } -func newExemplar(orig *otlpmetrics.Exemplar) Exemplar { - return Exemplar{orig} +func newExemplar(orig *otlpmetrics.Exemplar, state *internal.State) Exemplar { + return Exemplar{orig: orig, state: state} } // NewExemplar creates a new empty Exemplar. @@ -36,12 +37,15 @@ func newExemplar(orig *otlpmetrics.Exemplar) Exemplar { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewExemplar() Exemplar { - return newExemplar(&otlpmetrics.Exemplar{}) + state := internal.StateMutable + return newExemplar(&otlpmetrics.Exemplar{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms Exemplar) MoveTo(dest Exemplar) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.Exemplar{} } @@ -53,6 +57,7 @@ func (ms Exemplar) Timestamp() pcommon.Timestamp { // SetTimestamp replaces the timestamp associated with this Exemplar. func (ms Exemplar) SetTimestamp(v pcommon.Timestamp) { + ms.state.AssertMutable() ms.orig.TimeUnixNano = uint64(v) } @@ -75,6 +80,7 @@ func (ms Exemplar) DoubleValue() float64 { // SetDoubleValue replaces the double associated with this Exemplar. func (ms Exemplar) SetDoubleValue(v float64) { + ms.state.AssertMutable() ms.orig.Value = &otlpmetrics.Exemplar_AsDouble{ AsDouble: v, } @@ -87,6 +93,7 @@ func (ms Exemplar) IntValue() int64 { // SetIntValue replaces the int associated with this Exemplar. func (ms Exemplar) SetIntValue(v int64) { + ms.state.AssertMutable() ms.orig.Value = &otlpmetrics.Exemplar_AsInt{ AsInt: v, } @@ -94,7 +101,7 @@ func (ms Exemplar) SetIntValue(v int64) { // FilteredAttributes returns the FilteredAttributes associated with this Exemplar. func (ms Exemplar) FilteredAttributes() pcommon.Map { - return pcommon.Map(internal.NewMap(&ms.orig.FilteredAttributes)) + return pcommon.Map(internal.NewMap(&ms.orig.FilteredAttributes, ms.state)) } // TraceID returns the traceid associated with this Exemplar. @@ -104,6 +111,7 @@ func (ms Exemplar) TraceID() pcommon.TraceID { // SetTraceID replaces the traceid associated with this Exemplar. func (ms Exemplar) SetTraceID(v pcommon.TraceID) { + ms.state.AssertMutable() ms.orig.TraceId = data.TraceID(v) } @@ -114,11 +122,13 @@ func (ms Exemplar) SpanID() pcommon.SpanID { // SetSpanID replaces the spanid associated with this Exemplar. func (ms Exemplar) SetSpanID(v pcommon.SpanID) { + ms.state.AssertMutable() ms.orig.SpanId = data.SpanID(v) } // CopyTo copies all properties from the current struct overriding the destination. func (ms Exemplar) CopyTo(dest Exemplar) { + dest.state.AssertMutable() dest.SetTimestamp(ms.Timestamp()) switch ms.ValueType() { case ExemplarValueTypeDouble: diff --git a/pdata/pmetric/generated_exemplar_test.go b/pdata/pmetric/generated_exemplar_test.go index 5b9868a6752..b9f8ce27c81 100644 --- a/pdata/pmetric/generated_exemplar_test.go +++ b/pdata/pmetric/generated_exemplar_test.go @@ -23,6 +23,9 @@ func TestExemplar_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewExemplar(), ms) assert.Equal(t, generateTestExemplar(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newExemplar(&otlpmetrics.Exemplar{}, &sharedState)) }) + assert.Panics(t, func() { newExemplar(&otlpmetrics.Exemplar{}, &sharedState).MoveTo(dest) }) } func TestExemplar_CopyTo(t *testing.T) { @@ -33,6 +36,8 @@ func TestExemplar_CopyTo(t *testing.T) { orig = generateTestExemplar() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newExemplar(&otlpmetrics.Exemplar{}, &sharedState)) }) } func TestExemplar_Timestamp(t *testing.T) { @@ -54,6 +59,8 @@ func TestExemplar_DoubleValue(t *testing.T) { ms.SetDoubleValue(float64(17.13)) assert.Equal(t, float64(17.13), ms.DoubleValue()) assert.Equal(t, ExemplarValueTypeDouble, ms.ValueType()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newExemplar(&otlpmetrics.Exemplar{}, &sharedState).SetDoubleValue(float64(17.13)) }) } func TestExemplar_IntValue(t *testing.T) { @@ -62,6 +69,8 @@ func TestExemplar_IntValue(t *testing.T) { ms.SetIntValue(int64(17)) assert.Equal(t, int64(17), ms.IntValue()) assert.Equal(t, ExemplarValueTypeInt, ms.ValueType()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newExemplar(&otlpmetrics.Exemplar{}, &sharedState).SetIntValue(int64(17)) }) } func TestExemplar_FilteredAttributes(t *testing.T) { @@ -96,7 +105,7 @@ func generateTestExemplar() Exemplar { func fillTestExemplar(tv Exemplar) { tv.orig.TimeUnixNano = 1234567890 tv.orig.Value = &otlpmetrics.Exemplar_AsInt{AsInt: int64(17)} - internal.FillTestMap(internal.NewMap(&tv.orig.FilteredAttributes)) + internal.FillTestMap(internal.NewMap(&tv.orig.FilteredAttributes, tv.state)) tv.orig.TraceId = data.TraceID([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1}) tv.orig.SpanId = data.SpanID([8]byte{8, 7, 6, 5, 4, 3, 2, 1}) } diff --git a/pdata/pmetric/generated_exemplarslice.go b/pdata/pmetric/generated_exemplarslice.go index f39db94477b..15d70a6edeb 100644 --- a/pdata/pmetric/generated_exemplarslice.go +++ b/pdata/pmetric/generated_exemplarslice.go @@ -7,6 +7,7 @@ package pmetric import ( + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -18,18 +19,20 @@ import ( // Must use NewExemplarSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type ExemplarSlice struct { - orig *[]otlpmetrics.Exemplar + orig *[]otlpmetrics.Exemplar + state *internal.State } -func newExemplarSlice(orig *[]otlpmetrics.Exemplar) ExemplarSlice { - return ExemplarSlice{orig} +func newExemplarSlice(orig *[]otlpmetrics.Exemplar, state *internal.State) ExemplarSlice { + return ExemplarSlice{orig: orig, state: state} } // NewExemplarSlice creates a ExemplarSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewExemplarSlice() ExemplarSlice { orig := []otlpmetrics.Exemplar(nil) - return newExemplarSlice(&orig) + state := internal.StateMutable + return newExemplarSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -48,7 +51,7 @@ func (es ExemplarSlice) Len() int { // ... // Do something with the element // } func (es ExemplarSlice) At(i int) Exemplar { - return newExemplar(&(*es.orig)[i]) + return newExemplar(&(*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -64,6 +67,7 @@ func (es ExemplarSlice) At(i int) Exemplar { // // Here should set all the values for e. // } func (es ExemplarSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -77,6 +81,7 @@ func (es ExemplarSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty Exemplar. // It returns the newly added Exemplar. func (es ExemplarSlice) AppendEmpty() Exemplar { + es.state.AssertMutable() *es.orig = append(*es.orig, otlpmetrics.Exemplar{}) return es.At(es.Len() - 1) } @@ -84,6 +89,8 @@ func (es ExemplarSlice) AppendEmpty() Exemplar { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es ExemplarSlice) MoveAndAppendTo(dest ExemplarSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -96,6 +103,7 @@ func (es ExemplarSlice) MoveAndAppendTo(dest ExemplarSlice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es ExemplarSlice) RemoveIf(f func(Exemplar) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -109,12 +117,12 @@ func (es ExemplarSlice) RemoveIf(f func(Exemplar) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es ExemplarSlice) CopyTo(dest ExemplarSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { @@ -123,6 +131,6 @@ func (es ExemplarSlice) CopyTo(dest ExemplarSlice) { (*dest.orig) = make([]otlpmetrics.Exemplar, srcLen) } for i := range *es.orig { - newExemplar(&(*es.orig)[i]).CopyTo(newExemplar(&(*dest.orig)[i])) + newExemplar(&(*es.orig)[i], es.state).CopyTo(newExemplar(&(*dest.orig)[i], dest.state)) } } diff --git a/pdata/pmetric/generated_exemplarslice_test.go b/pdata/pmetric/generated_exemplarslice_test.go index 3eb96c12b80..7cda639f638 100644 --- a/pdata/pmetric/generated_exemplarslice_test.go +++ b/pdata/pmetric/generated_exemplarslice_test.go @@ -11,13 +11,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) func TestExemplarSlice(t *testing.T) { es := NewExemplarSlice() assert.Equal(t, 0, es.Len()) - es = newExemplarSlice(&[]otlpmetrics.Exemplar{}) + state := internal.StateMutable + es = newExemplarSlice(&[]otlpmetrics.Exemplar{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewExemplar() @@ -31,6 +33,19 @@ func TestExemplarSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestExemplarSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newExemplarSlice(&[]otlpmetrics.Exemplar{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewExemplarSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestExemplarSlice_CopyTo(t *testing.T) { dest := NewExemplarSlice() // Test CopyTo to empty @@ -117,6 +132,6 @@ func fillTestExemplarSlice(es ExemplarSlice) { *es.orig = make([]otlpmetrics.Exemplar, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = otlpmetrics.Exemplar{} - fillTestExemplar(newExemplar(&(*es.orig)[i])) + fillTestExemplar(newExemplar(&(*es.orig)[i], es.state)) } } diff --git a/pdata/pmetric/generated_exponentialhistogram.go b/pdata/pmetric/generated_exponentialhistogram.go index 5fd275b9554..18ba20d7377 100644 --- a/pdata/pmetric/generated_exponentialhistogram.go +++ b/pdata/pmetric/generated_exponentialhistogram.go @@ -7,6 +7,7 @@ package pmetric import ( + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -19,11 +20,12 @@ import ( // Must use NewExponentialHistogram function to create new instances. // Important: zero-initialized instance is not valid for use. type ExponentialHistogram struct { - orig *otlpmetrics.ExponentialHistogram + orig *otlpmetrics.ExponentialHistogram + state *internal.State } -func newExponentialHistogram(orig *otlpmetrics.ExponentialHistogram) ExponentialHistogram { - return ExponentialHistogram{orig} +func newExponentialHistogram(orig *otlpmetrics.ExponentialHistogram, state *internal.State) ExponentialHistogram { + return ExponentialHistogram{orig: orig, state: state} } // NewExponentialHistogram creates a new empty ExponentialHistogram. @@ -31,12 +33,15 @@ func newExponentialHistogram(orig *otlpmetrics.ExponentialHistogram) Exponential // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewExponentialHistogram() ExponentialHistogram { - return newExponentialHistogram(&otlpmetrics.ExponentialHistogram{}) + state := internal.StateMutable + return newExponentialHistogram(&otlpmetrics.ExponentialHistogram{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms ExponentialHistogram) MoveTo(dest ExponentialHistogram) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.ExponentialHistogram{} } @@ -48,16 +53,18 @@ func (ms ExponentialHistogram) AggregationTemporality() AggregationTemporality { // SetAggregationTemporality replaces the aggregationtemporality associated with this ExponentialHistogram. func (ms ExponentialHistogram) SetAggregationTemporality(v AggregationTemporality) { + ms.state.AssertMutable() ms.orig.AggregationTemporality = otlpmetrics.AggregationTemporality(v) } // DataPoints returns the DataPoints associated with this ExponentialHistogram. func (ms ExponentialHistogram) DataPoints() ExponentialHistogramDataPointSlice { - return newExponentialHistogramDataPointSlice(&ms.orig.DataPoints) + return newExponentialHistogramDataPointSlice(&ms.orig.DataPoints, ms.state) } // CopyTo copies all properties from the current struct overriding the destination. func (ms ExponentialHistogram) CopyTo(dest ExponentialHistogram) { + dest.state.AssertMutable() dest.SetAggregationTemporality(ms.AggregationTemporality()) ms.DataPoints().CopyTo(dest.DataPoints()) } diff --git a/pdata/pmetric/generated_exponentialhistogram_test.go b/pdata/pmetric/generated_exponentialhistogram_test.go index 543e53626cb..cc46edbb536 100644 --- a/pdata/pmetric/generated_exponentialhistogram_test.go +++ b/pdata/pmetric/generated_exponentialhistogram_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -20,6 +21,9 @@ func TestExponentialHistogram_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewExponentialHistogram(), ms) assert.Equal(t, generateTestExponentialHistogram(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newExponentialHistogram(&otlpmetrics.ExponentialHistogram{}, &sharedState)) }) + assert.Panics(t, func() { newExponentialHistogram(&otlpmetrics.ExponentialHistogram{}, &sharedState).MoveTo(dest) }) } func TestExponentialHistogram_CopyTo(t *testing.T) { @@ -30,6 +34,8 @@ func TestExponentialHistogram_CopyTo(t *testing.T) { orig = generateTestExponentialHistogram() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newExponentialHistogram(&otlpmetrics.ExponentialHistogram{}, &sharedState)) }) } func TestExponentialHistogram_AggregationTemporality(t *testing.T) { @@ -55,5 +61,5 @@ func generateTestExponentialHistogram() ExponentialHistogram { func fillTestExponentialHistogram(tv ExponentialHistogram) { tv.orig.AggregationTemporality = otlpmetrics.AggregationTemporality(1) - fillTestExponentialHistogramDataPointSlice(newExponentialHistogramDataPointSlice(&tv.orig.DataPoints)) + fillTestExponentialHistogramDataPointSlice(newExponentialHistogramDataPointSlice(&tv.orig.DataPoints, tv.state)) } diff --git a/pdata/pmetric/generated_exponentialhistogramdatapoint.go b/pdata/pmetric/generated_exponentialhistogramdatapoint.go index fcde3a18f30..3d76368b384 100644 --- a/pdata/pmetric/generated_exponentialhistogramdatapoint.go +++ b/pdata/pmetric/generated_exponentialhistogramdatapoint.go @@ -23,11 +23,12 @@ import ( // Must use NewExponentialHistogramDataPoint function to create new instances. // Important: zero-initialized instance is not valid for use. type ExponentialHistogramDataPoint struct { - orig *otlpmetrics.ExponentialHistogramDataPoint + orig *otlpmetrics.ExponentialHistogramDataPoint + state *internal.State } -func newExponentialHistogramDataPoint(orig *otlpmetrics.ExponentialHistogramDataPoint) ExponentialHistogramDataPoint { - return ExponentialHistogramDataPoint{orig} +func newExponentialHistogramDataPoint(orig *otlpmetrics.ExponentialHistogramDataPoint, state *internal.State) ExponentialHistogramDataPoint { + return ExponentialHistogramDataPoint{orig: orig, state: state} } // NewExponentialHistogramDataPoint creates a new empty ExponentialHistogramDataPoint. @@ -35,19 +36,22 @@ func newExponentialHistogramDataPoint(orig *otlpmetrics.ExponentialHistogramData // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewExponentialHistogramDataPoint() ExponentialHistogramDataPoint { - return newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}) + state := internal.StateMutable + return newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms ExponentialHistogramDataPoint) MoveTo(dest ExponentialHistogramDataPoint) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.ExponentialHistogramDataPoint{} } // Attributes returns the Attributes associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) Attributes() pcommon.Map { - return pcommon.Map(internal.NewMap(&ms.orig.Attributes)) + return pcommon.Map(internal.NewMap(&ms.orig.Attributes, ms.state)) } // StartTimestamp returns the starttimestamp associated with this ExponentialHistogramDataPoint. @@ -57,6 +61,7 @@ func (ms ExponentialHistogramDataPoint) StartTimestamp() pcommon.Timestamp { // SetStartTimestamp replaces the starttimestamp associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) SetStartTimestamp(v pcommon.Timestamp) { + ms.state.AssertMutable() ms.orig.StartTimeUnixNano = uint64(v) } @@ -67,6 +72,7 @@ func (ms ExponentialHistogramDataPoint) Timestamp() pcommon.Timestamp { // SetTimestamp replaces the timestamp associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) SetTimestamp(v pcommon.Timestamp) { + ms.state.AssertMutable() ms.orig.TimeUnixNano = uint64(v) } @@ -77,30 +83,10 @@ func (ms ExponentialHistogramDataPoint) Count() uint64 { // SetCount replaces the count associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) SetCount(v uint64) { + ms.state.AssertMutable() ms.orig.Count = v } -// Sum returns the sum associated with this ExponentialHistogramDataPoint. -func (ms ExponentialHistogramDataPoint) Sum() float64 { - return ms.orig.GetSum() -} - -// HasSum returns true if the ExponentialHistogramDataPoint contains a -// Sum value, false otherwise. -func (ms ExponentialHistogramDataPoint) HasSum() bool { - return ms.orig.Sum_ != nil -} - -// SetSum replaces the sum associated with this ExponentialHistogramDataPoint. -func (ms ExponentialHistogramDataPoint) SetSum(v float64) { - ms.orig.Sum_ = &otlpmetrics.ExponentialHistogramDataPoint_Sum{Sum: v} -} - -// RemoveSum removes the sum associated with this ExponentialHistogramDataPoint. -func (ms ExponentialHistogramDataPoint) RemoveSum() { - ms.orig.Sum_ = nil -} - // Scale returns the scale associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) Scale() int32 { return ms.orig.Scale @@ -108,6 +94,7 @@ func (ms ExponentialHistogramDataPoint) Scale() int32 { // SetScale replaces the scale associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) SetScale(v int32) { + ms.state.AssertMutable() ms.orig.Scale = v } @@ -118,22 +105,23 @@ func (ms ExponentialHistogramDataPoint) ZeroCount() uint64 { // SetZeroCount replaces the zerocount associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) SetZeroCount(v uint64) { + ms.state.AssertMutable() ms.orig.ZeroCount = v } // Positive returns the positive associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) Positive() ExponentialHistogramDataPointBuckets { - return newExponentialHistogramDataPointBuckets(&ms.orig.Positive) + return newExponentialHistogramDataPointBuckets(&ms.orig.Positive, ms.state) } // Negative returns the negative associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) Negative() ExponentialHistogramDataPointBuckets { - return newExponentialHistogramDataPointBuckets(&ms.orig.Negative) + return newExponentialHistogramDataPointBuckets(&ms.orig.Negative, ms.state) } // Exemplars returns the Exemplars associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) Exemplars() ExemplarSlice { - return newExemplarSlice(&ms.orig.Exemplars) + return newExemplarSlice(&ms.orig.Exemplars, ms.state) } // Flags returns the flags associated with this ExponentialHistogramDataPoint. @@ -143,9 +131,33 @@ func (ms ExponentialHistogramDataPoint) Flags() DataPointFlags { // SetFlags replaces the flags associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) SetFlags(v DataPointFlags) { + ms.state.AssertMutable() ms.orig.Flags = uint32(v) } +// Sum returns the sum associated with this ExponentialHistogramDataPoint. +func (ms ExponentialHistogramDataPoint) Sum() float64 { + return ms.orig.GetSum() +} + +// HasSum returns true if the ExponentialHistogramDataPoint contains a +// Sum value, false otherwise. +func (ms ExponentialHistogramDataPoint) HasSum() bool { + return ms.orig.Sum_ != nil +} + +// SetSum replaces the sum associated with this ExponentialHistogramDataPoint. +func (ms ExponentialHistogramDataPoint) SetSum(v float64) { + ms.state.AssertMutable() + ms.orig.Sum_ = &otlpmetrics.ExponentialHistogramDataPoint_Sum{Sum: v} +} + +// RemoveSum removes the sum associated with this ExponentialHistogramDataPoint. +func (ms ExponentialHistogramDataPoint) RemoveSum() { + ms.state.AssertMutable() + ms.orig.Sum_ = nil +} + // Min returns the min associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) Min() float64 { return ms.orig.GetMin() @@ -159,11 +171,13 @@ func (ms ExponentialHistogramDataPoint) HasMin() bool { // SetMin replaces the min associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) SetMin(v float64) { + ms.state.AssertMutable() ms.orig.Min_ = &otlpmetrics.ExponentialHistogramDataPoint_Min{Min: v} } // RemoveMin removes the min associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) RemoveMin() { + ms.state.AssertMutable() ms.orig.Min_ = nil } @@ -180,30 +194,44 @@ func (ms ExponentialHistogramDataPoint) HasMax() bool { // SetMax replaces the max associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) SetMax(v float64) { + ms.state.AssertMutable() ms.orig.Max_ = &otlpmetrics.ExponentialHistogramDataPoint_Max{Max: v} } // RemoveMax removes the max associated with this ExponentialHistogramDataPoint. func (ms ExponentialHistogramDataPoint) RemoveMax() { + ms.state.AssertMutable() ms.orig.Max_ = nil } +// ZeroThreshold returns the zerothreshold associated with this ExponentialHistogramDataPoint. +func (ms ExponentialHistogramDataPoint) ZeroThreshold() float64 { + return ms.orig.ZeroThreshold +} + +// SetZeroThreshold replaces the zerothreshold associated with this ExponentialHistogramDataPoint. +func (ms ExponentialHistogramDataPoint) SetZeroThreshold(v float64) { + ms.state.AssertMutable() + ms.orig.ZeroThreshold = v +} + // CopyTo copies all properties from the current struct overriding the destination. func (ms ExponentialHistogramDataPoint) CopyTo(dest ExponentialHistogramDataPoint) { + dest.state.AssertMutable() ms.Attributes().CopyTo(dest.Attributes()) dest.SetStartTimestamp(ms.StartTimestamp()) dest.SetTimestamp(ms.Timestamp()) dest.SetCount(ms.Count()) - if ms.HasSum() { - dest.SetSum(ms.Sum()) - } - dest.SetScale(ms.Scale()) dest.SetZeroCount(ms.ZeroCount()) ms.Positive().CopyTo(dest.Positive()) ms.Negative().CopyTo(dest.Negative()) ms.Exemplars().CopyTo(dest.Exemplars()) dest.SetFlags(ms.Flags()) + if ms.HasSum() { + dest.SetSum(ms.Sum()) + } + if ms.HasMin() { dest.SetMin(ms.Min()) } @@ -212,4 +240,5 @@ func (ms ExponentialHistogramDataPoint) CopyTo(dest ExponentialHistogramDataPoin dest.SetMax(ms.Max()) } + dest.SetZeroThreshold(ms.ZeroThreshold()) } diff --git a/pdata/pmetric/generated_exponentialhistogramdatapoint_test.go b/pdata/pmetric/generated_exponentialhistogramdatapoint_test.go index 9192b0f339b..f4347f2e47f 100644 --- a/pdata/pmetric/generated_exponentialhistogramdatapoint_test.go +++ b/pdata/pmetric/generated_exponentialhistogramdatapoint_test.go @@ -22,6 +22,13 @@ func TestExponentialHistogramDataPoint_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewExponentialHistogramDataPoint(), ms) assert.Equal(t, generateTestExponentialHistogramDataPoint(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + ms.MoveTo(newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState)) + }) + assert.Panics(t, func() { + newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState).MoveTo(dest) + }) } func TestExponentialHistogramDataPoint_CopyTo(t *testing.T) { @@ -32,6 +39,10 @@ func TestExponentialHistogramDataPoint_CopyTo(t *testing.T) { orig = generateTestExponentialHistogramDataPoint() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + ms.CopyTo(newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState)) + }) } func TestExponentialHistogramDataPoint_Attributes(t *testing.T) { @@ -62,16 +73,10 @@ func TestExponentialHistogramDataPoint_Count(t *testing.T) { assert.Equal(t, uint64(0), ms.Count()) ms.SetCount(uint64(17)) assert.Equal(t, uint64(17), ms.Count()) -} - -func TestExponentialHistogramDataPoint_Sum(t *testing.T) { - ms := NewExponentialHistogramDataPoint() - assert.Equal(t, float64(0.0), ms.Sum()) - ms.SetSum(float64(17.13)) - assert.True(t, ms.HasSum()) - assert.Equal(t, float64(17.13), ms.Sum()) - ms.RemoveSum() - assert.False(t, ms.HasSum()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState).SetCount(uint64(17)) + }) } func TestExponentialHistogramDataPoint_Scale(t *testing.T) { @@ -79,6 +84,10 @@ func TestExponentialHistogramDataPoint_Scale(t *testing.T) { assert.Equal(t, int32(0), ms.Scale()) ms.SetScale(int32(4)) assert.Equal(t, int32(4), ms.Scale()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState).SetScale(int32(4)) + }) } func TestExponentialHistogramDataPoint_ZeroCount(t *testing.T) { @@ -86,6 +95,10 @@ func TestExponentialHistogramDataPoint_ZeroCount(t *testing.T) { assert.Equal(t, uint64(0), ms.ZeroCount()) ms.SetZeroCount(uint64(201)) assert.Equal(t, uint64(201), ms.ZeroCount()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState).SetZeroCount(uint64(201)) + }) } func TestExponentialHistogramDataPoint_Positive(t *testing.T) { @@ -115,6 +128,16 @@ func TestExponentialHistogramDataPoint_Flags(t *testing.T) { assert.Equal(t, testValFlags, ms.Flags()) } +func TestExponentialHistogramDataPoint_Sum(t *testing.T) { + ms := NewExponentialHistogramDataPoint() + assert.Equal(t, float64(0.0), ms.Sum()) + ms.SetSum(float64(17.13)) + assert.True(t, ms.HasSum()) + assert.Equal(t, float64(17.13), ms.Sum()) + ms.RemoveSum() + assert.False(t, ms.HasSum()) +} + func TestExponentialHistogramDataPoint_Min(t *testing.T) { ms := NewExponentialHistogramDataPoint() assert.Equal(t, float64(0.0), ms.Min()) @@ -135,6 +158,17 @@ func TestExponentialHistogramDataPoint_Max(t *testing.T) { assert.False(t, ms.HasMax()) } +func TestExponentialHistogramDataPoint_ZeroThreshold(t *testing.T) { + ms := NewExponentialHistogramDataPoint() + assert.Equal(t, float64(0.0), ms.ZeroThreshold()) + ms.SetZeroThreshold(float64(0.5)) + assert.Equal(t, float64(0.5), ms.ZeroThreshold()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState).SetZeroThreshold(float64(0.5)) + }) +} + func generateTestExponentialHistogramDataPoint() ExponentialHistogramDataPoint { tv := NewExponentialHistogramDataPoint() fillTestExponentialHistogramDataPoint(tv) @@ -142,17 +176,18 @@ func generateTestExponentialHistogramDataPoint() ExponentialHistogramDataPoint { } func fillTestExponentialHistogramDataPoint(tv ExponentialHistogramDataPoint) { - internal.FillTestMap(internal.NewMap(&tv.orig.Attributes)) + internal.FillTestMap(internal.NewMap(&tv.orig.Attributes, tv.state)) tv.orig.StartTimeUnixNano = 1234567890 tv.orig.TimeUnixNano = 1234567890 tv.orig.Count = uint64(17) - tv.orig.Sum_ = &otlpmetrics.ExponentialHistogramDataPoint_Sum{Sum: float64(17.13)} tv.orig.Scale = int32(4) tv.orig.ZeroCount = uint64(201) - fillTestExponentialHistogramDataPointBuckets(newExponentialHistogramDataPointBuckets(&tv.orig.Positive)) - fillTestExponentialHistogramDataPointBuckets(newExponentialHistogramDataPointBuckets(&tv.orig.Negative)) - fillTestExemplarSlice(newExemplarSlice(&tv.orig.Exemplars)) + fillTestExponentialHistogramDataPointBuckets(newExponentialHistogramDataPointBuckets(&tv.orig.Positive, tv.state)) + fillTestExponentialHistogramDataPointBuckets(newExponentialHistogramDataPointBuckets(&tv.orig.Negative, tv.state)) + fillTestExemplarSlice(newExemplarSlice(&tv.orig.Exemplars, tv.state)) tv.orig.Flags = 1 + tv.orig.Sum_ = &otlpmetrics.ExponentialHistogramDataPoint_Sum{Sum: float64(17.13)} tv.orig.Min_ = &otlpmetrics.ExponentialHistogramDataPoint_Min{Min: float64(9.23)} tv.orig.Max_ = &otlpmetrics.ExponentialHistogramDataPoint_Max{Max: float64(182.55)} + tv.orig.ZeroThreshold = float64(0.5) } diff --git a/pdata/pmetric/generated_exponentialhistogramdatapointbuckets.go b/pdata/pmetric/generated_exponentialhistogramdatapointbuckets.go index c0e1532909a..7acfbc627f3 100644 --- a/pdata/pmetric/generated_exponentialhistogramdatapointbuckets.go +++ b/pdata/pmetric/generated_exponentialhistogramdatapointbuckets.go @@ -20,11 +20,12 @@ import ( // Must use NewExponentialHistogramDataPointBuckets function to create new instances. // Important: zero-initialized instance is not valid for use. type ExponentialHistogramDataPointBuckets struct { - orig *otlpmetrics.ExponentialHistogramDataPoint_Buckets + orig *otlpmetrics.ExponentialHistogramDataPoint_Buckets + state *internal.State } -func newExponentialHistogramDataPointBuckets(orig *otlpmetrics.ExponentialHistogramDataPoint_Buckets) ExponentialHistogramDataPointBuckets { - return ExponentialHistogramDataPointBuckets{orig} +func newExponentialHistogramDataPointBuckets(orig *otlpmetrics.ExponentialHistogramDataPoint_Buckets, state *internal.State) ExponentialHistogramDataPointBuckets { + return ExponentialHistogramDataPointBuckets{orig: orig, state: state} } // NewExponentialHistogramDataPointBuckets creates a new empty ExponentialHistogramDataPointBuckets. @@ -32,12 +33,15 @@ func newExponentialHistogramDataPointBuckets(orig *otlpmetrics.ExponentialHistog // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewExponentialHistogramDataPointBuckets() ExponentialHistogramDataPointBuckets { - return newExponentialHistogramDataPointBuckets(&otlpmetrics.ExponentialHistogramDataPoint_Buckets{}) + state := internal.StateMutable + return newExponentialHistogramDataPointBuckets(&otlpmetrics.ExponentialHistogramDataPoint_Buckets{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms ExponentialHistogramDataPointBuckets) MoveTo(dest ExponentialHistogramDataPointBuckets) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.ExponentialHistogramDataPoint_Buckets{} } @@ -49,16 +53,18 @@ func (ms ExponentialHistogramDataPointBuckets) Offset() int32 { // SetOffset replaces the offset associated with this ExponentialHistogramDataPointBuckets. func (ms ExponentialHistogramDataPointBuckets) SetOffset(v int32) { + ms.state.AssertMutable() ms.orig.Offset = v } // BucketCounts returns the bucketcounts associated with this ExponentialHistogramDataPointBuckets. func (ms ExponentialHistogramDataPointBuckets) BucketCounts() pcommon.UInt64Slice { - return pcommon.UInt64Slice(internal.NewUInt64Slice(&ms.orig.BucketCounts)) + return pcommon.UInt64Slice(internal.NewUInt64Slice(&ms.orig.BucketCounts, ms.state)) } // CopyTo copies all properties from the current struct overriding the destination. func (ms ExponentialHistogramDataPointBuckets) CopyTo(dest ExponentialHistogramDataPointBuckets) { + dest.state.AssertMutable() dest.SetOffset(ms.Offset()) ms.BucketCounts().CopyTo(dest.BucketCounts()) } diff --git a/pdata/pmetric/generated_exponentialhistogramdatapointbuckets_test.go b/pdata/pmetric/generated_exponentialhistogramdatapointbuckets_test.go index c1119861dbd..faf6e529f33 100644 --- a/pdata/pmetric/generated_exponentialhistogramdatapointbuckets_test.go +++ b/pdata/pmetric/generated_exponentialhistogramdatapointbuckets_test.go @@ -10,6 +10,9 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/pdata/internal" + otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) func TestExponentialHistogramDataPointBuckets_MoveTo(t *testing.T) { @@ -18,6 +21,13 @@ func TestExponentialHistogramDataPointBuckets_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewExponentialHistogramDataPointBuckets(), ms) assert.Equal(t, generateTestExponentialHistogramDataPointBuckets(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + ms.MoveTo(newExponentialHistogramDataPointBuckets(&otlpmetrics.ExponentialHistogramDataPoint_Buckets{}, &sharedState)) + }) + assert.Panics(t, func() { + newExponentialHistogramDataPointBuckets(&otlpmetrics.ExponentialHistogramDataPoint_Buckets{}, &sharedState).MoveTo(dest) + }) } func TestExponentialHistogramDataPointBuckets_CopyTo(t *testing.T) { @@ -28,6 +38,10 @@ func TestExponentialHistogramDataPointBuckets_CopyTo(t *testing.T) { orig = generateTestExponentialHistogramDataPointBuckets() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + ms.CopyTo(newExponentialHistogramDataPointBuckets(&otlpmetrics.ExponentialHistogramDataPoint_Buckets{}, &sharedState)) + }) } func TestExponentialHistogramDataPointBuckets_Offset(t *testing.T) { @@ -35,6 +49,10 @@ func TestExponentialHistogramDataPointBuckets_Offset(t *testing.T) { assert.Equal(t, int32(0), ms.Offset()) ms.SetOffset(int32(909)) assert.Equal(t, int32(909), ms.Offset()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newExponentialHistogramDataPointBuckets(&otlpmetrics.ExponentialHistogramDataPoint_Buckets{}, &sharedState).SetOffset(int32(909)) + }) } func TestExponentialHistogramDataPointBuckets_BucketCounts(t *testing.T) { diff --git a/pdata/pmetric/generated_exponentialhistogramdatapointslice.go b/pdata/pmetric/generated_exponentialhistogramdatapointslice.go index f2141d1e5c8..a466a7c185b 100644 --- a/pdata/pmetric/generated_exponentialhistogramdatapointslice.go +++ b/pdata/pmetric/generated_exponentialhistogramdatapointslice.go @@ -9,6 +9,7 @@ package pmetric import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewExponentialHistogramDataPointSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type ExponentialHistogramDataPointSlice struct { - orig *[]*otlpmetrics.ExponentialHistogramDataPoint + orig *[]*otlpmetrics.ExponentialHistogramDataPoint + state *internal.State } -func newExponentialHistogramDataPointSlice(orig *[]*otlpmetrics.ExponentialHistogramDataPoint) ExponentialHistogramDataPointSlice { - return ExponentialHistogramDataPointSlice{orig} +func newExponentialHistogramDataPointSlice(orig *[]*otlpmetrics.ExponentialHistogramDataPoint, state *internal.State) ExponentialHistogramDataPointSlice { + return ExponentialHistogramDataPointSlice{orig: orig, state: state} } // NewExponentialHistogramDataPointSlice creates a ExponentialHistogramDataPointSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewExponentialHistogramDataPointSlice() ExponentialHistogramDataPointSlice { orig := []*otlpmetrics.ExponentialHistogramDataPoint(nil) - return newExponentialHistogramDataPointSlice(&orig) + state := internal.StateMutable + return newExponentialHistogramDataPointSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es ExponentialHistogramDataPointSlice) Len() int { // ... // Do something with the element // } func (es ExponentialHistogramDataPointSlice) At(i int) ExponentialHistogramDataPoint { - return newExponentialHistogramDataPoint((*es.orig)[i]) + return newExponentialHistogramDataPoint((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es ExponentialHistogramDataPointSlice) At(i int) ExponentialHistogramDataP // // Here should set all the values for e. // } func (es ExponentialHistogramDataPointSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es ExponentialHistogramDataPointSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty ExponentialHistogramDataPoint. // It returns the newly added ExponentialHistogramDataPoint. func (es ExponentialHistogramDataPointSlice) AppendEmpty() ExponentialHistogramDataPoint { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlpmetrics.ExponentialHistogramDataPoint{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es ExponentialHistogramDataPointSlice) AppendEmpty() ExponentialHistogramD // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es ExponentialHistogramDataPointSlice) MoveAndAppendTo(dest ExponentialHistogramDataPointSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es ExponentialHistogramDataPointSlice) MoveAndAppendTo(dest ExponentialHis // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es ExponentialHistogramDataPointSlice) RemoveIf(f func(ExponentialHistogramDataPoint) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es ExponentialHistogramDataPointSlice) RemoveIf(f func(ExponentialHistogra (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es ExponentialHistogramDataPointSlice) CopyTo(dest ExponentialHistogramDataPointSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newExponentialHistogramDataPoint((*es.orig)[i]).CopyTo(newExponentialHistogramDataPoint((*dest.orig)[i])) + newExponentialHistogramDataPoint((*es.orig)[i], es.state).CopyTo(newExponentialHistogramDataPoint((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es ExponentialHistogramDataPointSlice) CopyTo(dest ExponentialHistogramDat wrappers := make([]*otlpmetrics.ExponentialHistogramDataPoint, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newExponentialHistogramDataPoint((*es.orig)[i]).CopyTo(newExponentialHistogramDataPoint(wrappers[i])) + newExponentialHistogramDataPoint((*es.orig)[i], es.state).CopyTo(newExponentialHistogramDataPoint(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es ExponentialHistogramDataPointSlice) CopyTo(dest ExponentialHistogramDat // provided less function so that two instances of ExponentialHistogramDataPointSlice // can be compared. func (es ExponentialHistogramDataPointSlice) Sort(less func(a, b ExponentialHistogramDataPoint) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/pmetric/generated_exponentialhistogramdatapointslice_test.go b/pdata/pmetric/generated_exponentialhistogramdatapointslice_test.go index 6fd8a3f6de0..7c938c6ee22 100644 --- a/pdata/pmetric/generated_exponentialhistogramdatapointslice_test.go +++ b/pdata/pmetric/generated_exponentialhistogramdatapointslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) func TestExponentialHistogramDataPointSlice(t *testing.T) { es := NewExponentialHistogramDataPointSlice() assert.Equal(t, 0, es.Len()) - es = newExponentialHistogramDataPointSlice(&[]*otlpmetrics.ExponentialHistogramDataPoint{}) + state := internal.StateMutable + es = newExponentialHistogramDataPointSlice(&[]*otlpmetrics.ExponentialHistogramDataPoint{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewExponentialHistogramDataPoint() @@ -32,6 +34,19 @@ func TestExponentialHistogramDataPointSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestExponentialHistogramDataPointSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newExponentialHistogramDataPointSlice(&[]*otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewExponentialHistogramDataPointSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestExponentialHistogramDataPointSlice_CopyTo(t *testing.T) { dest := NewExponentialHistogramDataPointSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestExponentialHistogramDataPointSlice(es ExponentialHistogramDataPoint *es.orig = make([]*otlpmetrics.ExponentialHistogramDataPoint, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlpmetrics.ExponentialHistogramDataPoint{} - fillTestExponentialHistogramDataPoint(newExponentialHistogramDataPoint((*es.orig)[i])) + fillTestExponentialHistogramDataPoint(newExponentialHistogramDataPoint((*es.orig)[i], es.state)) } } diff --git a/pdata/pmetric/generated_gauge.go b/pdata/pmetric/generated_gauge.go index 6c74325b6de..ba572f9ca57 100644 --- a/pdata/pmetric/generated_gauge.go +++ b/pdata/pmetric/generated_gauge.go @@ -7,6 +7,7 @@ package pmetric import ( + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -18,11 +19,12 @@ import ( // Must use NewGauge function to create new instances. // Important: zero-initialized instance is not valid for use. type Gauge struct { - orig *otlpmetrics.Gauge + orig *otlpmetrics.Gauge + state *internal.State } -func newGauge(orig *otlpmetrics.Gauge) Gauge { - return Gauge{orig} +func newGauge(orig *otlpmetrics.Gauge, state *internal.State) Gauge { + return Gauge{orig: orig, state: state} } // NewGauge creates a new empty Gauge. @@ -30,22 +32,26 @@ func newGauge(orig *otlpmetrics.Gauge) Gauge { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewGauge() Gauge { - return newGauge(&otlpmetrics.Gauge{}) + state := internal.StateMutable + return newGauge(&otlpmetrics.Gauge{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms Gauge) MoveTo(dest Gauge) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.Gauge{} } // DataPoints returns the DataPoints associated with this Gauge. func (ms Gauge) DataPoints() NumberDataPointSlice { - return newNumberDataPointSlice(&ms.orig.DataPoints) + return newNumberDataPointSlice(&ms.orig.DataPoints, ms.state) } // CopyTo copies all properties from the current struct overriding the destination. func (ms Gauge) CopyTo(dest Gauge) { + dest.state.AssertMutable() ms.DataPoints().CopyTo(dest.DataPoints()) } diff --git a/pdata/pmetric/generated_gauge_test.go b/pdata/pmetric/generated_gauge_test.go index 30b517cd05b..e1506be119b 100644 --- a/pdata/pmetric/generated_gauge_test.go +++ b/pdata/pmetric/generated_gauge_test.go @@ -10,6 +10,9 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/pdata/internal" + otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) func TestGauge_MoveTo(t *testing.T) { @@ -18,6 +21,9 @@ func TestGauge_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewGauge(), ms) assert.Equal(t, generateTestGauge(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newGauge(&otlpmetrics.Gauge{}, &sharedState)) }) + assert.Panics(t, func() { newGauge(&otlpmetrics.Gauge{}, &sharedState).MoveTo(dest) }) } func TestGauge_CopyTo(t *testing.T) { @@ -28,6 +34,8 @@ func TestGauge_CopyTo(t *testing.T) { orig = generateTestGauge() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newGauge(&otlpmetrics.Gauge{}, &sharedState)) }) } func TestGauge_DataPoints(t *testing.T) { @@ -44,5 +52,5 @@ func generateTestGauge() Gauge { } func fillTestGauge(tv Gauge) { - fillTestNumberDataPointSlice(newNumberDataPointSlice(&tv.orig.DataPoints)) + fillTestNumberDataPointSlice(newNumberDataPointSlice(&tv.orig.DataPoints, tv.state)) } diff --git a/pdata/pmetric/generated_histogram.go b/pdata/pmetric/generated_histogram.go index a32114b86ed..950fb13127e 100644 --- a/pdata/pmetric/generated_histogram.go +++ b/pdata/pmetric/generated_histogram.go @@ -7,6 +7,7 @@ package pmetric import ( + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -18,11 +19,12 @@ import ( // Must use NewHistogram function to create new instances. // Important: zero-initialized instance is not valid for use. type Histogram struct { - orig *otlpmetrics.Histogram + orig *otlpmetrics.Histogram + state *internal.State } -func newHistogram(orig *otlpmetrics.Histogram) Histogram { - return Histogram{orig} +func newHistogram(orig *otlpmetrics.Histogram, state *internal.State) Histogram { + return Histogram{orig: orig, state: state} } // NewHistogram creates a new empty Histogram. @@ -30,12 +32,15 @@ func newHistogram(orig *otlpmetrics.Histogram) Histogram { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewHistogram() Histogram { - return newHistogram(&otlpmetrics.Histogram{}) + state := internal.StateMutable + return newHistogram(&otlpmetrics.Histogram{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms Histogram) MoveTo(dest Histogram) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.Histogram{} } @@ -47,16 +52,18 @@ func (ms Histogram) AggregationTemporality() AggregationTemporality { // SetAggregationTemporality replaces the aggregationtemporality associated with this Histogram. func (ms Histogram) SetAggregationTemporality(v AggregationTemporality) { + ms.state.AssertMutable() ms.orig.AggregationTemporality = otlpmetrics.AggregationTemporality(v) } // DataPoints returns the DataPoints associated with this Histogram. func (ms Histogram) DataPoints() HistogramDataPointSlice { - return newHistogramDataPointSlice(&ms.orig.DataPoints) + return newHistogramDataPointSlice(&ms.orig.DataPoints, ms.state) } // CopyTo copies all properties from the current struct overriding the destination. func (ms Histogram) CopyTo(dest Histogram) { + dest.state.AssertMutable() dest.SetAggregationTemporality(ms.AggregationTemporality()) ms.DataPoints().CopyTo(dest.DataPoints()) } diff --git a/pdata/pmetric/generated_histogram_test.go b/pdata/pmetric/generated_histogram_test.go index b710fddbca0..8eb2dc9dda4 100644 --- a/pdata/pmetric/generated_histogram_test.go +++ b/pdata/pmetric/generated_histogram_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -20,6 +21,9 @@ func TestHistogram_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewHistogram(), ms) assert.Equal(t, generateTestHistogram(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newHistogram(&otlpmetrics.Histogram{}, &sharedState)) }) + assert.Panics(t, func() { newHistogram(&otlpmetrics.Histogram{}, &sharedState).MoveTo(dest) }) } func TestHistogram_CopyTo(t *testing.T) { @@ -30,6 +34,8 @@ func TestHistogram_CopyTo(t *testing.T) { orig = generateTestHistogram() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newHistogram(&otlpmetrics.Histogram{}, &sharedState)) }) } func TestHistogram_AggregationTemporality(t *testing.T) { @@ -55,5 +61,5 @@ func generateTestHistogram() Histogram { func fillTestHistogram(tv Histogram) { tv.orig.AggregationTemporality = otlpmetrics.AggregationTemporality(1) - fillTestHistogramDataPointSlice(newHistogramDataPointSlice(&tv.orig.DataPoints)) + fillTestHistogramDataPointSlice(newHistogramDataPointSlice(&tv.orig.DataPoints, tv.state)) } diff --git a/pdata/pmetric/generated_histogramdatapoint.go b/pdata/pmetric/generated_histogramdatapoint.go index 2901f42f986..22dc32344a2 100644 --- a/pdata/pmetric/generated_histogramdatapoint.go +++ b/pdata/pmetric/generated_histogramdatapoint.go @@ -20,11 +20,12 @@ import ( // Must use NewHistogramDataPoint function to create new instances. // Important: zero-initialized instance is not valid for use. type HistogramDataPoint struct { - orig *otlpmetrics.HistogramDataPoint + orig *otlpmetrics.HistogramDataPoint + state *internal.State } -func newHistogramDataPoint(orig *otlpmetrics.HistogramDataPoint) HistogramDataPoint { - return HistogramDataPoint{orig} +func newHistogramDataPoint(orig *otlpmetrics.HistogramDataPoint, state *internal.State) HistogramDataPoint { + return HistogramDataPoint{orig: orig, state: state} } // NewHistogramDataPoint creates a new empty HistogramDataPoint. @@ -32,19 +33,22 @@ func newHistogramDataPoint(orig *otlpmetrics.HistogramDataPoint) HistogramDataPo // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewHistogramDataPoint() HistogramDataPoint { - return newHistogramDataPoint(&otlpmetrics.HistogramDataPoint{}) + state := internal.StateMutable + return newHistogramDataPoint(&otlpmetrics.HistogramDataPoint{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms HistogramDataPoint) MoveTo(dest HistogramDataPoint) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.HistogramDataPoint{} } // Attributes returns the Attributes associated with this HistogramDataPoint. func (ms HistogramDataPoint) Attributes() pcommon.Map { - return pcommon.Map(internal.NewMap(&ms.orig.Attributes)) + return pcommon.Map(internal.NewMap(&ms.orig.Attributes, ms.state)) } // StartTimestamp returns the starttimestamp associated with this HistogramDataPoint. @@ -54,6 +58,7 @@ func (ms HistogramDataPoint) StartTimestamp() pcommon.Timestamp { // SetStartTimestamp replaces the starttimestamp associated with this HistogramDataPoint. func (ms HistogramDataPoint) SetStartTimestamp(v pcommon.Timestamp) { + ms.state.AssertMutable() ms.orig.StartTimeUnixNano = uint64(v) } @@ -64,6 +69,7 @@ func (ms HistogramDataPoint) Timestamp() pcommon.Timestamp { // SetTimestamp replaces the timestamp associated with this HistogramDataPoint. func (ms HistogramDataPoint) SetTimestamp(v pcommon.Timestamp) { + ms.state.AssertMutable() ms.orig.TimeUnixNano = uint64(v) } @@ -74,43 +80,23 @@ func (ms HistogramDataPoint) Count() uint64 { // SetCount replaces the count associated with this HistogramDataPoint. func (ms HistogramDataPoint) SetCount(v uint64) { + ms.state.AssertMutable() ms.orig.Count = v } -// Sum returns the sum associated with this HistogramDataPoint. -func (ms HistogramDataPoint) Sum() float64 { - return ms.orig.GetSum() -} - -// HasSum returns true if the HistogramDataPoint contains a -// Sum value, false otherwise. -func (ms HistogramDataPoint) HasSum() bool { - return ms.orig.Sum_ != nil -} - -// SetSum replaces the sum associated with this HistogramDataPoint. -func (ms HistogramDataPoint) SetSum(v float64) { - ms.orig.Sum_ = &otlpmetrics.HistogramDataPoint_Sum{Sum: v} -} - -// RemoveSum removes the sum associated with this HistogramDataPoint. -func (ms HistogramDataPoint) RemoveSum() { - ms.orig.Sum_ = nil -} - // BucketCounts returns the bucketcounts associated with this HistogramDataPoint. func (ms HistogramDataPoint) BucketCounts() pcommon.UInt64Slice { - return pcommon.UInt64Slice(internal.NewUInt64Slice(&ms.orig.BucketCounts)) + return pcommon.UInt64Slice(internal.NewUInt64Slice(&ms.orig.BucketCounts, ms.state)) } // ExplicitBounds returns the explicitbounds associated with this HistogramDataPoint. func (ms HistogramDataPoint) ExplicitBounds() pcommon.Float64Slice { - return pcommon.Float64Slice(internal.NewFloat64Slice(&ms.orig.ExplicitBounds)) + return pcommon.Float64Slice(internal.NewFloat64Slice(&ms.orig.ExplicitBounds, ms.state)) } // Exemplars returns the Exemplars associated with this HistogramDataPoint. func (ms HistogramDataPoint) Exemplars() ExemplarSlice { - return newExemplarSlice(&ms.orig.Exemplars) + return newExemplarSlice(&ms.orig.Exemplars, ms.state) } // Flags returns the flags associated with this HistogramDataPoint. @@ -120,9 +106,33 @@ func (ms HistogramDataPoint) Flags() DataPointFlags { // SetFlags replaces the flags associated with this HistogramDataPoint. func (ms HistogramDataPoint) SetFlags(v DataPointFlags) { + ms.state.AssertMutable() ms.orig.Flags = uint32(v) } +// Sum returns the sum associated with this HistogramDataPoint. +func (ms HistogramDataPoint) Sum() float64 { + return ms.orig.GetSum() +} + +// HasSum returns true if the HistogramDataPoint contains a +// Sum value, false otherwise. +func (ms HistogramDataPoint) HasSum() bool { + return ms.orig.Sum_ != nil +} + +// SetSum replaces the sum associated with this HistogramDataPoint. +func (ms HistogramDataPoint) SetSum(v float64) { + ms.state.AssertMutable() + ms.orig.Sum_ = &otlpmetrics.HistogramDataPoint_Sum{Sum: v} +} + +// RemoveSum removes the sum associated with this HistogramDataPoint. +func (ms HistogramDataPoint) RemoveSum() { + ms.state.AssertMutable() + ms.orig.Sum_ = nil +} + // Min returns the min associated with this HistogramDataPoint. func (ms HistogramDataPoint) Min() float64 { return ms.orig.GetMin() @@ -136,11 +146,13 @@ func (ms HistogramDataPoint) HasMin() bool { // SetMin replaces the min associated with this HistogramDataPoint. func (ms HistogramDataPoint) SetMin(v float64) { + ms.state.AssertMutable() ms.orig.Min_ = &otlpmetrics.HistogramDataPoint_Min{Min: v} } // RemoveMin removes the min associated with this HistogramDataPoint. func (ms HistogramDataPoint) RemoveMin() { + ms.state.AssertMutable() ms.orig.Min_ = nil } @@ -157,28 +169,31 @@ func (ms HistogramDataPoint) HasMax() bool { // SetMax replaces the max associated with this HistogramDataPoint. func (ms HistogramDataPoint) SetMax(v float64) { + ms.state.AssertMutable() ms.orig.Max_ = &otlpmetrics.HistogramDataPoint_Max{Max: v} } // RemoveMax removes the max associated with this HistogramDataPoint. func (ms HistogramDataPoint) RemoveMax() { + ms.state.AssertMutable() ms.orig.Max_ = nil } // CopyTo copies all properties from the current struct overriding the destination. func (ms HistogramDataPoint) CopyTo(dest HistogramDataPoint) { + dest.state.AssertMutable() ms.Attributes().CopyTo(dest.Attributes()) dest.SetStartTimestamp(ms.StartTimestamp()) dest.SetTimestamp(ms.Timestamp()) dest.SetCount(ms.Count()) - if ms.HasSum() { - dest.SetSum(ms.Sum()) - } - ms.BucketCounts().CopyTo(dest.BucketCounts()) ms.ExplicitBounds().CopyTo(dest.ExplicitBounds()) ms.Exemplars().CopyTo(dest.Exemplars()) dest.SetFlags(ms.Flags()) + if ms.HasSum() { + dest.SetSum(ms.Sum()) + } + if ms.HasMin() { dest.SetMin(ms.Min()) } diff --git a/pdata/pmetric/generated_histogramdatapoint_test.go b/pdata/pmetric/generated_histogramdatapoint_test.go index 9abc137c174..716cebd4cbf 100644 --- a/pdata/pmetric/generated_histogramdatapoint_test.go +++ b/pdata/pmetric/generated_histogramdatapoint_test.go @@ -22,6 +22,9 @@ func TestHistogramDataPoint_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewHistogramDataPoint(), ms) assert.Equal(t, generateTestHistogramDataPoint(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newHistogramDataPoint(&otlpmetrics.HistogramDataPoint{}, &sharedState)) }) + assert.Panics(t, func() { newHistogramDataPoint(&otlpmetrics.HistogramDataPoint{}, &sharedState).MoveTo(dest) }) } func TestHistogramDataPoint_CopyTo(t *testing.T) { @@ -32,6 +35,8 @@ func TestHistogramDataPoint_CopyTo(t *testing.T) { orig = generateTestHistogramDataPoint() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newHistogramDataPoint(&otlpmetrics.HistogramDataPoint{}, &sharedState)) }) } func TestHistogramDataPoint_Attributes(t *testing.T) { @@ -62,16 +67,8 @@ func TestHistogramDataPoint_Count(t *testing.T) { assert.Equal(t, uint64(0), ms.Count()) ms.SetCount(uint64(17)) assert.Equal(t, uint64(17), ms.Count()) -} - -func TestHistogramDataPoint_Sum(t *testing.T) { - ms := NewHistogramDataPoint() - assert.Equal(t, float64(0.0), ms.Sum()) - ms.SetSum(float64(17.13)) - assert.True(t, ms.HasSum()) - assert.Equal(t, float64(17.13), ms.Sum()) - ms.RemoveSum() - assert.False(t, ms.HasSum()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newHistogramDataPoint(&otlpmetrics.HistogramDataPoint{}, &sharedState).SetCount(uint64(17)) }) } func TestHistogramDataPoint_BucketCounts(t *testing.T) { @@ -103,6 +100,16 @@ func TestHistogramDataPoint_Flags(t *testing.T) { assert.Equal(t, testValFlags, ms.Flags()) } +func TestHistogramDataPoint_Sum(t *testing.T) { + ms := NewHistogramDataPoint() + assert.Equal(t, float64(0.0), ms.Sum()) + ms.SetSum(float64(17.13)) + assert.True(t, ms.HasSum()) + assert.Equal(t, float64(17.13), ms.Sum()) + ms.RemoveSum() + assert.False(t, ms.HasSum()) +} + func TestHistogramDataPoint_Min(t *testing.T) { ms := NewHistogramDataPoint() assert.Equal(t, float64(0.0), ms.Min()) @@ -130,15 +137,15 @@ func generateTestHistogramDataPoint() HistogramDataPoint { } func fillTestHistogramDataPoint(tv HistogramDataPoint) { - internal.FillTestMap(internal.NewMap(&tv.orig.Attributes)) + internal.FillTestMap(internal.NewMap(&tv.orig.Attributes, tv.state)) tv.orig.StartTimeUnixNano = 1234567890 tv.orig.TimeUnixNano = 1234567890 tv.orig.Count = uint64(17) - tv.orig.Sum_ = &otlpmetrics.HistogramDataPoint_Sum{Sum: float64(17.13)} tv.orig.BucketCounts = []uint64{1, 2, 3} tv.orig.ExplicitBounds = []float64{1, 2, 3} - fillTestExemplarSlice(newExemplarSlice(&tv.orig.Exemplars)) + fillTestExemplarSlice(newExemplarSlice(&tv.orig.Exemplars, tv.state)) tv.orig.Flags = 1 + tv.orig.Sum_ = &otlpmetrics.HistogramDataPoint_Sum{Sum: float64(17.13)} tv.orig.Min_ = &otlpmetrics.HistogramDataPoint_Min{Min: float64(9.23)} tv.orig.Max_ = &otlpmetrics.HistogramDataPoint_Max{Max: float64(182.55)} } diff --git a/pdata/pmetric/generated_histogramdatapointslice.go b/pdata/pmetric/generated_histogramdatapointslice.go index 27a018ed89b..7ee6ef737f8 100644 --- a/pdata/pmetric/generated_histogramdatapointslice.go +++ b/pdata/pmetric/generated_histogramdatapointslice.go @@ -9,6 +9,7 @@ package pmetric import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewHistogramDataPointSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type HistogramDataPointSlice struct { - orig *[]*otlpmetrics.HistogramDataPoint + orig *[]*otlpmetrics.HistogramDataPoint + state *internal.State } -func newHistogramDataPointSlice(orig *[]*otlpmetrics.HistogramDataPoint) HistogramDataPointSlice { - return HistogramDataPointSlice{orig} +func newHistogramDataPointSlice(orig *[]*otlpmetrics.HistogramDataPoint, state *internal.State) HistogramDataPointSlice { + return HistogramDataPointSlice{orig: orig, state: state} } // NewHistogramDataPointSlice creates a HistogramDataPointSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewHistogramDataPointSlice() HistogramDataPointSlice { orig := []*otlpmetrics.HistogramDataPoint(nil) - return newHistogramDataPointSlice(&orig) + state := internal.StateMutable + return newHistogramDataPointSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es HistogramDataPointSlice) Len() int { // ... // Do something with the element // } func (es HistogramDataPointSlice) At(i int) HistogramDataPoint { - return newHistogramDataPoint((*es.orig)[i]) + return newHistogramDataPoint((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es HistogramDataPointSlice) At(i int) HistogramDataPoint { // // Here should set all the values for e. // } func (es HistogramDataPointSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es HistogramDataPointSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty HistogramDataPoint. // It returns the newly added HistogramDataPoint. func (es HistogramDataPointSlice) AppendEmpty() HistogramDataPoint { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlpmetrics.HistogramDataPoint{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es HistogramDataPointSlice) AppendEmpty() HistogramDataPoint { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es HistogramDataPointSlice) MoveAndAppendTo(dest HistogramDataPointSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es HistogramDataPointSlice) MoveAndAppendTo(dest HistogramDataPointSlice) // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es HistogramDataPointSlice) RemoveIf(f func(HistogramDataPoint) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es HistogramDataPointSlice) RemoveIf(f func(HistogramDataPoint) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es HistogramDataPointSlice) CopyTo(dest HistogramDataPointSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newHistogramDataPoint((*es.orig)[i]).CopyTo(newHistogramDataPoint((*dest.orig)[i])) + newHistogramDataPoint((*es.orig)[i], es.state).CopyTo(newHistogramDataPoint((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es HistogramDataPointSlice) CopyTo(dest HistogramDataPointSlice) { wrappers := make([]*otlpmetrics.HistogramDataPoint, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newHistogramDataPoint((*es.orig)[i]).CopyTo(newHistogramDataPoint(wrappers[i])) + newHistogramDataPoint((*es.orig)[i], es.state).CopyTo(newHistogramDataPoint(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es HistogramDataPointSlice) CopyTo(dest HistogramDataPointSlice) { // provided less function so that two instances of HistogramDataPointSlice // can be compared. func (es HistogramDataPointSlice) Sort(less func(a, b HistogramDataPoint) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/pmetric/generated_histogramdatapointslice_test.go b/pdata/pmetric/generated_histogramdatapointslice_test.go index 390b7277d7c..bcf4305b993 100644 --- a/pdata/pmetric/generated_histogramdatapointslice_test.go +++ b/pdata/pmetric/generated_histogramdatapointslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) func TestHistogramDataPointSlice(t *testing.T) { es := NewHistogramDataPointSlice() assert.Equal(t, 0, es.Len()) - es = newHistogramDataPointSlice(&[]*otlpmetrics.HistogramDataPoint{}) + state := internal.StateMutable + es = newHistogramDataPointSlice(&[]*otlpmetrics.HistogramDataPoint{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewHistogramDataPoint() @@ -32,6 +34,19 @@ func TestHistogramDataPointSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestHistogramDataPointSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newHistogramDataPointSlice(&[]*otlpmetrics.HistogramDataPoint{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewHistogramDataPointSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestHistogramDataPointSlice_CopyTo(t *testing.T) { dest := NewHistogramDataPointSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestHistogramDataPointSlice(es HistogramDataPointSlice) { *es.orig = make([]*otlpmetrics.HistogramDataPoint, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlpmetrics.HistogramDataPoint{} - fillTestHistogramDataPoint(newHistogramDataPoint((*es.orig)[i])) + fillTestHistogramDataPoint(newHistogramDataPoint((*es.orig)[i], es.state)) } } diff --git a/pdata/pmetric/generated_metric.go b/pdata/pmetric/generated_metric.go index aba0d8e04df..839628520df 100644 --- a/pdata/pmetric/generated_metric.go +++ b/pdata/pmetric/generated_metric.go @@ -7,6 +7,7 @@ package pmetric import ( + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -19,11 +20,12 @@ import ( // Must use NewMetric function to create new instances. // Important: zero-initialized instance is not valid for use. type Metric struct { - orig *otlpmetrics.Metric + orig *otlpmetrics.Metric + state *internal.State } -func newMetric(orig *otlpmetrics.Metric) Metric { - return Metric{orig} +func newMetric(orig *otlpmetrics.Metric, state *internal.State) Metric { + return Metric{orig: orig, state: state} } // NewMetric creates a new empty Metric. @@ -31,12 +33,15 @@ func newMetric(orig *otlpmetrics.Metric) Metric { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewMetric() Metric { - return newMetric(&otlpmetrics.Metric{}) + state := internal.StateMutable + return newMetric(&otlpmetrics.Metric{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms Metric) MoveTo(dest Metric) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.Metric{} } @@ -48,6 +53,7 @@ func (ms Metric) Name() string { // SetName replaces the name associated with this Metric. func (ms Metric) SetName(v string) { + ms.state.AssertMutable() ms.orig.Name = v } @@ -58,6 +64,7 @@ func (ms Metric) Description() string { // SetDescription replaces the description associated with this Metric. func (ms Metric) SetDescription(v string) { + ms.state.AssertMutable() ms.orig.Description = v } @@ -68,6 +75,7 @@ func (ms Metric) Unit() string { // SetUnit replaces the unit associated with this Metric. func (ms Metric) SetUnit(v string) { + ms.state.AssertMutable() ms.orig.Unit = v } @@ -100,7 +108,7 @@ func (ms Metric) Gauge() Gauge { if !ok { return Gauge{} } - return newGauge(v.Gauge) + return newGauge(v.Gauge, ms.state) } // SetEmptyGauge sets an empty gauge to this Metric. @@ -109,9 +117,10 @@ func (ms Metric) Gauge() Gauge { // // Calling this function on zero-initialized Metric will cause a panic. func (ms Metric) SetEmptyGauge() Gauge { + ms.state.AssertMutable() val := &otlpmetrics.Gauge{} ms.orig.Data = &otlpmetrics.Metric_Gauge{Gauge: val} - return newGauge(val) + return newGauge(val, ms.state) } // Sum returns the sum associated with this Metric. @@ -125,7 +134,7 @@ func (ms Metric) Sum() Sum { if !ok { return Sum{} } - return newSum(v.Sum) + return newSum(v.Sum, ms.state) } // SetEmptySum sets an empty sum to this Metric. @@ -134,9 +143,10 @@ func (ms Metric) Sum() Sum { // // Calling this function on zero-initialized Metric will cause a panic. func (ms Metric) SetEmptySum() Sum { + ms.state.AssertMutable() val := &otlpmetrics.Sum{} ms.orig.Data = &otlpmetrics.Metric_Sum{Sum: val} - return newSum(val) + return newSum(val, ms.state) } // Histogram returns the histogram associated with this Metric. @@ -150,7 +160,7 @@ func (ms Metric) Histogram() Histogram { if !ok { return Histogram{} } - return newHistogram(v.Histogram) + return newHistogram(v.Histogram, ms.state) } // SetEmptyHistogram sets an empty histogram to this Metric. @@ -159,9 +169,10 @@ func (ms Metric) Histogram() Histogram { // // Calling this function on zero-initialized Metric will cause a panic. func (ms Metric) SetEmptyHistogram() Histogram { + ms.state.AssertMutable() val := &otlpmetrics.Histogram{} ms.orig.Data = &otlpmetrics.Metric_Histogram{Histogram: val} - return newHistogram(val) + return newHistogram(val, ms.state) } // ExponentialHistogram returns the exponentialhistogram associated with this Metric. @@ -175,7 +186,7 @@ func (ms Metric) ExponentialHistogram() ExponentialHistogram { if !ok { return ExponentialHistogram{} } - return newExponentialHistogram(v.ExponentialHistogram) + return newExponentialHistogram(v.ExponentialHistogram, ms.state) } // SetEmptyExponentialHistogram sets an empty exponentialhistogram to this Metric. @@ -184,9 +195,10 @@ func (ms Metric) ExponentialHistogram() ExponentialHistogram { // // Calling this function on zero-initialized Metric will cause a panic. func (ms Metric) SetEmptyExponentialHistogram() ExponentialHistogram { + ms.state.AssertMutable() val := &otlpmetrics.ExponentialHistogram{} ms.orig.Data = &otlpmetrics.Metric_ExponentialHistogram{ExponentialHistogram: val} - return newExponentialHistogram(val) + return newExponentialHistogram(val, ms.state) } // Summary returns the summary associated with this Metric. @@ -200,7 +212,7 @@ func (ms Metric) Summary() Summary { if !ok { return Summary{} } - return newSummary(v.Summary) + return newSummary(v.Summary, ms.state) } // SetEmptySummary sets an empty summary to this Metric. @@ -209,13 +221,15 @@ func (ms Metric) Summary() Summary { // // Calling this function on zero-initialized Metric will cause a panic. func (ms Metric) SetEmptySummary() Summary { + ms.state.AssertMutable() val := &otlpmetrics.Summary{} ms.orig.Data = &otlpmetrics.Metric_Summary{Summary: val} - return newSummary(val) + return newSummary(val, ms.state) } // CopyTo copies all properties from the current struct overriding the destination. func (ms Metric) CopyTo(dest Metric) { + dest.state.AssertMutable() dest.SetName(ms.Name()) dest.SetDescription(ms.Description()) dest.SetUnit(ms.Unit()) diff --git a/pdata/pmetric/generated_metric_test.go b/pdata/pmetric/generated_metric_test.go index 3dfdedd8627..920891b6096 100644 --- a/pdata/pmetric/generated_metric_test.go +++ b/pdata/pmetric/generated_metric_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -20,6 +21,9 @@ func TestMetric_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewMetric(), ms) assert.Equal(t, generateTestMetric(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) }) + assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).MoveTo(dest) }) } func TestMetric_CopyTo(t *testing.T) { @@ -30,6 +34,8 @@ func TestMetric_CopyTo(t *testing.T) { orig = generateTestMetric() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) }) } func TestMetric_Name(t *testing.T) { @@ -37,6 +43,8 @@ func TestMetric_Name(t *testing.T) { assert.Equal(t, "", ms.Name()) ms.SetName("test_name") assert.Equal(t, "test_name", ms.Name()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetName("test_name") }) } func TestMetric_Description(t *testing.T) { @@ -44,6 +52,8 @@ func TestMetric_Description(t *testing.T) { assert.Equal(t, "", ms.Description()) ms.SetDescription("test_description") assert.Equal(t, "test_description", ms.Description()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetDescription("test_description") }) } func TestMetric_Unit(t *testing.T) { @@ -51,6 +61,8 @@ func TestMetric_Unit(t *testing.T) { assert.Equal(t, "", ms.Unit()) ms.SetUnit("1") assert.Equal(t, "1", ms.Unit()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetUnit("1") }) } func TestMetric_Type(t *testing.T) { @@ -63,6 +75,8 @@ func TestMetric_Gauge(t *testing.T) { fillTestGauge(ms.SetEmptyGauge()) assert.Equal(t, MetricTypeGauge, ms.Type()) assert.Equal(t, generateTestGauge(), ms.Gauge()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetEmptyGauge() }) } func TestMetric_CopyTo_Gauge(t *testing.T) { @@ -71,6 +85,8 @@ func TestMetric_CopyTo_Gauge(t *testing.T) { dest := NewMetric() ms.CopyTo(dest) assert.Equal(t, ms, dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) }) } func TestMetric_Sum(t *testing.T) { @@ -78,6 +94,8 @@ func TestMetric_Sum(t *testing.T) { fillTestSum(ms.SetEmptySum()) assert.Equal(t, MetricTypeSum, ms.Type()) assert.Equal(t, generateTestSum(), ms.Sum()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetEmptySum() }) } func TestMetric_CopyTo_Sum(t *testing.T) { @@ -86,6 +104,8 @@ func TestMetric_CopyTo_Sum(t *testing.T) { dest := NewMetric() ms.CopyTo(dest) assert.Equal(t, ms, dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) }) } func TestMetric_Histogram(t *testing.T) { @@ -93,6 +113,8 @@ func TestMetric_Histogram(t *testing.T) { fillTestHistogram(ms.SetEmptyHistogram()) assert.Equal(t, MetricTypeHistogram, ms.Type()) assert.Equal(t, generateTestHistogram(), ms.Histogram()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetEmptyHistogram() }) } func TestMetric_CopyTo_Histogram(t *testing.T) { @@ -101,6 +123,8 @@ func TestMetric_CopyTo_Histogram(t *testing.T) { dest := NewMetric() ms.CopyTo(dest) assert.Equal(t, ms, dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) }) } func TestMetric_ExponentialHistogram(t *testing.T) { @@ -108,6 +132,8 @@ func TestMetric_ExponentialHistogram(t *testing.T) { fillTestExponentialHistogram(ms.SetEmptyExponentialHistogram()) assert.Equal(t, MetricTypeExponentialHistogram, ms.Type()) assert.Equal(t, generateTestExponentialHistogram(), ms.ExponentialHistogram()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetEmptyExponentialHistogram() }) } func TestMetric_CopyTo_ExponentialHistogram(t *testing.T) { @@ -116,6 +142,8 @@ func TestMetric_CopyTo_ExponentialHistogram(t *testing.T) { dest := NewMetric() ms.CopyTo(dest) assert.Equal(t, ms, dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) }) } func TestMetric_Summary(t *testing.T) { @@ -123,6 +151,8 @@ func TestMetric_Summary(t *testing.T) { fillTestSummary(ms.SetEmptySummary()) assert.Equal(t, MetricTypeSummary, ms.Type()) assert.Equal(t, generateTestSummary(), ms.Summary()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetEmptySummary() }) } func TestMetric_CopyTo_Summary(t *testing.T) { @@ -131,6 +161,8 @@ func TestMetric_CopyTo_Summary(t *testing.T) { dest := NewMetric() ms.CopyTo(dest) assert.Equal(t, ms, dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) }) } func generateTestMetric() Metric { @@ -144,5 +176,5 @@ func fillTestMetric(tv Metric) { tv.orig.Description = "test_description" tv.orig.Unit = "1" tv.orig.Data = &otlpmetrics.Metric_Sum{Sum: &otlpmetrics.Sum{}} - fillTestSum(newSum(tv.orig.GetSum())) + fillTestSum(newSum(tv.orig.GetSum(), tv.state)) } diff --git a/pdata/pmetric/generated_metricslice.go b/pdata/pmetric/generated_metricslice.go index a4e3b7940cf..13f05a0ecbc 100644 --- a/pdata/pmetric/generated_metricslice.go +++ b/pdata/pmetric/generated_metricslice.go @@ -9,6 +9,7 @@ package pmetric import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewMetricSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type MetricSlice struct { - orig *[]*otlpmetrics.Metric + orig *[]*otlpmetrics.Metric + state *internal.State } -func newMetricSlice(orig *[]*otlpmetrics.Metric) MetricSlice { - return MetricSlice{orig} +func newMetricSlice(orig *[]*otlpmetrics.Metric, state *internal.State) MetricSlice { + return MetricSlice{orig: orig, state: state} } // NewMetricSlice creates a MetricSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewMetricSlice() MetricSlice { orig := []*otlpmetrics.Metric(nil) - return newMetricSlice(&orig) + state := internal.StateMutable + return newMetricSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es MetricSlice) Len() int { // ... // Do something with the element // } func (es MetricSlice) At(i int) Metric { - return newMetric((*es.orig)[i]) + return newMetric((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es MetricSlice) At(i int) Metric { // // Here should set all the values for e. // } func (es MetricSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es MetricSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty Metric. // It returns the newly added Metric. func (es MetricSlice) AppendEmpty() Metric { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlpmetrics.Metric{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es MetricSlice) AppendEmpty() Metric { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es MetricSlice) MoveAndAppendTo(dest MetricSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es MetricSlice) MoveAndAppendTo(dest MetricSlice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es MetricSlice) RemoveIf(f func(Metric) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es MetricSlice) RemoveIf(f func(Metric) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es MetricSlice) CopyTo(dest MetricSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newMetric((*es.orig)[i]).CopyTo(newMetric((*dest.orig)[i])) + newMetric((*es.orig)[i], es.state).CopyTo(newMetric((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es MetricSlice) CopyTo(dest MetricSlice) { wrappers := make([]*otlpmetrics.Metric, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newMetric((*es.orig)[i]).CopyTo(newMetric(wrappers[i])) + newMetric((*es.orig)[i], es.state).CopyTo(newMetric(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es MetricSlice) CopyTo(dest MetricSlice) { // provided less function so that two instances of MetricSlice // can be compared. func (es MetricSlice) Sort(less func(a, b Metric) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/pmetric/generated_metricslice_test.go b/pdata/pmetric/generated_metricslice_test.go index 49470381cca..cb89ca8beab 100644 --- a/pdata/pmetric/generated_metricslice_test.go +++ b/pdata/pmetric/generated_metricslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) func TestMetricSlice(t *testing.T) { es := NewMetricSlice() assert.Equal(t, 0, es.Len()) - es = newMetricSlice(&[]*otlpmetrics.Metric{}) + state := internal.StateMutable + es = newMetricSlice(&[]*otlpmetrics.Metric{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewMetric() @@ -32,6 +34,19 @@ func TestMetricSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestMetricSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newMetricSlice(&[]*otlpmetrics.Metric{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewMetricSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestMetricSlice_CopyTo(t *testing.T) { dest := NewMetricSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestMetricSlice(es MetricSlice) { *es.orig = make([]*otlpmetrics.Metric, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlpmetrics.Metric{} - fillTestMetric(newMetric((*es.orig)[i])) + fillTestMetric(newMetric((*es.orig)[i], es.state)) } } diff --git a/pdata/pmetric/generated_numberdatapoint.go b/pdata/pmetric/generated_numberdatapoint.go index 67caecd618e..bc47c4747d1 100644 --- a/pdata/pmetric/generated_numberdatapoint.go +++ b/pdata/pmetric/generated_numberdatapoint.go @@ -20,11 +20,12 @@ import ( // Must use NewNumberDataPoint function to create new instances. // Important: zero-initialized instance is not valid for use. type NumberDataPoint struct { - orig *otlpmetrics.NumberDataPoint + orig *otlpmetrics.NumberDataPoint + state *internal.State } -func newNumberDataPoint(orig *otlpmetrics.NumberDataPoint) NumberDataPoint { - return NumberDataPoint{orig} +func newNumberDataPoint(orig *otlpmetrics.NumberDataPoint, state *internal.State) NumberDataPoint { + return NumberDataPoint{orig: orig, state: state} } // NewNumberDataPoint creates a new empty NumberDataPoint. @@ -32,19 +33,22 @@ func newNumberDataPoint(orig *otlpmetrics.NumberDataPoint) NumberDataPoint { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewNumberDataPoint() NumberDataPoint { - return newNumberDataPoint(&otlpmetrics.NumberDataPoint{}) + state := internal.StateMutable + return newNumberDataPoint(&otlpmetrics.NumberDataPoint{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms NumberDataPoint) MoveTo(dest NumberDataPoint) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.NumberDataPoint{} } // Attributes returns the Attributes associated with this NumberDataPoint. func (ms NumberDataPoint) Attributes() pcommon.Map { - return pcommon.Map(internal.NewMap(&ms.orig.Attributes)) + return pcommon.Map(internal.NewMap(&ms.orig.Attributes, ms.state)) } // StartTimestamp returns the starttimestamp associated with this NumberDataPoint. @@ -54,6 +58,7 @@ func (ms NumberDataPoint) StartTimestamp() pcommon.Timestamp { // SetStartTimestamp replaces the starttimestamp associated with this NumberDataPoint. func (ms NumberDataPoint) SetStartTimestamp(v pcommon.Timestamp) { + ms.state.AssertMutable() ms.orig.StartTimeUnixNano = uint64(v) } @@ -64,6 +69,7 @@ func (ms NumberDataPoint) Timestamp() pcommon.Timestamp { // SetTimestamp replaces the timestamp associated with this NumberDataPoint. func (ms NumberDataPoint) SetTimestamp(v pcommon.Timestamp) { + ms.state.AssertMutable() ms.orig.TimeUnixNano = uint64(v) } @@ -86,6 +92,7 @@ func (ms NumberDataPoint) DoubleValue() float64 { // SetDoubleValue replaces the double associated with this NumberDataPoint. func (ms NumberDataPoint) SetDoubleValue(v float64) { + ms.state.AssertMutable() ms.orig.Value = &otlpmetrics.NumberDataPoint_AsDouble{ AsDouble: v, } @@ -98,6 +105,7 @@ func (ms NumberDataPoint) IntValue() int64 { // SetIntValue replaces the int associated with this NumberDataPoint. func (ms NumberDataPoint) SetIntValue(v int64) { + ms.state.AssertMutable() ms.orig.Value = &otlpmetrics.NumberDataPoint_AsInt{ AsInt: v, } @@ -105,7 +113,7 @@ func (ms NumberDataPoint) SetIntValue(v int64) { // Exemplars returns the Exemplars associated with this NumberDataPoint. func (ms NumberDataPoint) Exemplars() ExemplarSlice { - return newExemplarSlice(&ms.orig.Exemplars) + return newExemplarSlice(&ms.orig.Exemplars, ms.state) } // Flags returns the flags associated with this NumberDataPoint. @@ -115,11 +123,13 @@ func (ms NumberDataPoint) Flags() DataPointFlags { // SetFlags replaces the flags associated with this NumberDataPoint. func (ms NumberDataPoint) SetFlags(v DataPointFlags) { + ms.state.AssertMutable() ms.orig.Flags = uint32(v) } // CopyTo copies all properties from the current struct overriding the destination. func (ms NumberDataPoint) CopyTo(dest NumberDataPoint) { + dest.state.AssertMutable() ms.Attributes().CopyTo(dest.Attributes()) dest.SetStartTimestamp(ms.StartTimestamp()) dest.SetTimestamp(ms.Timestamp()) diff --git a/pdata/pmetric/generated_numberdatapoint_test.go b/pdata/pmetric/generated_numberdatapoint_test.go index c54c8adffc3..2c7cedd7ff6 100644 --- a/pdata/pmetric/generated_numberdatapoint_test.go +++ b/pdata/pmetric/generated_numberdatapoint_test.go @@ -22,6 +22,9 @@ func TestNumberDataPoint_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewNumberDataPoint(), ms) assert.Equal(t, generateTestNumberDataPoint(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newNumberDataPoint(&otlpmetrics.NumberDataPoint{}, &sharedState)) }) + assert.Panics(t, func() { newNumberDataPoint(&otlpmetrics.NumberDataPoint{}, &sharedState).MoveTo(dest) }) } func TestNumberDataPoint_CopyTo(t *testing.T) { @@ -32,6 +35,8 @@ func TestNumberDataPoint_CopyTo(t *testing.T) { orig = generateTestNumberDataPoint() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newNumberDataPoint(&otlpmetrics.NumberDataPoint{}, &sharedState)) }) } func TestNumberDataPoint_Attributes(t *testing.T) { @@ -68,6 +73,10 @@ func TestNumberDataPoint_DoubleValue(t *testing.T) { ms.SetDoubleValue(float64(17.13)) assert.Equal(t, float64(17.13), ms.DoubleValue()) assert.Equal(t, NumberDataPointValueTypeDouble, ms.ValueType()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newNumberDataPoint(&otlpmetrics.NumberDataPoint{}, &sharedState).SetDoubleValue(float64(17.13)) + }) } func TestNumberDataPoint_IntValue(t *testing.T) { @@ -76,6 +85,8 @@ func TestNumberDataPoint_IntValue(t *testing.T) { ms.SetIntValue(int64(17)) assert.Equal(t, int64(17), ms.IntValue()) assert.Equal(t, NumberDataPointValueTypeInt, ms.ValueType()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newNumberDataPoint(&otlpmetrics.NumberDataPoint{}, &sharedState).SetIntValue(int64(17)) }) } func TestNumberDataPoint_Exemplars(t *testing.T) { @@ -100,10 +111,10 @@ func generateTestNumberDataPoint() NumberDataPoint { } func fillTestNumberDataPoint(tv NumberDataPoint) { - internal.FillTestMap(internal.NewMap(&tv.orig.Attributes)) + internal.FillTestMap(internal.NewMap(&tv.orig.Attributes, tv.state)) tv.orig.StartTimeUnixNano = 1234567890 tv.orig.TimeUnixNano = 1234567890 tv.orig.Value = &otlpmetrics.NumberDataPoint_AsDouble{AsDouble: float64(17.13)} - fillTestExemplarSlice(newExemplarSlice(&tv.orig.Exemplars)) + fillTestExemplarSlice(newExemplarSlice(&tv.orig.Exemplars, tv.state)) tv.orig.Flags = 1 } diff --git a/pdata/pmetric/generated_numberdatapointslice.go b/pdata/pmetric/generated_numberdatapointslice.go index 777a7209424..57cdd11743e 100644 --- a/pdata/pmetric/generated_numberdatapointslice.go +++ b/pdata/pmetric/generated_numberdatapointslice.go @@ -9,6 +9,7 @@ package pmetric import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewNumberDataPointSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type NumberDataPointSlice struct { - orig *[]*otlpmetrics.NumberDataPoint + orig *[]*otlpmetrics.NumberDataPoint + state *internal.State } -func newNumberDataPointSlice(orig *[]*otlpmetrics.NumberDataPoint) NumberDataPointSlice { - return NumberDataPointSlice{orig} +func newNumberDataPointSlice(orig *[]*otlpmetrics.NumberDataPoint, state *internal.State) NumberDataPointSlice { + return NumberDataPointSlice{orig: orig, state: state} } // NewNumberDataPointSlice creates a NumberDataPointSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewNumberDataPointSlice() NumberDataPointSlice { orig := []*otlpmetrics.NumberDataPoint(nil) - return newNumberDataPointSlice(&orig) + state := internal.StateMutable + return newNumberDataPointSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es NumberDataPointSlice) Len() int { // ... // Do something with the element // } func (es NumberDataPointSlice) At(i int) NumberDataPoint { - return newNumberDataPoint((*es.orig)[i]) + return newNumberDataPoint((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es NumberDataPointSlice) At(i int) NumberDataPoint { // // Here should set all the values for e. // } func (es NumberDataPointSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es NumberDataPointSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty NumberDataPoint. // It returns the newly added NumberDataPoint. func (es NumberDataPointSlice) AppendEmpty() NumberDataPoint { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlpmetrics.NumberDataPoint{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es NumberDataPointSlice) AppendEmpty() NumberDataPoint { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es NumberDataPointSlice) MoveAndAppendTo(dest NumberDataPointSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es NumberDataPointSlice) MoveAndAppendTo(dest NumberDataPointSlice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es NumberDataPointSlice) RemoveIf(f func(NumberDataPoint) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es NumberDataPointSlice) RemoveIf(f func(NumberDataPoint) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es NumberDataPointSlice) CopyTo(dest NumberDataPointSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newNumberDataPoint((*es.orig)[i]).CopyTo(newNumberDataPoint((*dest.orig)[i])) + newNumberDataPoint((*es.orig)[i], es.state).CopyTo(newNumberDataPoint((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es NumberDataPointSlice) CopyTo(dest NumberDataPointSlice) { wrappers := make([]*otlpmetrics.NumberDataPoint, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newNumberDataPoint((*es.orig)[i]).CopyTo(newNumberDataPoint(wrappers[i])) + newNumberDataPoint((*es.orig)[i], es.state).CopyTo(newNumberDataPoint(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es NumberDataPointSlice) CopyTo(dest NumberDataPointSlice) { // provided less function so that two instances of NumberDataPointSlice // can be compared. func (es NumberDataPointSlice) Sort(less func(a, b NumberDataPoint) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/pmetric/generated_numberdatapointslice_test.go b/pdata/pmetric/generated_numberdatapointslice_test.go index aeda43533f8..6bc35ff03c2 100644 --- a/pdata/pmetric/generated_numberdatapointslice_test.go +++ b/pdata/pmetric/generated_numberdatapointslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) func TestNumberDataPointSlice(t *testing.T) { es := NewNumberDataPointSlice() assert.Equal(t, 0, es.Len()) - es = newNumberDataPointSlice(&[]*otlpmetrics.NumberDataPoint{}) + state := internal.StateMutable + es = newNumberDataPointSlice(&[]*otlpmetrics.NumberDataPoint{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewNumberDataPoint() @@ -32,6 +34,19 @@ func TestNumberDataPointSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestNumberDataPointSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newNumberDataPointSlice(&[]*otlpmetrics.NumberDataPoint{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewNumberDataPointSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestNumberDataPointSlice_CopyTo(t *testing.T) { dest := NewNumberDataPointSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestNumberDataPointSlice(es NumberDataPointSlice) { *es.orig = make([]*otlpmetrics.NumberDataPoint, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlpmetrics.NumberDataPoint{} - fillTestNumberDataPoint(newNumberDataPoint((*es.orig)[i])) + fillTestNumberDataPoint(newNumberDataPoint((*es.orig)[i], es.state)) } } diff --git a/pdata/pmetric/generated_resourcemetrics.go b/pdata/pmetric/generated_resourcemetrics.go index 520de76c9c3..43622f3f806 100644 --- a/pdata/pmetric/generated_resourcemetrics.go +++ b/pdata/pmetric/generated_resourcemetrics.go @@ -20,11 +20,12 @@ import ( // Must use NewResourceMetrics function to create new instances. // Important: zero-initialized instance is not valid for use. type ResourceMetrics struct { - orig *otlpmetrics.ResourceMetrics + orig *otlpmetrics.ResourceMetrics + state *internal.State } -func newResourceMetrics(orig *otlpmetrics.ResourceMetrics) ResourceMetrics { - return ResourceMetrics{orig} +func newResourceMetrics(orig *otlpmetrics.ResourceMetrics, state *internal.State) ResourceMetrics { + return ResourceMetrics{orig: orig, state: state} } // NewResourceMetrics creates a new empty ResourceMetrics. @@ -32,19 +33,22 @@ func newResourceMetrics(orig *otlpmetrics.ResourceMetrics) ResourceMetrics { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewResourceMetrics() ResourceMetrics { - return newResourceMetrics(&otlpmetrics.ResourceMetrics{}) + state := internal.StateMutable + return newResourceMetrics(&otlpmetrics.ResourceMetrics{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms ResourceMetrics) MoveTo(dest ResourceMetrics) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.ResourceMetrics{} } // Resource returns the resource associated with this ResourceMetrics. func (ms ResourceMetrics) Resource() pcommon.Resource { - return pcommon.Resource(internal.NewResource(&ms.orig.Resource)) + return pcommon.Resource(internal.NewResource(&ms.orig.Resource, ms.state)) } // SchemaUrl returns the schemaurl associated with this ResourceMetrics. @@ -54,16 +58,18 @@ func (ms ResourceMetrics) SchemaUrl() string { // SetSchemaUrl replaces the schemaurl associated with this ResourceMetrics. func (ms ResourceMetrics) SetSchemaUrl(v string) { + ms.state.AssertMutable() ms.orig.SchemaUrl = v } // ScopeMetrics returns the ScopeMetrics associated with this ResourceMetrics. func (ms ResourceMetrics) ScopeMetrics() ScopeMetricsSlice { - return newScopeMetricsSlice(&ms.orig.ScopeMetrics) + return newScopeMetricsSlice(&ms.orig.ScopeMetrics, ms.state) } // CopyTo copies all properties from the current struct overriding the destination. func (ms ResourceMetrics) CopyTo(dest ResourceMetrics) { + dest.state.AssertMutable() ms.Resource().CopyTo(dest.Resource()) dest.SetSchemaUrl(ms.SchemaUrl()) ms.ScopeMetrics().CopyTo(dest.ScopeMetrics()) diff --git a/pdata/pmetric/generated_resourcemetrics_test.go b/pdata/pmetric/generated_resourcemetrics_test.go index d7bba42cc98..7bdfec11beb 100644 --- a/pdata/pmetric/generated_resourcemetrics_test.go +++ b/pdata/pmetric/generated_resourcemetrics_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/pdata/internal" + otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -21,6 +22,9 @@ func TestResourceMetrics_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewResourceMetrics(), ms) assert.Equal(t, generateTestResourceMetrics(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newResourceMetrics(&otlpmetrics.ResourceMetrics{}, &sharedState)) }) + assert.Panics(t, func() { newResourceMetrics(&otlpmetrics.ResourceMetrics{}, &sharedState).MoveTo(dest) }) } func TestResourceMetrics_CopyTo(t *testing.T) { @@ -31,6 +35,8 @@ func TestResourceMetrics_CopyTo(t *testing.T) { orig = generateTestResourceMetrics() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newResourceMetrics(&otlpmetrics.ResourceMetrics{}, &sharedState)) }) } func TestResourceMetrics_Resource(t *testing.T) { @@ -44,6 +50,10 @@ func TestResourceMetrics_SchemaUrl(t *testing.T) { assert.Equal(t, "", ms.SchemaUrl()) ms.SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0") assert.Equal(t, "https://opentelemetry.io/schemas/1.5.0", ms.SchemaUrl()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newResourceMetrics(&otlpmetrics.ResourceMetrics{}, &sharedState).SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0") + }) } func TestResourceMetrics_ScopeMetrics(t *testing.T) { @@ -60,7 +70,7 @@ func generateTestResourceMetrics() ResourceMetrics { } func fillTestResourceMetrics(tv ResourceMetrics) { - internal.FillTestResource(internal.NewResource(&tv.orig.Resource)) + internal.FillTestResource(internal.NewResource(&tv.orig.Resource, tv.state)) tv.orig.SchemaUrl = "https://opentelemetry.io/schemas/1.5.0" - fillTestScopeMetricsSlice(newScopeMetricsSlice(&tv.orig.ScopeMetrics)) + fillTestScopeMetricsSlice(newScopeMetricsSlice(&tv.orig.ScopeMetrics, tv.state)) } diff --git a/pdata/pmetric/generated_resourcemetricsslice.go b/pdata/pmetric/generated_resourcemetricsslice.go index 4f089354bda..55217ea27d5 100644 --- a/pdata/pmetric/generated_resourcemetricsslice.go +++ b/pdata/pmetric/generated_resourcemetricsslice.go @@ -9,6 +9,7 @@ package pmetric import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewResourceMetricsSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type ResourceMetricsSlice struct { - orig *[]*otlpmetrics.ResourceMetrics + orig *[]*otlpmetrics.ResourceMetrics + state *internal.State } -func newResourceMetricsSlice(orig *[]*otlpmetrics.ResourceMetrics) ResourceMetricsSlice { - return ResourceMetricsSlice{orig} +func newResourceMetricsSlice(orig *[]*otlpmetrics.ResourceMetrics, state *internal.State) ResourceMetricsSlice { + return ResourceMetricsSlice{orig: orig, state: state} } // NewResourceMetricsSlice creates a ResourceMetricsSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewResourceMetricsSlice() ResourceMetricsSlice { orig := []*otlpmetrics.ResourceMetrics(nil) - return newResourceMetricsSlice(&orig) + state := internal.StateMutable + return newResourceMetricsSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es ResourceMetricsSlice) Len() int { // ... // Do something with the element // } func (es ResourceMetricsSlice) At(i int) ResourceMetrics { - return newResourceMetrics((*es.orig)[i]) + return newResourceMetrics((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es ResourceMetricsSlice) At(i int) ResourceMetrics { // // Here should set all the values for e. // } func (es ResourceMetricsSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es ResourceMetricsSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty ResourceMetrics. // It returns the newly added ResourceMetrics. func (es ResourceMetricsSlice) AppendEmpty() ResourceMetrics { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlpmetrics.ResourceMetrics{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es ResourceMetricsSlice) AppendEmpty() ResourceMetrics { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es ResourceMetricsSlice) MoveAndAppendTo(dest ResourceMetricsSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es ResourceMetricsSlice) MoveAndAppendTo(dest ResourceMetricsSlice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es ResourceMetricsSlice) RemoveIf(f func(ResourceMetrics) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es ResourceMetricsSlice) RemoveIf(f func(ResourceMetrics) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es ResourceMetricsSlice) CopyTo(dest ResourceMetricsSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newResourceMetrics((*es.orig)[i]).CopyTo(newResourceMetrics((*dest.orig)[i])) + newResourceMetrics((*es.orig)[i], es.state).CopyTo(newResourceMetrics((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es ResourceMetricsSlice) CopyTo(dest ResourceMetricsSlice) { wrappers := make([]*otlpmetrics.ResourceMetrics, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newResourceMetrics((*es.orig)[i]).CopyTo(newResourceMetrics(wrappers[i])) + newResourceMetrics((*es.orig)[i], es.state).CopyTo(newResourceMetrics(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es ResourceMetricsSlice) CopyTo(dest ResourceMetricsSlice) { // provided less function so that two instances of ResourceMetricsSlice // can be compared. func (es ResourceMetricsSlice) Sort(less func(a, b ResourceMetrics) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/pmetric/generated_resourcemetricsslice_test.go b/pdata/pmetric/generated_resourcemetricsslice_test.go index acf358f91bd..869f7a37503 100644 --- a/pdata/pmetric/generated_resourcemetricsslice_test.go +++ b/pdata/pmetric/generated_resourcemetricsslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) func TestResourceMetricsSlice(t *testing.T) { es := NewResourceMetricsSlice() assert.Equal(t, 0, es.Len()) - es = newResourceMetricsSlice(&[]*otlpmetrics.ResourceMetrics{}) + state := internal.StateMutable + es = newResourceMetricsSlice(&[]*otlpmetrics.ResourceMetrics{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewResourceMetrics() @@ -32,6 +34,19 @@ func TestResourceMetricsSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestResourceMetricsSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newResourceMetricsSlice(&[]*otlpmetrics.ResourceMetrics{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewResourceMetricsSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestResourceMetricsSlice_CopyTo(t *testing.T) { dest := NewResourceMetricsSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestResourceMetricsSlice(es ResourceMetricsSlice) { *es.orig = make([]*otlpmetrics.ResourceMetrics, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlpmetrics.ResourceMetrics{} - fillTestResourceMetrics(newResourceMetrics((*es.orig)[i])) + fillTestResourceMetrics(newResourceMetrics((*es.orig)[i], es.state)) } } diff --git a/pdata/pmetric/generated_scopemetrics.go b/pdata/pmetric/generated_scopemetrics.go index f4ea50a31f8..1151c36dae3 100644 --- a/pdata/pmetric/generated_scopemetrics.go +++ b/pdata/pmetric/generated_scopemetrics.go @@ -20,11 +20,12 @@ import ( // Must use NewScopeMetrics function to create new instances. // Important: zero-initialized instance is not valid for use. type ScopeMetrics struct { - orig *otlpmetrics.ScopeMetrics + orig *otlpmetrics.ScopeMetrics + state *internal.State } -func newScopeMetrics(orig *otlpmetrics.ScopeMetrics) ScopeMetrics { - return ScopeMetrics{orig} +func newScopeMetrics(orig *otlpmetrics.ScopeMetrics, state *internal.State) ScopeMetrics { + return ScopeMetrics{orig: orig, state: state} } // NewScopeMetrics creates a new empty ScopeMetrics. @@ -32,19 +33,22 @@ func newScopeMetrics(orig *otlpmetrics.ScopeMetrics) ScopeMetrics { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewScopeMetrics() ScopeMetrics { - return newScopeMetrics(&otlpmetrics.ScopeMetrics{}) + state := internal.StateMutable + return newScopeMetrics(&otlpmetrics.ScopeMetrics{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms ScopeMetrics) MoveTo(dest ScopeMetrics) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.ScopeMetrics{} } // Scope returns the scope associated with this ScopeMetrics. func (ms ScopeMetrics) Scope() pcommon.InstrumentationScope { - return pcommon.InstrumentationScope(internal.NewInstrumentationScope(&ms.orig.Scope)) + return pcommon.InstrumentationScope(internal.NewInstrumentationScope(&ms.orig.Scope, ms.state)) } // SchemaUrl returns the schemaurl associated with this ScopeMetrics. @@ -54,16 +58,18 @@ func (ms ScopeMetrics) SchemaUrl() string { // SetSchemaUrl replaces the schemaurl associated with this ScopeMetrics. func (ms ScopeMetrics) SetSchemaUrl(v string) { + ms.state.AssertMutable() ms.orig.SchemaUrl = v } // Metrics returns the Metrics associated with this ScopeMetrics. func (ms ScopeMetrics) Metrics() MetricSlice { - return newMetricSlice(&ms.orig.Metrics) + return newMetricSlice(&ms.orig.Metrics, ms.state) } // CopyTo copies all properties from the current struct overriding the destination. func (ms ScopeMetrics) CopyTo(dest ScopeMetrics) { + dest.state.AssertMutable() ms.Scope().CopyTo(dest.Scope()) dest.SetSchemaUrl(ms.SchemaUrl()) ms.Metrics().CopyTo(dest.Metrics()) diff --git a/pdata/pmetric/generated_scopemetrics_test.go b/pdata/pmetric/generated_scopemetrics_test.go index 4734e7efc50..451c4743657 100644 --- a/pdata/pmetric/generated_scopemetrics_test.go +++ b/pdata/pmetric/generated_scopemetrics_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/pdata/internal" + otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -21,6 +22,9 @@ func TestScopeMetrics_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewScopeMetrics(), ms) assert.Equal(t, generateTestScopeMetrics(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newScopeMetrics(&otlpmetrics.ScopeMetrics{}, &sharedState)) }) + assert.Panics(t, func() { newScopeMetrics(&otlpmetrics.ScopeMetrics{}, &sharedState).MoveTo(dest) }) } func TestScopeMetrics_CopyTo(t *testing.T) { @@ -31,6 +35,8 @@ func TestScopeMetrics_CopyTo(t *testing.T) { orig = generateTestScopeMetrics() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newScopeMetrics(&otlpmetrics.ScopeMetrics{}, &sharedState)) }) } func TestScopeMetrics_Scope(t *testing.T) { @@ -44,6 +50,10 @@ func TestScopeMetrics_SchemaUrl(t *testing.T) { assert.Equal(t, "", ms.SchemaUrl()) ms.SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0") assert.Equal(t, "https://opentelemetry.io/schemas/1.5.0", ms.SchemaUrl()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newScopeMetrics(&otlpmetrics.ScopeMetrics{}, &sharedState).SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0") + }) } func TestScopeMetrics_Metrics(t *testing.T) { @@ -60,7 +70,7 @@ func generateTestScopeMetrics() ScopeMetrics { } func fillTestScopeMetrics(tv ScopeMetrics) { - internal.FillTestInstrumentationScope(internal.NewInstrumentationScope(&tv.orig.Scope)) + internal.FillTestInstrumentationScope(internal.NewInstrumentationScope(&tv.orig.Scope, tv.state)) tv.orig.SchemaUrl = "https://opentelemetry.io/schemas/1.5.0" - fillTestMetricSlice(newMetricSlice(&tv.orig.Metrics)) + fillTestMetricSlice(newMetricSlice(&tv.orig.Metrics, tv.state)) } diff --git a/pdata/pmetric/generated_scopemetricsslice.go b/pdata/pmetric/generated_scopemetricsslice.go index 90cc4979e53..a86eb0b4815 100644 --- a/pdata/pmetric/generated_scopemetricsslice.go +++ b/pdata/pmetric/generated_scopemetricsslice.go @@ -9,6 +9,7 @@ package pmetric import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewScopeMetricsSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type ScopeMetricsSlice struct { - orig *[]*otlpmetrics.ScopeMetrics + orig *[]*otlpmetrics.ScopeMetrics + state *internal.State } -func newScopeMetricsSlice(orig *[]*otlpmetrics.ScopeMetrics) ScopeMetricsSlice { - return ScopeMetricsSlice{orig} +func newScopeMetricsSlice(orig *[]*otlpmetrics.ScopeMetrics, state *internal.State) ScopeMetricsSlice { + return ScopeMetricsSlice{orig: orig, state: state} } // NewScopeMetricsSlice creates a ScopeMetricsSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewScopeMetricsSlice() ScopeMetricsSlice { orig := []*otlpmetrics.ScopeMetrics(nil) - return newScopeMetricsSlice(&orig) + state := internal.StateMutable + return newScopeMetricsSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es ScopeMetricsSlice) Len() int { // ... // Do something with the element // } func (es ScopeMetricsSlice) At(i int) ScopeMetrics { - return newScopeMetrics((*es.orig)[i]) + return newScopeMetrics((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es ScopeMetricsSlice) At(i int) ScopeMetrics { // // Here should set all the values for e. // } func (es ScopeMetricsSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es ScopeMetricsSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty ScopeMetrics. // It returns the newly added ScopeMetrics. func (es ScopeMetricsSlice) AppendEmpty() ScopeMetrics { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlpmetrics.ScopeMetrics{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es ScopeMetricsSlice) AppendEmpty() ScopeMetrics { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es ScopeMetricsSlice) MoveAndAppendTo(dest ScopeMetricsSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es ScopeMetricsSlice) MoveAndAppendTo(dest ScopeMetricsSlice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es ScopeMetricsSlice) RemoveIf(f func(ScopeMetrics) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es ScopeMetricsSlice) RemoveIf(f func(ScopeMetrics) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es ScopeMetricsSlice) CopyTo(dest ScopeMetricsSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newScopeMetrics((*es.orig)[i]).CopyTo(newScopeMetrics((*dest.orig)[i])) + newScopeMetrics((*es.orig)[i], es.state).CopyTo(newScopeMetrics((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es ScopeMetricsSlice) CopyTo(dest ScopeMetricsSlice) { wrappers := make([]*otlpmetrics.ScopeMetrics, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newScopeMetrics((*es.orig)[i]).CopyTo(newScopeMetrics(wrappers[i])) + newScopeMetrics((*es.orig)[i], es.state).CopyTo(newScopeMetrics(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es ScopeMetricsSlice) CopyTo(dest ScopeMetricsSlice) { // provided less function so that two instances of ScopeMetricsSlice // can be compared. func (es ScopeMetricsSlice) Sort(less func(a, b ScopeMetrics) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/pmetric/generated_scopemetricsslice_test.go b/pdata/pmetric/generated_scopemetricsslice_test.go index f6a4c3f5960..b0903bc256e 100644 --- a/pdata/pmetric/generated_scopemetricsslice_test.go +++ b/pdata/pmetric/generated_scopemetricsslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) func TestScopeMetricsSlice(t *testing.T) { es := NewScopeMetricsSlice() assert.Equal(t, 0, es.Len()) - es = newScopeMetricsSlice(&[]*otlpmetrics.ScopeMetrics{}) + state := internal.StateMutable + es = newScopeMetricsSlice(&[]*otlpmetrics.ScopeMetrics{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewScopeMetrics() @@ -32,6 +34,19 @@ func TestScopeMetricsSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestScopeMetricsSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newScopeMetricsSlice(&[]*otlpmetrics.ScopeMetrics{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewScopeMetricsSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestScopeMetricsSlice_CopyTo(t *testing.T) { dest := NewScopeMetricsSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestScopeMetricsSlice(es ScopeMetricsSlice) { *es.orig = make([]*otlpmetrics.ScopeMetrics, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlpmetrics.ScopeMetrics{} - fillTestScopeMetrics(newScopeMetrics((*es.orig)[i])) + fillTestScopeMetrics(newScopeMetrics((*es.orig)[i], es.state)) } } diff --git a/pdata/pmetric/generated_sum.go b/pdata/pmetric/generated_sum.go index 13cfe7d3f75..7def0749aa5 100644 --- a/pdata/pmetric/generated_sum.go +++ b/pdata/pmetric/generated_sum.go @@ -7,6 +7,7 @@ package pmetric import ( + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -18,11 +19,12 @@ import ( // Must use NewSum function to create new instances. // Important: zero-initialized instance is not valid for use. type Sum struct { - orig *otlpmetrics.Sum + orig *otlpmetrics.Sum + state *internal.State } -func newSum(orig *otlpmetrics.Sum) Sum { - return Sum{orig} +func newSum(orig *otlpmetrics.Sum, state *internal.State) Sum { + return Sum{orig: orig, state: state} } // NewSum creates a new empty Sum. @@ -30,12 +32,15 @@ func newSum(orig *otlpmetrics.Sum) Sum { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewSum() Sum { - return newSum(&otlpmetrics.Sum{}) + state := internal.StateMutable + return newSum(&otlpmetrics.Sum{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms Sum) MoveTo(dest Sum) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.Sum{} } @@ -47,6 +52,7 @@ func (ms Sum) AggregationTemporality() AggregationTemporality { // SetAggregationTemporality replaces the aggregationtemporality associated with this Sum. func (ms Sum) SetAggregationTemporality(v AggregationTemporality) { + ms.state.AssertMutable() ms.orig.AggregationTemporality = otlpmetrics.AggregationTemporality(v) } @@ -57,16 +63,18 @@ func (ms Sum) IsMonotonic() bool { // SetIsMonotonic replaces the ismonotonic associated with this Sum. func (ms Sum) SetIsMonotonic(v bool) { + ms.state.AssertMutable() ms.orig.IsMonotonic = v } // DataPoints returns the DataPoints associated with this Sum. func (ms Sum) DataPoints() NumberDataPointSlice { - return newNumberDataPointSlice(&ms.orig.DataPoints) + return newNumberDataPointSlice(&ms.orig.DataPoints, ms.state) } // CopyTo copies all properties from the current struct overriding the destination. func (ms Sum) CopyTo(dest Sum) { + dest.state.AssertMutable() dest.SetAggregationTemporality(ms.AggregationTemporality()) dest.SetIsMonotonic(ms.IsMonotonic()) ms.DataPoints().CopyTo(dest.DataPoints()) diff --git a/pdata/pmetric/generated_sum_test.go b/pdata/pmetric/generated_sum_test.go index f2590feea06..98f3574b10f 100644 --- a/pdata/pmetric/generated_sum_test.go +++ b/pdata/pmetric/generated_sum_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -20,6 +21,9 @@ func TestSum_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewSum(), ms) assert.Equal(t, generateTestSum(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newSum(&otlpmetrics.Sum{}, &sharedState)) }) + assert.Panics(t, func() { newSum(&otlpmetrics.Sum{}, &sharedState).MoveTo(dest) }) } func TestSum_CopyTo(t *testing.T) { @@ -30,6 +34,8 @@ func TestSum_CopyTo(t *testing.T) { orig = generateTestSum() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newSum(&otlpmetrics.Sum{}, &sharedState)) }) } func TestSum_AggregationTemporality(t *testing.T) { @@ -45,6 +51,8 @@ func TestSum_IsMonotonic(t *testing.T) { assert.Equal(t, false, ms.IsMonotonic()) ms.SetIsMonotonic(true) assert.Equal(t, true, ms.IsMonotonic()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newSum(&otlpmetrics.Sum{}, &sharedState).SetIsMonotonic(true) }) } func TestSum_DataPoints(t *testing.T) { @@ -63,5 +71,5 @@ func generateTestSum() Sum { func fillTestSum(tv Sum) { tv.orig.AggregationTemporality = otlpmetrics.AggregationTemporality(1) tv.orig.IsMonotonic = true - fillTestNumberDataPointSlice(newNumberDataPointSlice(&tv.orig.DataPoints)) + fillTestNumberDataPointSlice(newNumberDataPointSlice(&tv.orig.DataPoints, tv.state)) } diff --git a/pdata/pmetric/generated_summary.go b/pdata/pmetric/generated_summary.go index bea3b764b5d..64fbffbefd3 100644 --- a/pdata/pmetric/generated_summary.go +++ b/pdata/pmetric/generated_summary.go @@ -7,6 +7,7 @@ package pmetric import ( + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -18,11 +19,12 @@ import ( // Must use NewSummary function to create new instances. // Important: zero-initialized instance is not valid for use. type Summary struct { - orig *otlpmetrics.Summary + orig *otlpmetrics.Summary + state *internal.State } -func newSummary(orig *otlpmetrics.Summary) Summary { - return Summary{orig} +func newSummary(orig *otlpmetrics.Summary, state *internal.State) Summary { + return Summary{orig: orig, state: state} } // NewSummary creates a new empty Summary. @@ -30,22 +32,26 @@ func newSummary(orig *otlpmetrics.Summary) Summary { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewSummary() Summary { - return newSummary(&otlpmetrics.Summary{}) + state := internal.StateMutable + return newSummary(&otlpmetrics.Summary{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms Summary) MoveTo(dest Summary) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.Summary{} } // DataPoints returns the DataPoints associated with this Summary. func (ms Summary) DataPoints() SummaryDataPointSlice { - return newSummaryDataPointSlice(&ms.orig.DataPoints) + return newSummaryDataPointSlice(&ms.orig.DataPoints, ms.state) } // CopyTo copies all properties from the current struct overriding the destination. func (ms Summary) CopyTo(dest Summary) { + dest.state.AssertMutable() ms.DataPoints().CopyTo(dest.DataPoints()) } diff --git a/pdata/pmetric/generated_summary_test.go b/pdata/pmetric/generated_summary_test.go index 2f81ead8807..c592870ef8b 100644 --- a/pdata/pmetric/generated_summary_test.go +++ b/pdata/pmetric/generated_summary_test.go @@ -10,6 +10,9 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/pdata/internal" + otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) func TestSummary_MoveTo(t *testing.T) { @@ -18,6 +21,9 @@ func TestSummary_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewSummary(), ms) assert.Equal(t, generateTestSummary(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newSummary(&otlpmetrics.Summary{}, &sharedState)) }) + assert.Panics(t, func() { newSummary(&otlpmetrics.Summary{}, &sharedState).MoveTo(dest) }) } func TestSummary_CopyTo(t *testing.T) { @@ -28,6 +34,8 @@ func TestSummary_CopyTo(t *testing.T) { orig = generateTestSummary() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newSummary(&otlpmetrics.Summary{}, &sharedState)) }) } func TestSummary_DataPoints(t *testing.T) { @@ -44,5 +52,5 @@ func generateTestSummary() Summary { } func fillTestSummary(tv Summary) { - fillTestSummaryDataPointSlice(newSummaryDataPointSlice(&tv.orig.DataPoints)) + fillTestSummaryDataPointSlice(newSummaryDataPointSlice(&tv.orig.DataPoints, tv.state)) } diff --git a/pdata/pmetric/generated_summarydatapoint.go b/pdata/pmetric/generated_summarydatapoint.go index 51177d69cbd..0f0f6dd1e99 100644 --- a/pdata/pmetric/generated_summarydatapoint.go +++ b/pdata/pmetric/generated_summarydatapoint.go @@ -20,11 +20,12 @@ import ( // Must use NewSummaryDataPoint function to create new instances. // Important: zero-initialized instance is not valid for use. type SummaryDataPoint struct { - orig *otlpmetrics.SummaryDataPoint + orig *otlpmetrics.SummaryDataPoint + state *internal.State } -func newSummaryDataPoint(orig *otlpmetrics.SummaryDataPoint) SummaryDataPoint { - return SummaryDataPoint{orig} +func newSummaryDataPoint(orig *otlpmetrics.SummaryDataPoint, state *internal.State) SummaryDataPoint { + return SummaryDataPoint{orig: orig, state: state} } // NewSummaryDataPoint creates a new empty SummaryDataPoint. @@ -32,19 +33,22 @@ func newSummaryDataPoint(orig *otlpmetrics.SummaryDataPoint) SummaryDataPoint { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewSummaryDataPoint() SummaryDataPoint { - return newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{}) + state := internal.StateMutable + return newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms SummaryDataPoint) MoveTo(dest SummaryDataPoint) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.SummaryDataPoint{} } // Attributes returns the Attributes associated with this SummaryDataPoint. func (ms SummaryDataPoint) Attributes() pcommon.Map { - return pcommon.Map(internal.NewMap(&ms.orig.Attributes)) + return pcommon.Map(internal.NewMap(&ms.orig.Attributes, ms.state)) } // StartTimestamp returns the starttimestamp associated with this SummaryDataPoint. @@ -54,6 +58,7 @@ func (ms SummaryDataPoint) StartTimestamp() pcommon.Timestamp { // SetStartTimestamp replaces the starttimestamp associated with this SummaryDataPoint. func (ms SummaryDataPoint) SetStartTimestamp(v pcommon.Timestamp) { + ms.state.AssertMutable() ms.orig.StartTimeUnixNano = uint64(v) } @@ -64,6 +69,7 @@ func (ms SummaryDataPoint) Timestamp() pcommon.Timestamp { // SetTimestamp replaces the timestamp associated with this SummaryDataPoint. func (ms SummaryDataPoint) SetTimestamp(v pcommon.Timestamp) { + ms.state.AssertMutable() ms.orig.TimeUnixNano = uint64(v) } @@ -74,6 +80,7 @@ func (ms SummaryDataPoint) Count() uint64 { // SetCount replaces the count associated with this SummaryDataPoint. func (ms SummaryDataPoint) SetCount(v uint64) { + ms.state.AssertMutable() ms.orig.Count = v } @@ -84,12 +91,13 @@ func (ms SummaryDataPoint) Sum() float64 { // SetSum replaces the sum associated with this SummaryDataPoint. func (ms SummaryDataPoint) SetSum(v float64) { + ms.state.AssertMutable() ms.orig.Sum = v } // QuantileValues returns the QuantileValues associated with this SummaryDataPoint. func (ms SummaryDataPoint) QuantileValues() SummaryDataPointValueAtQuantileSlice { - return newSummaryDataPointValueAtQuantileSlice(&ms.orig.QuantileValues) + return newSummaryDataPointValueAtQuantileSlice(&ms.orig.QuantileValues, ms.state) } // Flags returns the flags associated with this SummaryDataPoint. @@ -99,11 +107,13 @@ func (ms SummaryDataPoint) Flags() DataPointFlags { // SetFlags replaces the flags associated with this SummaryDataPoint. func (ms SummaryDataPoint) SetFlags(v DataPointFlags) { + ms.state.AssertMutable() ms.orig.Flags = uint32(v) } // CopyTo copies all properties from the current struct overriding the destination. func (ms SummaryDataPoint) CopyTo(dest SummaryDataPoint) { + dest.state.AssertMutable() ms.Attributes().CopyTo(dest.Attributes()) dest.SetStartTimestamp(ms.StartTimestamp()) dest.SetTimestamp(ms.Timestamp()) diff --git a/pdata/pmetric/generated_summarydatapoint_test.go b/pdata/pmetric/generated_summarydatapoint_test.go index b82d6104991..fce1e638d41 100644 --- a/pdata/pmetric/generated_summarydatapoint_test.go +++ b/pdata/pmetric/generated_summarydatapoint_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/pdata/internal" + otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -21,6 +22,9 @@ func TestSummaryDataPoint_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewSummaryDataPoint(), ms) assert.Equal(t, generateTestSummaryDataPoint(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{}, &sharedState)) }) + assert.Panics(t, func() { newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{}, &sharedState).MoveTo(dest) }) } func TestSummaryDataPoint_CopyTo(t *testing.T) { @@ -31,6 +35,8 @@ func TestSummaryDataPoint_CopyTo(t *testing.T) { orig = generateTestSummaryDataPoint() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{}, &sharedState)) }) } func TestSummaryDataPoint_Attributes(t *testing.T) { @@ -61,6 +67,8 @@ func TestSummaryDataPoint_Count(t *testing.T) { assert.Equal(t, uint64(0), ms.Count()) ms.SetCount(uint64(17)) assert.Equal(t, uint64(17), ms.Count()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{}, &sharedState).SetCount(uint64(17)) }) } func TestSummaryDataPoint_Sum(t *testing.T) { @@ -68,6 +76,8 @@ func TestSummaryDataPoint_Sum(t *testing.T) { assert.Equal(t, float64(0.0), ms.Sum()) ms.SetSum(float64(17.13)) assert.Equal(t, float64(17.13), ms.Sum()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{}, &sharedState).SetSum(float64(17.13)) }) } func TestSummaryDataPoint_QuantileValues(t *testing.T) { @@ -92,11 +102,11 @@ func generateTestSummaryDataPoint() SummaryDataPoint { } func fillTestSummaryDataPoint(tv SummaryDataPoint) { - internal.FillTestMap(internal.NewMap(&tv.orig.Attributes)) + internal.FillTestMap(internal.NewMap(&tv.orig.Attributes, tv.state)) tv.orig.StartTimeUnixNano = 1234567890 tv.orig.TimeUnixNano = 1234567890 tv.orig.Count = uint64(17) tv.orig.Sum = float64(17.13) - fillTestSummaryDataPointValueAtQuantileSlice(newSummaryDataPointValueAtQuantileSlice(&tv.orig.QuantileValues)) + fillTestSummaryDataPointValueAtQuantileSlice(newSummaryDataPointValueAtQuantileSlice(&tv.orig.QuantileValues, tv.state)) tv.orig.Flags = 1 } diff --git a/pdata/pmetric/generated_summarydatapointslice.go b/pdata/pmetric/generated_summarydatapointslice.go index 57e895e3265..f915500963f 100644 --- a/pdata/pmetric/generated_summarydatapointslice.go +++ b/pdata/pmetric/generated_summarydatapointslice.go @@ -9,6 +9,7 @@ package pmetric import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewSummaryDataPointSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type SummaryDataPointSlice struct { - orig *[]*otlpmetrics.SummaryDataPoint + orig *[]*otlpmetrics.SummaryDataPoint + state *internal.State } -func newSummaryDataPointSlice(orig *[]*otlpmetrics.SummaryDataPoint) SummaryDataPointSlice { - return SummaryDataPointSlice{orig} +func newSummaryDataPointSlice(orig *[]*otlpmetrics.SummaryDataPoint, state *internal.State) SummaryDataPointSlice { + return SummaryDataPointSlice{orig: orig, state: state} } // NewSummaryDataPointSlice creates a SummaryDataPointSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewSummaryDataPointSlice() SummaryDataPointSlice { orig := []*otlpmetrics.SummaryDataPoint(nil) - return newSummaryDataPointSlice(&orig) + state := internal.StateMutable + return newSummaryDataPointSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es SummaryDataPointSlice) Len() int { // ... // Do something with the element // } func (es SummaryDataPointSlice) At(i int) SummaryDataPoint { - return newSummaryDataPoint((*es.orig)[i]) + return newSummaryDataPoint((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es SummaryDataPointSlice) At(i int) SummaryDataPoint { // // Here should set all the values for e. // } func (es SummaryDataPointSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es SummaryDataPointSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty SummaryDataPoint. // It returns the newly added SummaryDataPoint. func (es SummaryDataPointSlice) AppendEmpty() SummaryDataPoint { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlpmetrics.SummaryDataPoint{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es SummaryDataPointSlice) AppendEmpty() SummaryDataPoint { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es SummaryDataPointSlice) MoveAndAppendTo(dest SummaryDataPointSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es SummaryDataPointSlice) MoveAndAppendTo(dest SummaryDataPointSlice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es SummaryDataPointSlice) RemoveIf(f func(SummaryDataPoint) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es SummaryDataPointSlice) RemoveIf(f func(SummaryDataPoint) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es SummaryDataPointSlice) CopyTo(dest SummaryDataPointSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newSummaryDataPoint((*es.orig)[i]).CopyTo(newSummaryDataPoint((*dest.orig)[i])) + newSummaryDataPoint((*es.orig)[i], es.state).CopyTo(newSummaryDataPoint((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es SummaryDataPointSlice) CopyTo(dest SummaryDataPointSlice) { wrappers := make([]*otlpmetrics.SummaryDataPoint, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newSummaryDataPoint((*es.orig)[i]).CopyTo(newSummaryDataPoint(wrappers[i])) + newSummaryDataPoint((*es.orig)[i], es.state).CopyTo(newSummaryDataPoint(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es SummaryDataPointSlice) CopyTo(dest SummaryDataPointSlice) { // provided less function so that two instances of SummaryDataPointSlice // can be compared. func (es SummaryDataPointSlice) Sort(less func(a, b SummaryDataPoint) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/pmetric/generated_summarydatapointslice_test.go b/pdata/pmetric/generated_summarydatapointslice_test.go index 3c917e4bfb4..10a12b45e5a 100644 --- a/pdata/pmetric/generated_summarydatapointslice_test.go +++ b/pdata/pmetric/generated_summarydatapointslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) func TestSummaryDataPointSlice(t *testing.T) { es := NewSummaryDataPointSlice() assert.Equal(t, 0, es.Len()) - es = newSummaryDataPointSlice(&[]*otlpmetrics.SummaryDataPoint{}) + state := internal.StateMutable + es = newSummaryDataPointSlice(&[]*otlpmetrics.SummaryDataPoint{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewSummaryDataPoint() @@ -32,6 +34,19 @@ func TestSummaryDataPointSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestSummaryDataPointSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newSummaryDataPointSlice(&[]*otlpmetrics.SummaryDataPoint{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewSummaryDataPointSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestSummaryDataPointSlice_CopyTo(t *testing.T) { dest := NewSummaryDataPointSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestSummaryDataPointSlice(es SummaryDataPointSlice) { *es.orig = make([]*otlpmetrics.SummaryDataPoint, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlpmetrics.SummaryDataPoint{} - fillTestSummaryDataPoint(newSummaryDataPoint((*es.orig)[i])) + fillTestSummaryDataPoint(newSummaryDataPoint((*es.orig)[i], es.state)) } } diff --git a/pdata/pmetric/generated_summarydatapointvalueatquantile.go b/pdata/pmetric/generated_summarydatapointvalueatquantile.go index c32d24d1d11..b4e1fe08f7b 100644 --- a/pdata/pmetric/generated_summarydatapointvalueatquantile.go +++ b/pdata/pmetric/generated_summarydatapointvalueatquantile.go @@ -7,6 +7,7 @@ package pmetric import ( + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -18,11 +19,12 @@ import ( // Must use NewSummaryDataPointValueAtQuantile function to create new instances. // Important: zero-initialized instance is not valid for use. type SummaryDataPointValueAtQuantile struct { - orig *otlpmetrics.SummaryDataPoint_ValueAtQuantile + orig *otlpmetrics.SummaryDataPoint_ValueAtQuantile + state *internal.State } -func newSummaryDataPointValueAtQuantile(orig *otlpmetrics.SummaryDataPoint_ValueAtQuantile) SummaryDataPointValueAtQuantile { - return SummaryDataPointValueAtQuantile{orig} +func newSummaryDataPointValueAtQuantile(orig *otlpmetrics.SummaryDataPoint_ValueAtQuantile, state *internal.State) SummaryDataPointValueAtQuantile { + return SummaryDataPointValueAtQuantile{orig: orig, state: state} } // NewSummaryDataPointValueAtQuantile creates a new empty SummaryDataPointValueAtQuantile. @@ -30,12 +32,15 @@ func newSummaryDataPointValueAtQuantile(orig *otlpmetrics.SummaryDataPoint_Value // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewSummaryDataPointValueAtQuantile() SummaryDataPointValueAtQuantile { - return newSummaryDataPointValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{}) + state := internal.StateMutable + return newSummaryDataPointValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms SummaryDataPointValueAtQuantile) MoveTo(dest SummaryDataPointValueAtQuantile) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpmetrics.SummaryDataPoint_ValueAtQuantile{} } @@ -47,6 +52,7 @@ func (ms SummaryDataPointValueAtQuantile) Quantile() float64 { // SetQuantile replaces the quantile associated with this SummaryDataPointValueAtQuantile. func (ms SummaryDataPointValueAtQuantile) SetQuantile(v float64) { + ms.state.AssertMutable() ms.orig.Quantile = v } @@ -57,11 +63,13 @@ func (ms SummaryDataPointValueAtQuantile) Value() float64 { // SetValue replaces the value associated with this SummaryDataPointValueAtQuantile. func (ms SummaryDataPointValueAtQuantile) SetValue(v float64) { + ms.state.AssertMutable() ms.orig.Value = v } // CopyTo copies all properties from the current struct overriding the destination. func (ms SummaryDataPointValueAtQuantile) CopyTo(dest SummaryDataPointValueAtQuantile) { + dest.state.AssertMutable() dest.SetQuantile(ms.Quantile()) dest.SetValue(ms.Value()) } diff --git a/pdata/pmetric/generated_summarydatapointvalueatquantile_test.go b/pdata/pmetric/generated_summarydatapointvalueatquantile_test.go index 7b0510c5da1..2dd02c799cf 100644 --- a/pdata/pmetric/generated_summarydatapointvalueatquantile_test.go +++ b/pdata/pmetric/generated_summarydatapointvalueatquantile_test.go @@ -10,6 +10,9 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/pdata/internal" + otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) func TestSummaryDataPointValueAtQuantile_MoveTo(t *testing.T) { @@ -18,6 +21,13 @@ func TestSummaryDataPointValueAtQuantile_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewSummaryDataPointValueAtQuantile(), ms) assert.Equal(t, generateTestSummaryDataPointValueAtQuantile(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + ms.MoveTo(newSummaryDataPointValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{}, &sharedState)) + }) + assert.Panics(t, func() { + newSummaryDataPointValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{}, &sharedState).MoveTo(dest) + }) } func TestSummaryDataPointValueAtQuantile_CopyTo(t *testing.T) { @@ -28,6 +38,10 @@ func TestSummaryDataPointValueAtQuantile_CopyTo(t *testing.T) { orig = generateTestSummaryDataPointValueAtQuantile() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + ms.CopyTo(newSummaryDataPointValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{}, &sharedState)) + }) } func TestSummaryDataPointValueAtQuantile_Quantile(t *testing.T) { @@ -35,6 +49,10 @@ func TestSummaryDataPointValueAtQuantile_Quantile(t *testing.T) { assert.Equal(t, float64(0.0), ms.Quantile()) ms.SetQuantile(float64(17.13)) assert.Equal(t, float64(17.13), ms.Quantile()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newSummaryDataPointValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{}, &sharedState).SetQuantile(float64(17.13)) + }) } func TestSummaryDataPointValueAtQuantile_Value(t *testing.T) { @@ -42,6 +60,10 @@ func TestSummaryDataPointValueAtQuantile_Value(t *testing.T) { assert.Equal(t, float64(0.0), ms.Value()) ms.SetValue(float64(17.13)) assert.Equal(t, float64(17.13), ms.Value()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newSummaryDataPointValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{}, &sharedState).SetValue(float64(17.13)) + }) } func generateTestSummaryDataPointValueAtQuantile() SummaryDataPointValueAtQuantile { diff --git a/pdata/pmetric/generated_summarydatapointvalueatquantileslice.go b/pdata/pmetric/generated_summarydatapointvalueatquantileslice.go index 3c424944b6a..ed899050ac6 100644 --- a/pdata/pmetric/generated_summarydatapointvalueatquantileslice.go +++ b/pdata/pmetric/generated_summarydatapointvalueatquantileslice.go @@ -9,6 +9,7 @@ package pmetric import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewSummaryDataPointValueAtQuantileSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type SummaryDataPointValueAtQuantileSlice struct { - orig *[]*otlpmetrics.SummaryDataPoint_ValueAtQuantile + orig *[]*otlpmetrics.SummaryDataPoint_ValueAtQuantile + state *internal.State } -func newSummaryDataPointValueAtQuantileSlice(orig *[]*otlpmetrics.SummaryDataPoint_ValueAtQuantile) SummaryDataPointValueAtQuantileSlice { - return SummaryDataPointValueAtQuantileSlice{orig} +func newSummaryDataPointValueAtQuantileSlice(orig *[]*otlpmetrics.SummaryDataPoint_ValueAtQuantile, state *internal.State) SummaryDataPointValueAtQuantileSlice { + return SummaryDataPointValueAtQuantileSlice{orig: orig, state: state} } // NewSummaryDataPointValueAtQuantileSlice creates a SummaryDataPointValueAtQuantileSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewSummaryDataPointValueAtQuantileSlice() SummaryDataPointValueAtQuantileSlice { orig := []*otlpmetrics.SummaryDataPoint_ValueAtQuantile(nil) - return newSummaryDataPointValueAtQuantileSlice(&orig) + state := internal.StateMutable + return newSummaryDataPointValueAtQuantileSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es SummaryDataPointValueAtQuantileSlice) Len() int { // ... // Do something with the element // } func (es SummaryDataPointValueAtQuantileSlice) At(i int) SummaryDataPointValueAtQuantile { - return newSummaryDataPointValueAtQuantile((*es.orig)[i]) + return newSummaryDataPointValueAtQuantile((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es SummaryDataPointValueAtQuantileSlice) At(i int) SummaryDataPointValueAt // // Here should set all the values for e. // } func (es SummaryDataPointValueAtQuantileSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es SummaryDataPointValueAtQuantileSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty SummaryDataPointValueAtQuantile. // It returns the newly added SummaryDataPointValueAtQuantile. func (es SummaryDataPointValueAtQuantileSlice) AppendEmpty() SummaryDataPointValueAtQuantile { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlpmetrics.SummaryDataPoint_ValueAtQuantile{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es SummaryDataPointValueAtQuantileSlice) AppendEmpty() SummaryDataPointVal // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es SummaryDataPointValueAtQuantileSlice) MoveAndAppendTo(dest SummaryDataPointValueAtQuantileSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es SummaryDataPointValueAtQuantileSlice) MoveAndAppendTo(dest SummaryDataP // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es SummaryDataPointValueAtQuantileSlice) RemoveIf(f func(SummaryDataPointValueAtQuantile) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es SummaryDataPointValueAtQuantileSlice) RemoveIf(f func(SummaryDataPointV (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es SummaryDataPointValueAtQuantileSlice) CopyTo(dest SummaryDataPointValueAtQuantileSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newSummaryDataPointValueAtQuantile((*es.orig)[i]).CopyTo(newSummaryDataPointValueAtQuantile((*dest.orig)[i])) + newSummaryDataPointValueAtQuantile((*es.orig)[i], es.state).CopyTo(newSummaryDataPointValueAtQuantile((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es SummaryDataPointValueAtQuantileSlice) CopyTo(dest SummaryDataPointValue wrappers := make([]*otlpmetrics.SummaryDataPoint_ValueAtQuantile, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newSummaryDataPointValueAtQuantile((*es.orig)[i]).CopyTo(newSummaryDataPointValueAtQuantile(wrappers[i])) + newSummaryDataPointValueAtQuantile((*es.orig)[i], es.state).CopyTo(newSummaryDataPointValueAtQuantile(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es SummaryDataPointValueAtQuantileSlice) CopyTo(dest SummaryDataPointValue // provided less function so that two instances of SummaryDataPointValueAtQuantileSlice // can be compared. func (es SummaryDataPointValueAtQuantileSlice) Sort(less func(a, b SummaryDataPointValueAtQuantile) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/pmetric/generated_summarydatapointvalueatquantileslice_test.go b/pdata/pmetric/generated_summarydatapointvalueatquantileslice_test.go index 20f7c439efe..5ad949f10d1 100644 --- a/pdata/pmetric/generated_summarydatapointvalueatquantileslice_test.go +++ b/pdata/pmetric/generated_summarydatapointvalueatquantileslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" ) func TestSummaryDataPointValueAtQuantileSlice(t *testing.T) { es := NewSummaryDataPointValueAtQuantileSlice() assert.Equal(t, 0, es.Len()) - es = newSummaryDataPointValueAtQuantileSlice(&[]*otlpmetrics.SummaryDataPoint_ValueAtQuantile{}) + state := internal.StateMutable + es = newSummaryDataPointValueAtQuantileSlice(&[]*otlpmetrics.SummaryDataPoint_ValueAtQuantile{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewSummaryDataPointValueAtQuantile() @@ -32,6 +34,19 @@ func TestSummaryDataPointValueAtQuantileSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestSummaryDataPointValueAtQuantileSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newSummaryDataPointValueAtQuantileSlice(&[]*otlpmetrics.SummaryDataPoint_ValueAtQuantile{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewSummaryDataPointValueAtQuantileSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestSummaryDataPointValueAtQuantileSlice_CopyTo(t *testing.T) { dest := NewSummaryDataPointValueAtQuantileSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestSummaryDataPointValueAtQuantileSlice(es SummaryDataPointValueAtQuan *es.orig = make([]*otlpmetrics.SummaryDataPoint_ValueAtQuantile, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlpmetrics.SummaryDataPoint_ValueAtQuantile{} - fillTestSummaryDataPointValueAtQuantile(newSummaryDataPointValueAtQuantile((*es.orig)[i])) + fillTestSummaryDataPointValueAtQuantile(newSummaryDataPointValueAtQuantile((*es.orig)[i], es.state)) } } diff --git a/pdata/pmetric/json.go b/pdata/pmetric/json.go index 3df234c2000..c8b76b0e6ec 100644 --- a/pdata/pmetric/json.go +++ b/pdata/pmetric/json.go @@ -17,8 +17,10 @@ import ( var _ Marshaler = (*JSONMarshaler)(nil) +// JSONMarshaler marshals pdata.Metrics to JSON bytes using the OTLP/JSON format. type JSONMarshaler struct{} +// MarshalMetrics to the OTLP/JSON format. func (*JSONMarshaler) MarshalMetrics(md Metrics) ([]byte, error) { buf := bytes.Buffer{} pb := internal.MetricsToProto(internal.Metrics(md)) @@ -26,8 +28,10 @@ func (*JSONMarshaler) MarshalMetrics(md Metrics) ([]byte, error) { return buf.Bytes(), err } +// JSONUnmarshaler unmarshals OTLP/JSON formatted-bytes to pdata.Metrics. type JSONUnmarshaler struct{} +// UnmarshalMetrics from OTLP/JSON format into pdata.Metrics. func (*JSONUnmarshaler) UnmarshalMetrics(buf []byte) (Metrics, error) { iter := jsoniter.ConfigFastest.BorrowIterator(buf) defer jsoniter.ConfigFastest.ReturnIterator(iter) @@ -44,7 +48,7 @@ func (ms Metrics) unmarshalJsoniter(iter *jsoniter.Iterator) { iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { switch f { case "resource_metrics", "resourceMetrics": - iter.ReadArrayCB(func(iterator *jsoniter.Iterator) bool { + iter.ReadArrayCB(func(*jsoniter.Iterator) bool { ms.ResourceMetrics().AppendEmpty().unmarshalJsoniter(iter) return true }) diff --git a/pdata/pmetric/metrics.go b/pdata/pmetric/metrics.go index d72997a1bc4..91195ca4dfa 100644 --- a/pdata/pmetric/metrics.go +++ b/pdata/pmetric/metrics.go @@ -13,18 +13,28 @@ import ( type Metrics internal.Metrics func newMetrics(orig *otlpcollectormetrics.ExportMetricsServiceRequest) Metrics { - return Metrics(internal.NewMetrics(orig)) + state := internal.StateMutable + return Metrics(internal.NewMetrics(orig, &state)) } func (ms Metrics) getOrig() *otlpcollectormetrics.ExportMetricsServiceRequest { return internal.GetOrigMetrics(internal.Metrics(ms)) } +func (ms Metrics) getState() *internal.State { + return internal.GetMetricsState(internal.Metrics(ms)) +} + // NewMetrics creates a new Metrics struct. func NewMetrics() Metrics { return newMetrics(&otlpcollectormetrics.ExportMetricsServiceRequest{}) } +// IsReadOnly returns true if this Metrics instance is read-only. +func (ms Metrics) IsReadOnly() bool { + return *ms.getState() == internal.StateReadOnly +} + // CopyTo copies the Metrics instance overriding the destination. func (ms Metrics) CopyTo(dest Metrics) { ms.ResourceMetrics().CopyTo(dest.ResourceMetrics()) @@ -32,7 +42,7 @@ func (ms Metrics) CopyTo(dest Metrics) { // ResourceMetrics returns the ResourceMetricsSlice associated with this Metrics. func (ms Metrics) ResourceMetrics() ResourceMetricsSlice { - return newResourceMetricsSlice(&ms.getOrig().ResourceMetrics) + return newResourceMetricsSlice(&ms.getOrig().ResourceMetrics, internal.GetMetricsState(internal.Metrics(ms))) } // MetricCount calculates the total number of metrics. @@ -78,3 +88,8 @@ func (ms Metrics) DataPointCount() (dataPointCount int) { } return } + +// MarkReadOnly marks the Metrics as shared so that no further modifications can be done on it. +func (ms Metrics) MarkReadOnly() { + internal.SetMetricsState(internal.Metrics(ms), internal.StateReadOnly) +} diff --git a/pdata/pmetric/metrics_test.go b/pdata/pmetric/metrics_test.go index 811123aa00f..3c059643a84 100644 --- a/pdata/pmetric/metrics_test.go +++ b/pdata/pmetric/metrics_test.go @@ -5,6 +5,7 @@ package pmetric import ( "testing" + "time" gogoproto "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/assert" @@ -635,6 +636,16 @@ func TestMetricsCopyTo(t *testing.T) { assert.EqualValues(t, metrics, metricsCopy) } +func TestReadOnlyMetricsInvalidUsage(t *testing.T) { + metrics := NewMetrics() + assert.False(t, metrics.IsReadOnly()) + res := metrics.ResourceMetrics().AppendEmpty().Resource() + res.Attributes().PutStr("k1", "v1") + metrics.MarkReadOnly() + assert.True(t, metrics.IsReadOnly()) + assert.Panics(t, func() { res.Attributes().PutStr("k2", "v2") }) +} + func BenchmarkOtlpToFromInternal_PassThrough(b *testing.B) { req := &otlpcollectormetrics.ExportMetricsServiceRequest{ ResourceMetrics: []*otlpmetrics.ResourceMetrics{ @@ -931,3 +942,57 @@ func generateMetricsEmptyDataPoints() Metrics { }, }) } + +func BenchmarkMetricsUsage(b *testing.B) { + metrics := NewMetrics() + fillTestResourceMetricsSlice(metrics.ResourceMetrics()) + + ts := pcommon.NewTimestampFromTime(time.Now()) + + b.ReportAllocs() + b.ResetTimer() + + for bb := 0; bb < b.N; bb++ { + for i := 0; i < metrics.ResourceMetrics().Len(); i++ { + rm := metrics.ResourceMetrics().At(i) + res := rm.Resource() + res.Attributes().PutStr("foo", "bar") + v, ok := res.Attributes().Get("foo") + assert.True(b, ok) + assert.Equal(b, "bar", v.Str()) + v.SetStr("new-bar") + assert.Equal(b, "new-bar", v.Str()) + res.Attributes().Remove("foo") + for j := 0; j < rm.ScopeMetrics().Len(); j++ { + sm := rm.ScopeMetrics().At(j) + for k := 0; k < sm.Metrics().Len(); k++ { + m := sm.Metrics().At(k) + m.SetName("new_metric_name") + assert.Equal(b, "new_metric_name", m.Name()) + assert.Equal(b, MetricTypeSum, m.Type()) + m.Sum().SetAggregationTemporality(AggregationTemporalityCumulative) + assert.Equal(b, AggregationTemporalityCumulative, m.Sum().AggregationTemporality()) + m.Sum().SetIsMonotonic(true) + assert.True(b, m.Sum().IsMonotonic()) + for l := 0; l < m.Sum().DataPoints().Len(); l++ { + dp := m.Sum().DataPoints().At(l) + dp.SetIntValue(123) + assert.Equal(b, int64(123), dp.IntValue()) + assert.Equal(b, NumberDataPointValueTypeInt, dp.ValueType()) + dp.SetStartTimestamp(ts) + assert.Equal(b, ts, dp.StartTimestamp()) + } + dp := m.Sum().DataPoints().AppendEmpty() + dp.Attributes().PutStr("foo", "bar") + dp.SetDoubleValue(123) + dp.SetStartTimestamp(ts) + dp.SetTimestamp(ts) + m.Sum().DataPoints().RemoveIf(func(dp NumberDataPoint) bool { + _, ok := dp.Attributes().Get("foo") + return ok + }) + } + } + } + } +} diff --git a/pdata/pmetric/package_test.go b/pdata/pmetric/package_test.go new file mode 100644 index 00000000000..c07f77b2217 --- /dev/null +++ b/pdata/pmetric/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package pmetric + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess.go b/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess.go index d528e6e8f46..60aa6a03e95 100644 --- a/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess.go +++ b/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess.go @@ -7,6 +7,7 @@ package pmetricotlp import ( + "go.opentelemetry.io/collector/pdata/internal" otlpcollectormetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/metrics/v1" ) @@ -18,11 +19,12 @@ import ( // Must use NewExportPartialSuccess function to create new instances. // Important: zero-initialized instance is not valid for use. type ExportPartialSuccess struct { - orig *otlpcollectormetrics.ExportMetricsPartialSuccess + orig *otlpcollectormetrics.ExportMetricsPartialSuccess + state *internal.State } -func newExportPartialSuccess(orig *otlpcollectormetrics.ExportMetricsPartialSuccess) ExportPartialSuccess { - return ExportPartialSuccess{orig} +func newExportPartialSuccess(orig *otlpcollectormetrics.ExportMetricsPartialSuccess, state *internal.State) ExportPartialSuccess { + return ExportPartialSuccess{orig: orig, state: state} } // NewExportPartialSuccess creates a new empty ExportPartialSuccess. @@ -30,12 +32,15 @@ func newExportPartialSuccess(orig *otlpcollectormetrics.ExportMetricsPartialSucc // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewExportPartialSuccess() ExportPartialSuccess { - return newExportPartialSuccess(&otlpcollectormetrics.ExportMetricsPartialSuccess{}) + state := internal.StateMutable + return newExportPartialSuccess(&otlpcollectormetrics.ExportMetricsPartialSuccess{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms ExportPartialSuccess) MoveTo(dest ExportPartialSuccess) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpcollectormetrics.ExportMetricsPartialSuccess{} } @@ -47,6 +52,7 @@ func (ms ExportPartialSuccess) RejectedDataPoints() int64 { // SetRejectedDataPoints replaces the rejecteddatapoints associated with this ExportPartialSuccess. func (ms ExportPartialSuccess) SetRejectedDataPoints(v int64) { + ms.state.AssertMutable() ms.orig.RejectedDataPoints = v } @@ -57,11 +63,13 @@ func (ms ExportPartialSuccess) ErrorMessage() string { // SetErrorMessage replaces the errormessage associated with this ExportPartialSuccess. func (ms ExportPartialSuccess) SetErrorMessage(v string) { + ms.state.AssertMutable() ms.orig.ErrorMessage = v } // CopyTo copies all properties from the current struct overriding the destination. func (ms ExportPartialSuccess) CopyTo(dest ExportPartialSuccess) { + dest.state.AssertMutable() dest.SetRejectedDataPoints(ms.RejectedDataPoints()) dest.SetErrorMessage(ms.ErrorMessage()) } diff --git a/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess_test.go b/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess_test.go index a351ba048fa..e6345f60413 100644 --- a/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess_test.go +++ b/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess_test.go @@ -10,6 +10,9 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/pdata/internal" + otlpcollectormetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/metrics/v1" ) func TestExportPartialSuccess_MoveTo(t *testing.T) { @@ -18,6 +21,13 @@ func TestExportPartialSuccess_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewExportPartialSuccess(), ms) assert.Equal(t, generateTestExportPartialSuccess(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + ms.MoveTo(newExportPartialSuccess(&otlpcollectormetrics.ExportMetricsPartialSuccess{}, &sharedState)) + }) + assert.Panics(t, func() { + newExportPartialSuccess(&otlpcollectormetrics.ExportMetricsPartialSuccess{}, &sharedState).MoveTo(dest) + }) } func TestExportPartialSuccess_CopyTo(t *testing.T) { @@ -28,6 +38,10 @@ func TestExportPartialSuccess_CopyTo(t *testing.T) { orig = generateTestExportPartialSuccess() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + ms.CopyTo(newExportPartialSuccess(&otlpcollectormetrics.ExportMetricsPartialSuccess{}, &sharedState)) + }) } func TestExportPartialSuccess_RejectedDataPoints(t *testing.T) { @@ -35,6 +49,10 @@ func TestExportPartialSuccess_RejectedDataPoints(t *testing.T) { assert.Equal(t, int64(0), ms.RejectedDataPoints()) ms.SetRejectedDataPoints(int64(13)) assert.Equal(t, int64(13), ms.RejectedDataPoints()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newExportPartialSuccess(&otlpcollectormetrics.ExportMetricsPartialSuccess{}, &sharedState).SetRejectedDataPoints(int64(13)) + }) } func TestExportPartialSuccess_ErrorMessage(t *testing.T) { @@ -42,6 +60,10 @@ func TestExportPartialSuccess_ErrorMessage(t *testing.T) { assert.Equal(t, "", ms.ErrorMessage()) ms.SetErrorMessage("error message") assert.Equal(t, "error message", ms.ErrorMessage()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newExportPartialSuccess(&otlpcollectormetrics.ExportMetricsPartialSuccess{}, &sharedState).SetErrorMessage("error message") + }) } func generateTestExportPartialSuccess() ExportPartialSuccess { diff --git a/pdata/pmetric/pmetricotlp/grpc.go b/pdata/pmetric/pmetricotlp/grpc.go index be9d946b3c8..98d864d7371 100644 --- a/pdata/pmetric/pmetricotlp/grpc.go +++ b/pdata/pmetric/pmetricotlp/grpc.go @@ -10,6 +10,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "go.opentelemetry.io/collector/pdata/internal" otlpcollectormetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/metrics/v1" "go.opentelemetry.io/collector/pdata/internal/otlp" ) @@ -39,7 +40,11 @@ type grpcClient struct { func (c *grpcClient) Export(ctx context.Context, request ExportRequest, opts ...grpc.CallOption) (ExportResponse, error) { rsp, err := c.rawClient.Export(ctx, request.orig, opts...) - return ExportResponse{orig: rsp}, err + if err != nil { + return ExportResponse{}, err + } + state := internal.StateMutable + return ExportResponse{orig: rsp, state: &state}, err } func (c *grpcClient) unexported() {} @@ -79,6 +84,7 @@ type rawMetricsServer struct { func (s rawMetricsServer) Export(ctx context.Context, request *otlpcollectormetrics.ExportMetricsServiceRequest) (*otlpcollectormetrics.ExportMetricsServiceResponse, error) { otlp.MigrateMetrics(request.ResourceMetrics) - rsp, err := s.srv.Export(ctx, ExportRequest{orig: request}) + state := internal.StateMutable + rsp, err := s.srv.Export(ctx, ExportRequest{orig: request, state: &state}) return rsp.orig, err } diff --git a/pdata/pmetric/pmetricotlp/package_test.go b/pdata/pmetric/pmetricotlp/package_test.go new file mode 100644 index 00000000000..f8191b76d55 --- /dev/null +++ b/pdata/pmetric/pmetricotlp/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package pmetricotlp + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/pdata/pmetric/pmetricotlp/request.go b/pdata/pmetric/pmetricotlp/request.go index 060b6e5bb07..4cca31a609f 100644 --- a/pdata/pmetric/pmetricotlp/request.go +++ b/pdata/pmetric/pmetricotlp/request.go @@ -17,19 +17,27 @@ var jsonUnmarshaler = &pmetric.JSONUnmarshaler{} // ExportRequest represents the request for gRPC/HTTP client/server. // It's a wrapper for pmetric.Metrics data. type ExportRequest struct { - orig *otlpcollectormetrics.ExportMetricsServiceRequest + orig *otlpcollectormetrics.ExportMetricsServiceRequest + state *internal.State } // NewExportRequest returns an empty ExportRequest. func NewExportRequest() ExportRequest { - return ExportRequest{orig: &otlpcollectormetrics.ExportMetricsServiceRequest{}} + state := internal.StateMutable + return ExportRequest{ + orig: &otlpcollectormetrics.ExportMetricsServiceRequest{}, + state: &state, + } } // NewExportRequestFromMetrics returns a ExportRequest from pmetric.Metrics. // Because ExportRequest is a wrapper for pmetric.Metrics, // any changes to the provided Metrics struct will be reflected in the ExportRequest and vice versa. func NewExportRequestFromMetrics(md pmetric.Metrics) ExportRequest { - return ExportRequest{orig: internal.GetOrigMetrics(internal.Metrics(md))} + return ExportRequest{ + orig: internal.GetOrigMetrics(internal.Metrics(md)), + state: internal.GetMetricsState(internal.Metrics(md)), + } } // MarshalProto marshals ExportRequest into proto bytes. @@ -62,5 +70,5 @@ func (ms ExportRequest) UnmarshalJSON(data []byte) error { } func (ms ExportRequest) Metrics() pmetric.Metrics { - return pmetric.Metrics(internal.NewMetrics(ms.orig)) + return pmetric.Metrics(internal.NewMetrics(ms.orig, ms.state)) } diff --git a/pdata/pmetric/pmetricotlp/response.go b/pdata/pmetric/pmetricotlp/response.go index 4e9d6bfe169..5942568ddb6 100644 --- a/pdata/pmetric/pmetricotlp/response.go +++ b/pdata/pmetric/pmetricotlp/response.go @@ -8,18 +8,24 @@ import ( jsoniter "github.com/json-iterator/go" + "go.opentelemetry.io/collector/pdata/internal" otlpcollectormetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/metrics/v1" "go.opentelemetry.io/collector/pdata/internal/json" ) // ExportResponse represents the response for gRPC/HTTP client/server. type ExportResponse struct { - orig *otlpcollectormetrics.ExportMetricsServiceResponse + orig *otlpcollectormetrics.ExportMetricsServiceResponse + state *internal.State } // NewExportResponse returns an empty ExportResponse. func NewExportResponse() ExportResponse { - return ExportResponse{orig: &otlpcollectormetrics.ExportMetricsServiceResponse{}} + state := internal.StateMutable + return ExportResponse{ + orig: &otlpcollectormetrics.ExportMetricsServiceResponse{}, + state: &state, + } } // MarshalProto marshals ExportResponse into proto bytes. @@ -51,7 +57,7 @@ func (ms ExportResponse) UnmarshalJSON(data []byte) error { // PartialSuccess returns the ExportLogsPartialSuccess associated with this ExportResponse. func (ms ExportResponse) PartialSuccess() ExportPartialSuccess { - return newExportPartialSuccess(&ms.orig.PartialSuccess) + return newExportPartialSuccess(&ms.orig.PartialSuccess, ms.state) } func (ms ExportResponse) unmarshalJsoniter(iter *jsoniter.Iterator) { @@ -67,7 +73,7 @@ func (ms ExportResponse) unmarshalJsoniter(iter *jsoniter.Iterator) { } func (ms ExportPartialSuccess) unmarshalJsoniter(iter *jsoniter.Iterator) { - iter.ReadObjectCB(func(iterator *jsoniter.Iterator, f string) bool { + iter.ReadObjectCB(func(_ *jsoniter.Iterator, f string) bool { switch f { case "rejected_data_points", "rejectedDataPoints": ms.orig.RejectedDataPoints = json.ReadInt64(iter) diff --git a/pdata/ptrace/generated_resourcespans.go b/pdata/ptrace/generated_resourcespans.go index b86cca53402..fc2ed01dbbc 100644 --- a/pdata/ptrace/generated_resourcespans.go +++ b/pdata/ptrace/generated_resourcespans.go @@ -20,11 +20,12 @@ import ( // Must use NewResourceSpans function to create new instances. // Important: zero-initialized instance is not valid for use. type ResourceSpans struct { - orig *otlptrace.ResourceSpans + orig *otlptrace.ResourceSpans + state *internal.State } -func newResourceSpans(orig *otlptrace.ResourceSpans) ResourceSpans { - return ResourceSpans{orig} +func newResourceSpans(orig *otlptrace.ResourceSpans, state *internal.State) ResourceSpans { + return ResourceSpans{orig: orig, state: state} } // NewResourceSpans creates a new empty ResourceSpans. @@ -32,19 +33,22 @@ func newResourceSpans(orig *otlptrace.ResourceSpans) ResourceSpans { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewResourceSpans() ResourceSpans { - return newResourceSpans(&otlptrace.ResourceSpans{}) + state := internal.StateMutable + return newResourceSpans(&otlptrace.ResourceSpans{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms ResourceSpans) MoveTo(dest ResourceSpans) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlptrace.ResourceSpans{} } // Resource returns the resource associated with this ResourceSpans. func (ms ResourceSpans) Resource() pcommon.Resource { - return pcommon.Resource(internal.NewResource(&ms.orig.Resource)) + return pcommon.Resource(internal.NewResource(&ms.orig.Resource, ms.state)) } // SchemaUrl returns the schemaurl associated with this ResourceSpans. @@ -54,16 +58,18 @@ func (ms ResourceSpans) SchemaUrl() string { // SetSchemaUrl replaces the schemaurl associated with this ResourceSpans. func (ms ResourceSpans) SetSchemaUrl(v string) { + ms.state.AssertMutable() ms.orig.SchemaUrl = v } // ScopeSpans returns the ScopeSpans associated with this ResourceSpans. func (ms ResourceSpans) ScopeSpans() ScopeSpansSlice { - return newScopeSpansSlice(&ms.orig.ScopeSpans) + return newScopeSpansSlice(&ms.orig.ScopeSpans, ms.state) } // CopyTo copies all properties from the current struct overriding the destination. func (ms ResourceSpans) CopyTo(dest ResourceSpans) { + dest.state.AssertMutable() ms.Resource().CopyTo(dest.Resource()) dest.SetSchemaUrl(ms.SchemaUrl()) ms.ScopeSpans().CopyTo(dest.ScopeSpans()) diff --git a/pdata/ptrace/generated_resourcespans_test.go b/pdata/ptrace/generated_resourcespans_test.go index 0fb248b3aba..2300c04f63e 100644 --- a/pdata/ptrace/generated_resourcespans_test.go +++ b/pdata/ptrace/generated_resourcespans_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/pdata/internal" + otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -21,6 +22,9 @@ func TestResourceSpans_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewResourceSpans(), ms) assert.Equal(t, generateTestResourceSpans(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newResourceSpans(&otlptrace.ResourceSpans{}, &sharedState)) }) + assert.Panics(t, func() { newResourceSpans(&otlptrace.ResourceSpans{}, &sharedState).MoveTo(dest) }) } func TestResourceSpans_CopyTo(t *testing.T) { @@ -31,6 +35,8 @@ func TestResourceSpans_CopyTo(t *testing.T) { orig = generateTestResourceSpans() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newResourceSpans(&otlptrace.ResourceSpans{}, &sharedState)) }) } func TestResourceSpans_Resource(t *testing.T) { @@ -44,6 +50,10 @@ func TestResourceSpans_SchemaUrl(t *testing.T) { assert.Equal(t, "", ms.SchemaUrl()) ms.SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0") assert.Equal(t, "https://opentelemetry.io/schemas/1.5.0", ms.SchemaUrl()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newResourceSpans(&otlptrace.ResourceSpans{}, &sharedState).SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0") + }) } func TestResourceSpans_ScopeSpans(t *testing.T) { @@ -60,7 +70,7 @@ func generateTestResourceSpans() ResourceSpans { } func fillTestResourceSpans(tv ResourceSpans) { - internal.FillTestResource(internal.NewResource(&tv.orig.Resource)) + internal.FillTestResource(internal.NewResource(&tv.orig.Resource, tv.state)) tv.orig.SchemaUrl = "https://opentelemetry.io/schemas/1.5.0" - fillTestScopeSpansSlice(newScopeSpansSlice(&tv.orig.ScopeSpans)) + fillTestScopeSpansSlice(newScopeSpansSlice(&tv.orig.ScopeSpans, tv.state)) } diff --git a/pdata/ptrace/generated_resourcespansslice.go b/pdata/ptrace/generated_resourcespansslice.go index 5c625fb781f..da79ef4a342 100644 --- a/pdata/ptrace/generated_resourcespansslice.go +++ b/pdata/ptrace/generated_resourcespansslice.go @@ -9,6 +9,7 @@ package ptrace import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewResourceSpansSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type ResourceSpansSlice struct { - orig *[]*otlptrace.ResourceSpans + orig *[]*otlptrace.ResourceSpans + state *internal.State } -func newResourceSpansSlice(orig *[]*otlptrace.ResourceSpans) ResourceSpansSlice { - return ResourceSpansSlice{orig} +func newResourceSpansSlice(orig *[]*otlptrace.ResourceSpans, state *internal.State) ResourceSpansSlice { + return ResourceSpansSlice{orig: orig, state: state} } // NewResourceSpansSlice creates a ResourceSpansSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewResourceSpansSlice() ResourceSpansSlice { orig := []*otlptrace.ResourceSpans(nil) - return newResourceSpansSlice(&orig) + state := internal.StateMutable + return newResourceSpansSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es ResourceSpansSlice) Len() int { // ... // Do something with the element // } func (es ResourceSpansSlice) At(i int) ResourceSpans { - return newResourceSpans((*es.orig)[i]) + return newResourceSpans((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es ResourceSpansSlice) At(i int) ResourceSpans { // // Here should set all the values for e. // } func (es ResourceSpansSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es ResourceSpansSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty ResourceSpans. // It returns the newly added ResourceSpans. func (es ResourceSpansSlice) AppendEmpty() ResourceSpans { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlptrace.ResourceSpans{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es ResourceSpansSlice) AppendEmpty() ResourceSpans { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es ResourceSpansSlice) MoveAndAppendTo(dest ResourceSpansSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es ResourceSpansSlice) MoveAndAppendTo(dest ResourceSpansSlice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es ResourceSpansSlice) RemoveIf(f func(ResourceSpans) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es ResourceSpansSlice) RemoveIf(f func(ResourceSpans) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es ResourceSpansSlice) CopyTo(dest ResourceSpansSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newResourceSpans((*es.orig)[i]).CopyTo(newResourceSpans((*dest.orig)[i])) + newResourceSpans((*es.orig)[i], es.state).CopyTo(newResourceSpans((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es ResourceSpansSlice) CopyTo(dest ResourceSpansSlice) { wrappers := make([]*otlptrace.ResourceSpans, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newResourceSpans((*es.orig)[i]).CopyTo(newResourceSpans(wrappers[i])) + newResourceSpans((*es.orig)[i], es.state).CopyTo(newResourceSpans(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es ResourceSpansSlice) CopyTo(dest ResourceSpansSlice) { // provided less function so that two instances of ResourceSpansSlice // can be compared. func (es ResourceSpansSlice) Sort(less func(a, b ResourceSpans) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/ptrace/generated_resourcespansslice_test.go b/pdata/ptrace/generated_resourcespansslice_test.go index db8e3b1c7e4..aa7bdf738a9 100644 --- a/pdata/ptrace/generated_resourcespansslice_test.go +++ b/pdata/ptrace/generated_resourcespansslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" ) func TestResourceSpansSlice(t *testing.T) { es := NewResourceSpansSlice() assert.Equal(t, 0, es.Len()) - es = newResourceSpansSlice(&[]*otlptrace.ResourceSpans{}) + state := internal.StateMutable + es = newResourceSpansSlice(&[]*otlptrace.ResourceSpans{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewResourceSpans() @@ -32,6 +34,19 @@ func TestResourceSpansSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestResourceSpansSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newResourceSpansSlice(&[]*otlptrace.ResourceSpans{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewResourceSpansSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestResourceSpansSlice_CopyTo(t *testing.T) { dest := NewResourceSpansSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestResourceSpansSlice(es ResourceSpansSlice) { *es.orig = make([]*otlptrace.ResourceSpans, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlptrace.ResourceSpans{} - fillTestResourceSpans(newResourceSpans((*es.orig)[i])) + fillTestResourceSpans(newResourceSpans((*es.orig)[i], es.state)) } } diff --git a/pdata/ptrace/generated_scopespans.go b/pdata/ptrace/generated_scopespans.go index 81926f24004..6ea0d82fd68 100644 --- a/pdata/ptrace/generated_scopespans.go +++ b/pdata/ptrace/generated_scopespans.go @@ -20,11 +20,12 @@ import ( // Must use NewScopeSpans function to create new instances. // Important: zero-initialized instance is not valid for use. type ScopeSpans struct { - orig *otlptrace.ScopeSpans + orig *otlptrace.ScopeSpans + state *internal.State } -func newScopeSpans(orig *otlptrace.ScopeSpans) ScopeSpans { - return ScopeSpans{orig} +func newScopeSpans(orig *otlptrace.ScopeSpans, state *internal.State) ScopeSpans { + return ScopeSpans{orig: orig, state: state} } // NewScopeSpans creates a new empty ScopeSpans. @@ -32,19 +33,22 @@ func newScopeSpans(orig *otlptrace.ScopeSpans) ScopeSpans { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewScopeSpans() ScopeSpans { - return newScopeSpans(&otlptrace.ScopeSpans{}) + state := internal.StateMutable + return newScopeSpans(&otlptrace.ScopeSpans{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms ScopeSpans) MoveTo(dest ScopeSpans) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlptrace.ScopeSpans{} } // Scope returns the scope associated with this ScopeSpans. func (ms ScopeSpans) Scope() pcommon.InstrumentationScope { - return pcommon.InstrumentationScope(internal.NewInstrumentationScope(&ms.orig.Scope)) + return pcommon.InstrumentationScope(internal.NewInstrumentationScope(&ms.orig.Scope, ms.state)) } // SchemaUrl returns the schemaurl associated with this ScopeSpans. @@ -54,16 +58,18 @@ func (ms ScopeSpans) SchemaUrl() string { // SetSchemaUrl replaces the schemaurl associated with this ScopeSpans. func (ms ScopeSpans) SetSchemaUrl(v string) { + ms.state.AssertMutable() ms.orig.SchemaUrl = v } // Spans returns the Spans associated with this ScopeSpans. func (ms ScopeSpans) Spans() SpanSlice { - return newSpanSlice(&ms.orig.Spans) + return newSpanSlice(&ms.orig.Spans, ms.state) } // CopyTo copies all properties from the current struct overriding the destination. func (ms ScopeSpans) CopyTo(dest ScopeSpans) { + dest.state.AssertMutable() ms.Scope().CopyTo(dest.Scope()) dest.SetSchemaUrl(ms.SchemaUrl()) ms.Spans().CopyTo(dest.Spans()) diff --git a/pdata/ptrace/generated_scopespans_test.go b/pdata/ptrace/generated_scopespans_test.go index c470e8f11fc..21b665aed27 100644 --- a/pdata/ptrace/generated_scopespans_test.go +++ b/pdata/ptrace/generated_scopespans_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/pdata/internal" + otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -21,6 +22,9 @@ func TestScopeSpans_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewScopeSpans(), ms) assert.Equal(t, generateTestScopeSpans(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newScopeSpans(&otlptrace.ScopeSpans{}, &sharedState)) }) + assert.Panics(t, func() { newScopeSpans(&otlptrace.ScopeSpans{}, &sharedState).MoveTo(dest) }) } func TestScopeSpans_CopyTo(t *testing.T) { @@ -31,6 +35,8 @@ func TestScopeSpans_CopyTo(t *testing.T) { orig = generateTestScopeSpans() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newScopeSpans(&otlptrace.ScopeSpans{}, &sharedState)) }) } func TestScopeSpans_Scope(t *testing.T) { @@ -44,6 +50,10 @@ func TestScopeSpans_SchemaUrl(t *testing.T) { assert.Equal(t, "", ms.SchemaUrl()) ms.SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0") assert.Equal(t, "https://opentelemetry.io/schemas/1.5.0", ms.SchemaUrl()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newScopeSpans(&otlptrace.ScopeSpans{}, &sharedState).SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0") + }) } func TestScopeSpans_Spans(t *testing.T) { @@ -60,7 +70,7 @@ func generateTestScopeSpans() ScopeSpans { } func fillTestScopeSpans(tv ScopeSpans) { - internal.FillTestInstrumentationScope(internal.NewInstrumentationScope(&tv.orig.Scope)) + internal.FillTestInstrumentationScope(internal.NewInstrumentationScope(&tv.orig.Scope, tv.state)) tv.orig.SchemaUrl = "https://opentelemetry.io/schemas/1.5.0" - fillTestSpanSlice(newSpanSlice(&tv.orig.Spans)) + fillTestSpanSlice(newSpanSlice(&tv.orig.Spans, tv.state)) } diff --git a/pdata/ptrace/generated_scopespansslice.go b/pdata/ptrace/generated_scopespansslice.go index 622d29be2c9..8fd0b4b8e99 100644 --- a/pdata/ptrace/generated_scopespansslice.go +++ b/pdata/ptrace/generated_scopespansslice.go @@ -9,6 +9,7 @@ package ptrace import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewScopeSpansSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type ScopeSpansSlice struct { - orig *[]*otlptrace.ScopeSpans + orig *[]*otlptrace.ScopeSpans + state *internal.State } -func newScopeSpansSlice(orig *[]*otlptrace.ScopeSpans) ScopeSpansSlice { - return ScopeSpansSlice{orig} +func newScopeSpansSlice(orig *[]*otlptrace.ScopeSpans, state *internal.State) ScopeSpansSlice { + return ScopeSpansSlice{orig: orig, state: state} } // NewScopeSpansSlice creates a ScopeSpansSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewScopeSpansSlice() ScopeSpansSlice { orig := []*otlptrace.ScopeSpans(nil) - return newScopeSpansSlice(&orig) + state := internal.StateMutable + return newScopeSpansSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es ScopeSpansSlice) Len() int { // ... // Do something with the element // } func (es ScopeSpansSlice) At(i int) ScopeSpans { - return newScopeSpans((*es.orig)[i]) + return newScopeSpans((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es ScopeSpansSlice) At(i int) ScopeSpans { // // Here should set all the values for e. // } func (es ScopeSpansSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es ScopeSpansSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty ScopeSpans. // It returns the newly added ScopeSpans. func (es ScopeSpansSlice) AppendEmpty() ScopeSpans { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlptrace.ScopeSpans{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es ScopeSpansSlice) AppendEmpty() ScopeSpans { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es ScopeSpansSlice) MoveAndAppendTo(dest ScopeSpansSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es ScopeSpansSlice) MoveAndAppendTo(dest ScopeSpansSlice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es ScopeSpansSlice) RemoveIf(f func(ScopeSpans) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es ScopeSpansSlice) RemoveIf(f func(ScopeSpans) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es ScopeSpansSlice) CopyTo(dest ScopeSpansSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newScopeSpans((*es.orig)[i]).CopyTo(newScopeSpans((*dest.orig)[i])) + newScopeSpans((*es.orig)[i], es.state).CopyTo(newScopeSpans((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es ScopeSpansSlice) CopyTo(dest ScopeSpansSlice) { wrappers := make([]*otlptrace.ScopeSpans, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newScopeSpans((*es.orig)[i]).CopyTo(newScopeSpans(wrappers[i])) + newScopeSpans((*es.orig)[i], es.state).CopyTo(newScopeSpans(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es ScopeSpansSlice) CopyTo(dest ScopeSpansSlice) { // provided less function so that two instances of ScopeSpansSlice // can be compared. func (es ScopeSpansSlice) Sort(less func(a, b ScopeSpans) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/ptrace/generated_scopespansslice_test.go b/pdata/ptrace/generated_scopespansslice_test.go index 950e481913c..1c3fa931bf1 100644 --- a/pdata/ptrace/generated_scopespansslice_test.go +++ b/pdata/ptrace/generated_scopespansslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" ) func TestScopeSpansSlice(t *testing.T) { es := NewScopeSpansSlice() assert.Equal(t, 0, es.Len()) - es = newScopeSpansSlice(&[]*otlptrace.ScopeSpans{}) + state := internal.StateMutable + es = newScopeSpansSlice(&[]*otlptrace.ScopeSpans{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewScopeSpans() @@ -32,6 +34,19 @@ func TestScopeSpansSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestScopeSpansSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newScopeSpansSlice(&[]*otlptrace.ScopeSpans{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewScopeSpansSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestScopeSpansSlice_CopyTo(t *testing.T) { dest := NewScopeSpansSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestScopeSpansSlice(es ScopeSpansSlice) { *es.orig = make([]*otlptrace.ScopeSpans, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlptrace.ScopeSpans{} - fillTestScopeSpans(newScopeSpans((*es.orig)[i])) + fillTestScopeSpans(newScopeSpans((*es.orig)[i], es.state)) } } diff --git a/pdata/ptrace/generated_span.go b/pdata/ptrace/generated_span.go index 6b76b7efd40..56a701974c4 100644 --- a/pdata/ptrace/generated_span.go +++ b/pdata/ptrace/generated_span.go @@ -22,11 +22,12 @@ import ( // Must use NewSpan function to create new instances. // Important: zero-initialized instance is not valid for use. type Span struct { - orig *otlptrace.Span + orig *otlptrace.Span + state *internal.State } -func newSpan(orig *otlptrace.Span) Span { - return Span{orig} +func newSpan(orig *otlptrace.Span, state *internal.State) Span { + return Span{orig: orig, state: state} } // NewSpan creates a new empty Span. @@ -34,12 +35,15 @@ func newSpan(orig *otlptrace.Span) Span { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewSpan() Span { - return newSpan(&otlptrace.Span{}) + state := internal.StateMutable + return newSpan(&otlptrace.Span{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms Span) MoveTo(dest Span) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlptrace.Span{} } @@ -51,6 +55,7 @@ func (ms Span) TraceID() pcommon.TraceID { // SetTraceID replaces the traceid associated with this Span. func (ms Span) SetTraceID(v pcommon.TraceID) { + ms.state.AssertMutable() ms.orig.TraceId = data.TraceID(v) } @@ -61,12 +66,13 @@ func (ms Span) SpanID() pcommon.SpanID { // SetSpanID replaces the spanid associated with this Span. func (ms Span) SetSpanID(v pcommon.SpanID) { + ms.state.AssertMutable() ms.orig.SpanId = data.SpanID(v) } // TraceState returns the tracestate associated with this Span. func (ms Span) TraceState() pcommon.TraceState { - return pcommon.TraceState(internal.NewTraceState(&ms.orig.TraceState)) + return pcommon.TraceState(internal.NewTraceState(&ms.orig.TraceState, ms.state)) } // ParentSpanID returns the parentspanid associated with this Span. @@ -76,6 +82,7 @@ func (ms Span) ParentSpanID() pcommon.SpanID { // SetParentSpanID replaces the parentspanid associated with this Span. func (ms Span) SetParentSpanID(v pcommon.SpanID) { + ms.state.AssertMutable() ms.orig.ParentSpanId = data.SpanID(v) } @@ -86,9 +93,21 @@ func (ms Span) Name() string { // SetName replaces the name associated with this Span. func (ms Span) SetName(v string) { + ms.state.AssertMutable() ms.orig.Name = v } +// Flags returns the flags associated with this Span. +func (ms Span) Flags() uint32 { + return ms.orig.Flags +} + +// SetFlags replaces the flags associated with this Span. +func (ms Span) SetFlags(v uint32) { + ms.state.AssertMutable() + ms.orig.Flags = v +} + // Kind returns the kind associated with this Span. func (ms Span) Kind() SpanKind { return SpanKind(ms.orig.Kind) @@ -96,6 +115,7 @@ func (ms Span) Kind() SpanKind { // SetKind replaces the kind associated with this Span. func (ms Span) SetKind(v SpanKind) { + ms.state.AssertMutable() ms.orig.Kind = otlptrace.Span_SpanKind(v) } @@ -106,6 +126,7 @@ func (ms Span) StartTimestamp() pcommon.Timestamp { // SetStartTimestamp replaces the starttimestamp associated with this Span. func (ms Span) SetStartTimestamp(v pcommon.Timestamp) { + ms.state.AssertMutable() ms.orig.StartTimeUnixNano = uint64(v) } @@ -116,12 +137,13 @@ func (ms Span) EndTimestamp() pcommon.Timestamp { // SetEndTimestamp replaces the endtimestamp associated with this Span. func (ms Span) SetEndTimestamp(v pcommon.Timestamp) { + ms.state.AssertMutable() ms.orig.EndTimeUnixNano = uint64(v) } // Attributes returns the Attributes associated with this Span. func (ms Span) Attributes() pcommon.Map { - return pcommon.Map(internal.NewMap(&ms.orig.Attributes)) + return pcommon.Map(internal.NewMap(&ms.orig.Attributes, ms.state)) } // DroppedAttributesCount returns the droppedattributescount associated with this Span. @@ -131,12 +153,13 @@ func (ms Span) DroppedAttributesCount() uint32 { // SetDroppedAttributesCount replaces the droppedattributescount associated with this Span. func (ms Span) SetDroppedAttributesCount(v uint32) { + ms.state.AssertMutable() ms.orig.DroppedAttributesCount = v } // Events returns the Events associated with this Span. func (ms Span) Events() SpanEventSlice { - return newSpanEventSlice(&ms.orig.Events) + return newSpanEventSlice(&ms.orig.Events, ms.state) } // DroppedEventsCount returns the droppedeventscount associated with this Span. @@ -146,12 +169,13 @@ func (ms Span) DroppedEventsCount() uint32 { // SetDroppedEventsCount replaces the droppedeventscount associated with this Span. func (ms Span) SetDroppedEventsCount(v uint32) { + ms.state.AssertMutable() ms.orig.DroppedEventsCount = v } // Links returns the Links associated with this Span. func (ms Span) Links() SpanLinkSlice { - return newSpanLinkSlice(&ms.orig.Links) + return newSpanLinkSlice(&ms.orig.Links, ms.state) } // DroppedLinksCount returns the droppedlinkscount associated with this Span. @@ -161,21 +185,24 @@ func (ms Span) DroppedLinksCount() uint32 { // SetDroppedLinksCount replaces the droppedlinkscount associated with this Span. func (ms Span) SetDroppedLinksCount(v uint32) { + ms.state.AssertMutable() ms.orig.DroppedLinksCount = v } // Status returns the status associated with this Span. func (ms Span) Status() Status { - return newStatus(&ms.orig.Status) + return newStatus(&ms.orig.Status, ms.state) } // CopyTo copies all properties from the current struct overriding the destination. func (ms Span) CopyTo(dest Span) { + dest.state.AssertMutable() dest.SetTraceID(ms.TraceID()) dest.SetSpanID(ms.SpanID()) ms.TraceState().CopyTo(dest.TraceState()) dest.SetParentSpanID(ms.ParentSpanID()) dest.SetName(ms.Name()) + dest.SetFlags(ms.Flags()) dest.SetKind(ms.Kind()) dest.SetStartTimestamp(ms.StartTimestamp()) dest.SetEndTimestamp(ms.EndTimestamp()) diff --git a/pdata/ptrace/generated_span_test.go b/pdata/ptrace/generated_span_test.go index b971dd3294a..1038d583066 100644 --- a/pdata/ptrace/generated_span_test.go +++ b/pdata/ptrace/generated_span_test.go @@ -23,6 +23,9 @@ func TestSpan_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewSpan(), ms) assert.Equal(t, generateTestSpan(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newSpan(&otlptrace.Span{}, &sharedState)) }) + assert.Panics(t, func() { newSpan(&otlptrace.Span{}, &sharedState).MoveTo(dest) }) } func TestSpan_CopyTo(t *testing.T) { @@ -33,6 +36,8 @@ func TestSpan_CopyTo(t *testing.T) { orig = generateTestSpan() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newSpan(&otlptrace.Span{}, &sharedState)) }) } func TestSpan_TraceID(t *testing.T) { @@ -70,6 +75,17 @@ func TestSpan_Name(t *testing.T) { assert.Equal(t, "", ms.Name()) ms.SetName("test_name") assert.Equal(t, "test_name", ms.Name()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newSpan(&otlptrace.Span{}, &sharedState).SetName("test_name") }) +} + +func TestSpan_Flags(t *testing.T) { + ms := NewSpan() + assert.Equal(t, uint32(0), ms.Flags()) + ms.SetFlags(uint32(0xf)) + assert.Equal(t, uint32(0xf), ms.Flags()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newSpan(&otlptrace.Span{}, &sharedState).SetFlags(uint32(0xf)) }) } func TestSpan_Kind(t *testing.T) { @@ -108,6 +124,8 @@ func TestSpan_DroppedAttributesCount(t *testing.T) { assert.Equal(t, uint32(0), ms.DroppedAttributesCount()) ms.SetDroppedAttributesCount(uint32(17)) assert.Equal(t, uint32(17), ms.DroppedAttributesCount()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newSpan(&otlptrace.Span{}, &sharedState).SetDroppedAttributesCount(uint32(17)) }) } func TestSpan_Events(t *testing.T) { @@ -122,6 +140,8 @@ func TestSpan_DroppedEventsCount(t *testing.T) { assert.Equal(t, uint32(0), ms.DroppedEventsCount()) ms.SetDroppedEventsCount(uint32(17)) assert.Equal(t, uint32(17), ms.DroppedEventsCount()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newSpan(&otlptrace.Span{}, &sharedState).SetDroppedEventsCount(uint32(17)) }) } func TestSpan_Links(t *testing.T) { @@ -136,6 +156,8 @@ func TestSpan_DroppedLinksCount(t *testing.T) { assert.Equal(t, uint32(0), ms.DroppedLinksCount()) ms.SetDroppedLinksCount(uint32(17)) assert.Equal(t, uint32(17), ms.DroppedLinksCount()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newSpan(&otlptrace.Span{}, &sharedState).SetDroppedLinksCount(uint32(17)) }) } func TestSpan_Status(t *testing.T) { @@ -153,17 +175,18 @@ func generateTestSpan() Span { func fillTestSpan(tv Span) { tv.orig.TraceId = data.TraceID([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1}) tv.orig.SpanId = data.SpanID([8]byte{8, 7, 6, 5, 4, 3, 2, 1}) - internal.FillTestTraceState(internal.NewTraceState(&tv.orig.TraceState)) + internal.FillTestTraceState(internal.NewTraceState(&tv.orig.TraceState, tv.state)) tv.orig.ParentSpanId = data.SpanID([8]byte{8, 7, 6, 5, 4, 3, 2, 1}) tv.orig.Name = "test_name" + tv.orig.Flags = uint32(0xf) tv.orig.Kind = otlptrace.Span_SpanKind(3) tv.orig.StartTimeUnixNano = 1234567890 tv.orig.EndTimeUnixNano = 1234567890 - internal.FillTestMap(internal.NewMap(&tv.orig.Attributes)) + internal.FillTestMap(internal.NewMap(&tv.orig.Attributes, tv.state)) tv.orig.DroppedAttributesCount = uint32(17) - fillTestSpanEventSlice(newSpanEventSlice(&tv.orig.Events)) + fillTestSpanEventSlice(newSpanEventSlice(&tv.orig.Events, tv.state)) tv.orig.DroppedEventsCount = uint32(17) - fillTestSpanLinkSlice(newSpanLinkSlice(&tv.orig.Links)) + fillTestSpanLinkSlice(newSpanLinkSlice(&tv.orig.Links, tv.state)) tv.orig.DroppedLinksCount = uint32(17) - fillTestStatus(newStatus(&tv.orig.Status)) + fillTestStatus(newStatus(&tv.orig.Status, tv.state)) } diff --git a/pdata/ptrace/generated_spanevent.go b/pdata/ptrace/generated_spanevent.go index 06da71a3425..a35c88ae93d 100644 --- a/pdata/ptrace/generated_spanevent.go +++ b/pdata/ptrace/generated_spanevent.go @@ -21,11 +21,12 @@ import ( // Must use NewSpanEvent function to create new instances. // Important: zero-initialized instance is not valid for use. type SpanEvent struct { - orig *otlptrace.Span_Event + orig *otlptrace.Span_Event + state *internal.State } -func newSpanEvent(orig *otlptrace.Span_Event) SpanEvent { - return SpanEvent{orig} +func newSpanEvent(orig *otlptrace.Span_Event, state *internal.State) SpanEvent { + return SpanEvent{orig: orig, state: state} } // NewSpanEvent creates a new empty SpanEvent. @@ -33,12 +34,15 @@ func newSpanEvent(orig *otlptrace.Span_Event) SpanEvent { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewSpanEvent() SpanEvent { - return newSpanEvent(&otlptrace.Span_Event{}) + state := internal.StateMutable + return newSpanEvent(&otlptrace.Span_Event{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms SpanEvent) MoveTo(dest SpanEvent) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlptrace.Span_Event{} } @@ -50,6 +54,7 @@ func (ms SpanEvent) Timestamp() pcommon.Timestamp { // SetTimestamp replaces the timestamp associated with this SpanEvent. func (ms SpanEvent) SetTimestamp(v pcommon.Timestamp) { + ms.state.AssertMutable() ms.orig.TimeUnixNano = uint64(v) } @@ -60,12 +65,13 @@ func (ms SpanEvent) Name() string { // SetName replaces the name associated with this SpanEvent. func (ms SpanEvent) SetName(v string) { + ms.state.AssertMutable() ms.orig.Name = v } // Attributes returns the Attributes associated with this SpanEvent. func (ms SpanEvent) Attributes() pcommon.Map { - return pcommon.Map(internal.NewMap(&ms.orig.Attributes)) + return pcommon.Map(internal.NewMap(&ms.orig.Attributes, ms.state)) } // DroppedAttributesCount returns the droppedattributescount associated with this SpanEvent. @@ -75,11 +81,13 @@ func (ms SpanEvent) DroppedAttributesCount() uint32 { // SetDroppedAttributesCount replaces the droppedattributescount associated with this SpanEvent. func (ms SpanEvent) SetDroppedAttributesCount(v uint32) { + ms.state.AssertMutable() ms.orig.DroppedAttributesCount = v } // CopyTo copies all properties from the current struct overriding the destination. func (ms SpanEvent) CopyTo(dest SpanEvent) { + dest.state.AssertMutable() dest.SetTimestamp(ms.Timestamp()) dest.SetName(ms.Name()) ms.Attributes().CopyTo(dest.Attributes()) diff --git a/pdata/ptrace/generated_spanevent_test.go b/pdata/ptrace/generated_spanevent_test.go index af403e1fc24..24ad7de4d1c 100644 --- a/pdata/ptrace/generated_spanevent_test.go +++ b/pdata/ptrace/generated_spanevent_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/pdata/internal" + otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -21,6 +22,9 @@ func TestSpanEvent_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewSpanEvent(), ms) assert.Equal(t, generateTestSpanEvent(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newSpanEvent(&otlptrace.Span_Event{}, &sharedState)) }) + assert.Panics(t, func() { newSpanEvent(&otlptrace.Span_Event{}, &sharedState).MoveTo(dest) }) } func TestSpanEvent_CopyTo(t *testing.T) { @@ -31,6 +35,8 @@ func TestSpanEvent_CopyTo(t *testing.T) { orig = generateTestSpanEvent() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newSpanEvent(&otlptrace.Span_Event{}, &sharedState)) }) } func TestSpanEvent_Timestamp(t *testing.T) { @@ -46,6 +52,8 @@ func TestSpanEvent_Name(t *testing.T) { assert.Equal(t, "", ms.Name()) ms.SetName("test_name") assert.Equal(t, "test_name", ms.Name()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newSpanEvent(&otlptrace.Span_Event{}, &sharedState).SetName("test_name") }) } func TestSpanEvent_Attributes(t *testing.T) { @@ -60,6 +68,8 @@ func TestSpanEvent_DroppedAttributesCount(t *testing.T) { assert.Equal(t, uint32(0), ms.DroppedAttributesCount()) ms.SetDroppedAttributesCount(uint32(17)) assert.Equal(t, uint32(17), ms.DroppedAttributesCount()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newSpanEvent(&otlptrace.Span_Event{}, &sharedState).SetDroppedAttributesCount(uint32(17)) }) } func generateTestSpanEvent() SpanEvent { @@ -71,6 +81,6 @@ func generateTestSpanEvent() SpanEvent { func fillTestSpanEvent(tv SpanEvent) { tv.orig.TimeUnixNano = 1234567890 tv.orig.Name = "test_name" - internal.FillTestMap(internal.NewMap(&tv.orig.Attributes)) + internal.FillTestMap(internal.NewMap(&tv.orig.Attributes, tv.state)) tv.orig.DroppedAttributesCount = uint32(17) } diff --git a/pdata/ptrace/generated_spaneventslice.go b/pdata/ptrace/generated_spaneventslice.go index d78c8ee1735..ffde17c83a2 100644 --- a/pdata/ptrace/generated_spaneventslice.go +++ b/pdata/ptrace/generated_spaneventslice.go @@ -9,6 +9,7 @@ package ptrace import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewSpanEventSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type SpanEventSlice struct { - orig *[]*otlptrace.Span_Event + orig *[]*otlptrace.Span_Event + state *internal.State } -func newSpanEventSlice(orig *[]*otlptrace.Span_Event) SpanEventSlice { - return SpanEventSlice{orig} +func newSpanEventSlice(orig *[]*otlptrace.Span_Event, state *internal.State) SpanEventSlice { + return SpanEventSlice{orig: orig, state: state} } // NewSpanEventSlice creates a SpanEventSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewSpanEventSlice() SpanEventSlice { orig := []*otlptrace.Span_Event(nil) - return newSpanEventSlice(&orig) + state := internal.StateMutable + return newSpanEventSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es SpanEventSlice) Len() int { // ... // Do something with the element // } func (es SpanEventSlice) At(i int) SpanEvent { - return newSpanEvent((*es.orig)[i]) + return newSpanEvent((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es SpanEventSlice) At(i int) SpanEvent { // // Here should set all the values for e. // } func (es SpanEventSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es SpanEventSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty SpanEvent. // It returns the newly added SpanEvent. func (es SpanEventSlice) AppendEmpty() SpanEvent { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlptrace.Span_Event{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es SpanEventSlice) AppendEmpty() SpanEvent { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es SpanEventSlice) MoveAndAppendTo(dest SpanEventSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es SpanEventSlice) MoveAndAppendTo(dest SpanEventSlice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es SpanEventSlice) RemoveIf(f func(SpanEvent) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es SpanEventSlice) RemoveIf(f func(SpanEvent) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es SpanEventSlice) CopyTo(dest SpanEventSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newSpanEvent((*es.orig)[i]).CopyTo(newSpanEvent((*dest.orig)[i])) + newSpanEvent((*es.orig)[i], es.state).CopyTo(newSpanEvent((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es SpanEventSlice) CopyTo(dest SpanEventSlice) { wrappers := make([]*otlptrace.Span_Event, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newSpanEvent((*es.orig)[i]).CopyTo(newSpanEvent(wrappers[i])) + newSpanEvent((*es.orig)[i], es.state).CopyTo(newSpanEvent(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es SpanEventSlice) CopyTo(dest SpanEventSlice) { // provided less function so that two instances of SpanEventSlice // can be compared. func (es SpanEventSlice) Sort(less func(a, b SpanEvent) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/ptrace/generated_spaneventslice_test.go b/pdata/ptrace/generated_spaneventslice_test.go index 76161623897..86da67e1332 100644 --- a/pdata/ptrace/generated_spaneventslice_test.go +++ b/pdata/ptrace/generated_spaneventslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" ) func TestSpanEventSlice(t *testing.T) { es := NewSpanEventSlice() assert.Equal(t, 0, es.Len()) - es = newSpanEventSlice(&[]*otlptrace.Span_Event{}) + state := internal.StateMutable + es = newSpanEventSlice(&[]*otlptrace.Span_Event{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewSpanEvent() @@ -32,6 +34,19 @@ func TestSpanEventSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestSpanEventSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newSpanEventSlice(&[]*otlptrace.Span_Event{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewSpanEventSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestSpanEventSlice_CopyTo(t *testing.T) { dest := NewSpanEventSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestSpanEventSlice(es SpanEventSlice) { *es.orig = make([]*otlptrace.Span_Event, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlptrace.Span_Event{} - fillTestSpanEvent(newSpanEvent((*es.orig)[i])) + fillTestSpanEvent(newSpanEvent((*es.orig)[i], es.state)) } } diff --git a/pdata/ptrace/generated_spanlink.go b/pdata/ptrace/generated_spanlink.go index 89454fb8fcb..3121e263e23 100644 --- a/pdata/ptrace/generated_spanlink.go +++ b/pdata/ptrace/generated_spanlink.go @@ -23,11 +23,12 @@ import ( // Must use NewSpanLink function to create new instances. // Important: zero-initialized instance is not valid for use. type SpanLink struct { - orig *otlptrace.Span_Link + orig *otlptrace.Span_Link + state *internal.State } -func newSpanLink(orig *otlptrace.Span_Link) SpanLink { - return SpanLink{orig} +func newSpanLink(orig *otlptrace.Span_Link, state *internal.State) SpanLink { + return SpanLink{orig: orig, state: state} } // NewSpanLink creates a new empty SpanLink. @@ -35,12 +36,15 @@ func newSpanLink(orig *otlptrace.Span_Link) SpanLink { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewSpanLink() SpanLink { - return newSpanLink(&otlptrace.Span_Link{}) + state := internal.StateMutable + return newSpanLink(&otlptrace.Span_Link{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms SpanLink) MoveTo(dest SpanLink) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlptrace.Span_Link{} } @@ -52,6 +56,7 @@ func (ms SpanLink) TraceID() pcommon.TraceID { // SetTraceID replaces the traceid associated with this SpanLink. func (ms SpanLink) SetTraceID(v pcommon.TraceID) { + ms.state.AssertMutable() ms.orig.TraceId = data.TraceID(v) } @@ -62,17 +67,29 @@ func (ms SpanLink) SpanID() pcommon.SpanID { // SetSpanID replaces the spanid associated with this SpanLink. func (ms SpanLink) SetSpanID(v pcommon.SpanID) { + ms.state.AssertMutable() ms.orig.SpanId = data.SpanID(v) } // TraceState returns the tracestate associated with this SpanLink. func (ms SpanLink) TraceState() pcommon.TraceState { - return pcommon.TraceState(internal.NewTraceState(&ms.orig.TraceState)) + return pcommon.TraceState(internal.NewTraceState(&ms.orig.TraceState, ms.state)) +} + +// Flags returns the flags associated with this SpanLink. +func (ms SpanLink) Flags() uint32 { + return ms.orig.Flags +} + +// SetFlags replaces the flags associated with this SpanLink. +func (ms SpanLink) SetFlags(v uint32) { + ms.state.AssertMutable() + ms.orig.Flags = v } // Attributes returns the Attributes associated with this SpanLink. func (ms SpanLink) Attributes() pcommon.Map { - return pcommon.Map(internal.NewMap(&ms.orig.Attributes)) + return pcommon.Map(internal.NewMap(&ms.orig.Attributes, ms.state)) } // DroppedAttributesCount returns the droppedattributescount associated with this SpanLink. @@ -82,14 +99,17 @@ func (ms SpanLink) DroppedAttributesCount() uint32 { // SetDroppedAttributesCount replaces the droppedattributescount associated with this SpanLink. func (ms SpanLink) SetDroppedAttributesCount(v uint32) { + ms.state.AssertMutable() ms.orig.DroppedAttributesCount = v } // CopyTo copies all properties from the current struct overriding the destination. func (ms SpanLink) CopyTo(dest SpanLink) { + dest.state.AssertMutable() dest.SetTraceID(ms.TraceID()) dest.SetSpanID(ms.SpanID()) ms.TraceState().CopyTo(dest.TraceState()) + dest.SetFlags(ms.Flags()) ms.Attributes().CopyTo(dest.Attributes()) dest.SetDroppedAttributesCount(ms.DroppedAttributesCount()) } diff --git a/pdata/ptrace/generated_spanlink_test.go b/pdata/ptrace/generated_spanlink_test.go index b0bbb58a78a..89d60df56d1 100644 --- a/pdata/ptrace/generated_spanlink_test.go +++ b/pdata/ptrace/generated_spanlink_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" "go.opentelemetry.io/collector/pdata/internal/data" + otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -22,6 +23,9 @@ func TestSpanLink_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewSpanLink(), ms) assert.Equal(t, generateTestSpanLink(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newSpanLink(&otlptrace.Span_Link{}, &sharedState)) }) + assert.Panics(t, func() { newSpanLink(&otlptrace.Span_Link{}, &sharedState).MoveTo(dest) }) } func TestSpanLink_CopyTo(t *testing.T) { @@ -32,6 +36,8 @@ func TestSpanLink_CopyTo(t *testing.T) { orig = generateTestSpanLink() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newSpanLink(&otlptrace.Span_Link{}, &sharedState)) }) } func TestSpanLink_TraceID(t *testing.T) { @@ -56,6 +62,15 @@ func TestSpanLink_TraceState(t *testing.T) { assert.Equal(t, pcommon.TraceState(internal.GenerateTestTraceState()), ms.TraceState()) } +func TestSpanLink_Flags(t *testing.T) { + ms := NewSpanLink() + assert.Equal(t, uint32(0), ms.Flags()) + ms.SetFlags(uint32(0xf)) + assert.Equal(t, uint32(0xf), ms.Flags()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newSpanLink(&otlptrace.Span_Link{}, &sharedState).SetFlags(uint32(0xf)) }) +} + func TestSpanLink_Attributes(t *testing.T) { ms := NewSpanLink() assert.Equal(t, pcommon.NewMap(), ms.Attributes()) @@ -68,6 +83,8 @@ func TestSpanLink_DroppedAttributesCount(t *testing.T) { assert.Equal(t, uint32(0), ms.DroppedAttributesCount()) ms.SetDroppedAttributesCount(uint32(17)) assert.Equal(t, uint32(17), ms.DroppedAttributesCount()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newSpanLink(&otlptrace.Span_Link{}, &sharedState).SetDroppedAttributesCount(uint32(17)) }) } func generateTestSpanLink() SpanLink { @@ -79,7 +96,8 @@ func generateTestSpanLink() SpanLink { func fillTestSpanLink(tv SpanLink) { tv.orig.TraceId = data.TraceID([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1}) tv.orig.SpanId = data.SpanID([8]byte{8, 7, 6, 5, 4, 3, 2, 1}) - internal.FillTestTraceState(internal.NewTraceState(&tv.orig.TraceState)) - internal.FillTestMap(internal.NewMap(&tv.orig.Attributes)) + internal.FillTestTraceState(internal.NewTraceState(&tv.orig.TraceState, tv.state)) + tv.orig.Flags = uint32(0xf) + internal.FillTestMap(internal.NewMap(&tv.orig.Attributes, tv.state)) tv.orig.DroppedAttributesCount = uint32(17) } diff --git a/pdata/ptrace/generated_spanlinkslice.go b/pdata/ptrace/generated_spanlinkslice.go index 19d75a4807b..164038b8bed 100644 --- a/pdata/ptrace/generated_spanlinkslice.go +++ b/pdata/ptrace/generated_spanlinkslice.go @@ -9,6 +9,7 @@ package ptrace import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewSpanLinkSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type SpanLinkSlice struct { - orig *[]*otlptrace.Span_Link + orig *[]*otlptrace.Span_Link + state *internal.State } -func newSpanLinkSlice(orig *[]*otlptrace.Span_Link) SpanLinkSlice { - return SpanLinkSlice{orig} +func newSpanLinkSlice(orig *[]*otlptrace.Span_Link, state *internal.State) SpanLinkSlice { + return SpanLinkSlice{orig: orig, state: state} } // NewSpanLinkSlice creates a SpanLinkSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewSpanLinkSlice() SpanLinkSlice { orig := []*otlptrace.Span_Link(nil) - return newSpanLinkSlice(&orig) + state := internal.StateMutable + return newSpanLinkSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es SpanLinkSlice) Len() int { // ... // Do something with the element // } func (es SpanLinkSlice) At(i int) SpanLink { - return newSpanLink((*es.orig)[i]) + return newSpanLink((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es SpanLinkSlice) At(i int) SpanLink { // // Here should set all the values for e. // } func (es SpanLinkSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es SpanLinkSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty SpanLink. // It returns the newly added SpanLink. func (es SpanLinkSlice) AppendEmpty() SpanLink { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlptrace.Span_Link{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es SpanLinkSlice) AppendEmpty() SpanLink { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es SpanLinkSlice) MoveAndAppendTo(dest SpanLinkSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es SpanLinkSlice) MoveAndAppendTo(dest SpanLinkSlice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es SpanLinkSlice) RemoveIf(f func(SpanLink) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es SpanLinkSlice) RemoveIf(f func(SpanLink) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es SpanLinkSlice) CopyTo(dest SpanLinkSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newSpanLink((*es.orig)[i]).CopyTo(newSpanLink((*dest.orig)[i])) + newSpanLink((*es.orig)[i], es.state).CopyTo(newSpanLink((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es SpanLinkSlice) CopyTo(dest SpanLinkSlice) { wrappers := make([]*otlptrace.Span_Link, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newSpanLink((*es.orig)[i]).CopyTo(newSpanLink(wrappers[i])) + newSpanLink((*es.orig)[i], es.state).CopyTo(newSpanLink(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es SpanLinkSlice) CopyTo(dest SpanLinkSlice) { // provided less function so that two instances of SpanLinkSlice // can be compared. func (es SpanLinkSlice) Sort(less func(a, b SpanLink) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/ptrace/generated_spanlinkslice_test.go b/pdata/ptrace/generated_spanlinkslice_test.go index 3ab05bfa547..9ad8f4dc276 100644 --- a/pdata/ptrace/generated_spanlinkslice_test.go +++ b/pdata/ptrace/generated_spanlinkslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" ) func TestSpanLinkSlice(t *testing.T) { es := NewSpanLinkSlice() assert.Equal(t, 0, es.Len()) - es = newSpanLinkSlice(&[]*otlptrace.Span_Link{}) + state := internal.StateMutable + es = newSpanLinkSlice(&[]*otlptrace.Span_Link{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewSpanLink() @@ -32,6 +34,19 @@ func TestSpanLinkSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestSpanLinkSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newSpanLinkSlice(&[]*otlptrace.Span_Link{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewSpanLinkSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestSpanLinkSlice_CopyTo(t *testing.T) { dest := NewSpanLinkSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestSpanLinkSlice(es SpanLinkSlice) { *es.orig = make([]*otlptrace.Span_Link, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlptrace.Span_Link{} - fillTestSpanLink(newSpanLink((*es.orig)[i])) + fillTestSpanLink(newSpanLink((*es.orig)[i], es.state)) } } diff --git a/pdata/ptrace/generated_spanslice.go b/pdata/ptrace/generated_spanslice.go index 5b39aacb073..654a547523f 100644 --- a/pdata/ptrace/generated_spanslice.go +++ b/pdata/ptrace/generated_spanslice.go @@ -9,6 +9,7 @@ package ptrace import ( "sort" + "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" ) @@ -20,18 +21,20 @@ import ( // Must use NewSpanSlice function to create new instances. // Important: zero-initialized instance is not valid for use. type SpanSlice struct { - orig *[]*otlptrace.Span + orig *[]*otlptrace.Span + state *internal.State } -func newSpanSlice(orig *[]*otlptrace.Span) SpanSlice { - return SpanSlice{orig} +func newSpanSlice(orig *[]*otlptrace.Span, state *internal.State) SpanSlice { + return SpanSlice{orig: orig, state: state} } // NewSpanSlice creates a SpanSlice with 0 elements. // Can use "EnsureCapacity" to initialize with a given capacity. func NewSpanSlice() SpanSlice { orig := []*otlptrace.Span(nil) - return newSpanSlice(&orig) + state := internal.StateMutable + return newSpanSlice(&orig, &state) } // Len returns the number of elements in the slice. @@ -50,7 +53,7 @@ func (es SpanSlice) Len() int { // ... // Do something with the element // } func (es SpanSlice) At(i int) Span { - return newSpan((*es.orig)[i]) + return newSpan((*es.orig)[i], es.state) } // EnsureCapacity is an operation that ensures the slice has at least the specified capacity. @@ -66,6 +69,7 @@ func (es SpanSlice) At(i int) Span { // // Here should set all the values for e. // } func (es SpanSlice) EnsureCapacity(newCap int) { + es.state.AssertMutable() oldCap := cap(*es.orig) if newCap <= oldCap { return @@ -79,6 +83,7 @@ func (es SpanSlice) EnsureCapacity(newCap int) { // AppendEmpty will append to the end of the slice an empty Span. // It returns the newly added Span. func (es SpanSlice) AppendEmpty() Span { + es.state.AssertMutable() *es.orig = append(*es.orig, &otlptrace.Span{}) return es.At(es.Len() - 1) } @@ -86,6 +91,8 @@ func (es SpanSlice) AppendEmpty() Span { // MoveAndAppendTo moves all elements from the current slice and appends them to the dest. // The current slice will be cleared. func (es SpanSlice) MoveAndAppendTo(dest SpanSlice) { + es.state.AssertMutable() + dest.state.AssertMutable() if *dest.orig == nil { // We can simply move the entire vector and avoid any allocations. *dest.orig = *es.orig @@ -98,6 +105,7 @@ func (es SpanSlice) MoveAndAppendTo(dest SpanSlice) { // RemoveIf calls f sequentially for each element present in the slice. // If f returns true, the element is removed from the slice. func (es SpanSlice) RemoveIf(f func(Span) bool) { + es.state.AssertMutable() newLen := 0 for i := 0; i < len(*es.orig); i++ { if f(es.At(i)) { @@ -111,18 +119,18 @@ func (es SpanSlice) RemoveIf(f func(Span) bool) { (*es.orig)[newLen] = (*es.orig)[i] newLen++ } - // TODO: Prevent memory leak by erasing truncated values. *es.orig = (*es.orig)[:newLen] } // CopyTo copies all elements from the current slice overriding the destination. func (es SpanSlice) CopyTo(dest SpanSlice) { + dest.state.AssertMutable() srcLen := es.Len() destCap := cap(*dest.orig) if srcLen <= destCap { (*dest.orig) = (*dest.orig)[:srcLen:destCap] for i := range *es.orig { - newSpan((*es.orig)[i]).CopyTo(newSpan((*dest.orig)[i])) + newSpan((*es.orig)[i], es.state).CopyTo(newSpan((*dest.orig)[i], dest.state)) } return } @@ -130,7 +138,7 @@ func (es SpanSlice) CopyTo(dest SpanSlice) { wrappers := make([]*otlptrace.Span, srcLen) for i := range *es.orig { wrappers[i] = &origs[i] - newSpan((*es.orig)[i]).CopyTo(newSpan(wrappers[i])) + newSpan((*es.orig)[i], es.state).CopyTo(newSpan(wrappers[i], dest.state)) } *dest.orig = wrappers } @@ -139,5 +147,6 @@ func (es SpanSlice) CopyTo(dest SpanSlice) { // provided less function so that two instances of SpanSlice // can be compared. func (es SpanSlice) Sort(less func(a, b Span) bool) { + es.state.AssertMutable() sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } diff --git a/pdata/ptrace/generated_spanslice_test.go b/pdata/ptrace/generated_spanslice_test.go index 0417d2cbd25..1ae585b996f 100644 --- a/pdata/ptrace/generated_spanslice_test.go +++ b/pdata/ptrace/generated_spanslice_test.go @@ -12,13 +12,15 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" ) func TestSpanSlice(t *testing.T) { es := NewSpanSlice() assert.Equal(t, 0, es.Len()) - es = newSpanSlice(&[]*otlptrace.Span{}) + state := internal.StateMutable + es = newSpanSlice(&[]*otlptrace.Span{}, &state) assert.Equal(t, 0, es.Len()) emptyVal := NewSpan() @@ -32,6 +34,19 @@ func TestSpanSlice(t *testing.T) { assert.Equal(t, 7, es.Len()) } +func TestSpanSliceReadOnly(t *testing.T) { + sharedState := internal.StateReadOnly + es := newSpanSlice(&[]*otlptrace.Span{}, &sharedState) + assert.Equal(t, 0, es.Len()) + assert.Panics(t, func() { es.AppendEmpty() }) + assert.Panics(t, func() { es.EnsureCapacity(2) }) + es2 := NewSpanSlice() + es.CopyTo(es2) + assert.Panics(t, func() { es2.CopyTo(es) }) + assert.Panics(t, func() { es.MoveAndAppendTo(es2) }) + assert.Panics(t, func() { es2.MoveAndAppendTo(es) }) +} + func TestSpanSlice_CopyTo(t *testing.T) { dest := NewSpanSlice() // Test CopyTo to empty @@ -134,6 +149,6 @@ func fillTestSpanSlice(es SpanSlice) { *es.orig = make([]*otlptrace.Span, 7) for i := 0; i < 7; i++ { (*es.orig)[i] = &otlptrace.Span{} - fillTestSpan(newSpan((*es.orig)[i])) + fillTestSpan(newSpan((*es.orig)[i], es.state)) } } diff --git a/pdata/ptrace/generated_status.go b/pdata/ptrace/generated_status.go index c0850997b22..2b3e66a92d0 100644 --- a/pdata/ptrace/generated_status.go +++ b/pdata/ptrace/generated_status.go @@ -7,6 +7,7 @@ package ptrace import ( + "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" ) @@ -19,11 +20,12 @@ import ( // Must use NewStatus function to create new instances. // Important: zero-initialized instance is not valid for use. type Status struct { - orig *otlptrace.Status + orig *otlptrace.Status + state *internal.State } -func newStatus(orig *otlptrace.Status) Status { - return Status{orig} +func newStatus(orig *otlptrace.Status, state *internal.State) Status { + return Status{orig: orig, state: state} } // NewStatus creates a new empty Status. @@ -31,12 +33,15 @@ func newStatus(orig *otlptrace.Status) Status { // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewStatus() Status { - return newStatus(&otlptrace.Status{}) + state := internal.StateMutable + return newStatus(&otlptrace.Status{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms Status) MoveTo(dest Status) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlptrace.Status{} } @@ -48,6 +53,7 @@ func (ms Status) Code() StatusCode { // SetCode replaces the code associated with this Status. func (ms Status) SetCode(v StatusCode) { + ms.state.AssertMutable() ms.orig.Code = otlptrace.Status_StatusCode(v) } @@ -58,11 +64,13 @@ func (ms Status) Message() string { // SetMessage replaces the message associated with this Status. func (ms Status) SetMessage(v string) { + ms.state.AssertMutable() ms.orig.Message = v } // CopyTo copies all properties from the current struct overriding the destination. func (ms Status) CopyTo(dest Status) { + dest.state.AssertMutable() dest.SetCode(ms.Code()) dest.SetMessage(ms.Message()) } diff --git a/pdata/ptrace/generated_status_test.go b/pdata/ptrace/generated_status_test.go index b3a960f62f1..97d158ef4b3 100644 --- a/pdata/ptrace/generated_status_test.go +++ b/pdata/ptrace/generated_status_test.go @@ -10,6 +10,9 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/pdata/internal" + otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" ) func TestStatus_MoveTo(t *testing.T) { @@ -18,6 +21,9 @@ func TestStatus_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewStatus(), ms) assert.Equal(t, generateTestStatus(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.MoveTo(newStatus(&otlptrace.Status{}, &sharedState)) }) + assert.Panics(t, func() { newStatus(&otlptrace.Status{}, &sharedState).MoveTo(dest) }) } func TestStatus_CopyTo(t *testing.T) { @@ -28,6 +34,8 @@ func TestStatus_CopyTo(t *testing.T) { orig = generateTestStatus() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { ms.CopyTo(newStatus(&otlptrace.Status{}, &sharedState)) }) } func TestStatus_Code(t *testing.T) { @@ -43,6 +51,8 @@ func TestStatus_Message(t *testing.T) { assert.Equal(t, "", ms.Message()) ms.SetMessage("cancelled") assert.Equal(t, "cancelled", ms.Message()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { newStatus(&otlptrace.Status{}, &sharedState).SetMessage("cancelled") }) } func generateTestStatus() Status { diff --git a/pdata/ptrace/json.go b/pdata/ptrace/json.go index 682eeed1ca5..64bd273ba96 100644 --- a/pdata/ptrace/json.go +++ b/pdata/ptrace/json.go @@ -15,8 +15,10 @@ import ( "go.opentelemetry.io/collector/pdata/internal/otlp" ) +// JSONMarshaler marshals pdata.Traces to JSON bytes using the OTLP/JSON format. type JSONMarshaler struct{} +// MarshalTraces to the OTLP/JSON format. func (*JSONMarshaler) MarshalTraces(td Traces) ([]byte, error) { buf := bytes.Buffer{} pb := internal.TracesToProto(internal.Traces(td)) @@ -24,8 +26,10 @@ func (*JSONMarshaler) MarshalTraces(td Traces) ([]byte, error) { return buf.Bytes(), err } +// JSONUnmarshaler unmarshals OTLP/JSON formatted-bytes to pdata.Traces. type JSONUnmarshaler struct{} +// UnmarshalTraces from OTLP/JSON format into pdata.Traces. func (*JSONUnmarshaler) UnmarshalTraces(buf []byte) (Traces, error) { iter := jsoniter.ConfigFastest.BorrowIterator(buf) defer jsoniter.ConfigFastest.ReturnIterator(iter) diff --git a/pdata/ptrace/package_test.go b/pdata/ptrace/package_test.go new file mode 100644 index 00000000000..6a79f065692 --- /dev/null +++ b/pdata/ptrace/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package ptrace + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess.go b/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess.go index 5fb974d187c..50cf0c805e8 100644 --- a/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess.go +++ b/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess.go @@ -7,6 +7,7 @@ package ptraceotlp import ( + "go.opentelemetry.io/collector/pdata/internal" otlpcollectortrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/trace/v1" ) @@ -18,11 +19,12 @@ import ( // Must use NewExportPartialSuccess function to create new instances. // Important: zero-initialized instance is not valid for use. type ExportPartialSuccess struct { - orig *otlpcollectortrace.ExportTracePartialSuccess + orig *otlpcollectortrace.ExportTracePartialSuccess + state *internal.State } -func newExportPartialSuccess(orig *otlpcollectortrace.ExportTracePartialSuccess) ExportPartialSuccess { - return ExportPartialSuccess{orig} +func newExportPartialSuccess(orig *otlpcollectortrace.ExportTracePartialSuccess, state *internal.State) ExportPartialSuccess { + return ExportPartialSuccess{orig: orig, state: state} } // NewExportPartialSuccess creates a new empty ExportPartialSuccess. @@ -30,12 +32,15 @@ func newExportPartialSuccess(orig *otlpcollectortrace.ExportTracePartialSuccess) // This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice, // OR directly access the member if this is embedded in another struct. func NewExportPartialSuccess() ExportPartialSuccess { - return newExportPartialSuccess(&otlpcollectortrace.ExportTracePartialSuccess{}) + state := internal.StateMutable + return newExportPartialSuccess(&otlpcollectortrace.ExportTracePartialSuccess{}, &state) } // MoveTo moves all properties from the current struct overriding the destination and // resetting the current instance to its zero value func (ms ExportPartialSuccess) MoveTo(dest ExportPartialSuccess) { + ms.state.AssertMutable() + dest.state.AssertMutable() *dest.orig = *ms.orig *ms.orig = otlpcollectortrace.ExportTracePartialSuccess{} } @@ -47,6 +52,7 @@ func (ms ExportPartialSuccess) RejectedSpans() int64 { // SetRejectedSpans replaces the rejectedspans associated with this ExportPartialSuccess. func (ms ExportPartialSuccess) SetRejectedSpans(v int64) { + ms.state.AssertMutable() ms.orig.RejectedSpans = v } @@ -57,11 +63,13 @@ func (ms ExportPartialSuccess) ErrorMessage() string { // SetErrorMessage replaces the errormessage associated with this ExportPartialSuccess. func (ms ExportPartialSuccess) SetErrorMessage(v string) { + ms.state.AssertMutable() ms.orig.ErrorMessage = v } // CopyTo copies all properties from the current struct overriding the destination. func (ms ExportPartialSuccess) CopyTo(dest ExportPartialSuccess) { + dest.state.AssertMutable() dest.SetRejectedSpans(ms.RejectedSpans()) dest.SetErrorMessage(ms.ErrorMessage()) } diff --git a/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess_test.go b/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess_test.go index a32ade473c3..927f0897e1b 100644 --- a/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess_test.go +++ b/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess_test.go @@ -10,6 +10,9 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/pdata/internal" + otlpcollectortrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/trace/v1" ) func TestExportPartialSuccess_MoveTo(t *testing.T) { @@ -18,6 +21,13 @@ func TestExportPartialSuccess_MoveTo(t *testing.T) { ms.MoveTo(dest) assert.Equal(t, NewExportPartialSuccess(), ms) assert.Equal(t, generateTestExportPartialSuccess(), dest) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + ms.MoveTo(newExportPartialSuccess(&otlpcollectortrace.ExportTracePartialSuccess{}, &sharedState)) + }) + assert.Panics(t, func() { + newExportPartialSuccess(&otlpcollectortrace.ExportTracePartialSuccess{}, &sharedState).MoveTo(dest) + }) } func TestExportPartialSuccess_CopyTo(t *testing.T) { @@ -28,6 +38,10 @@ func TestExportPartialSuccess_CopyTo(t *testing.T) { orig = generateTestExportPartialSuccess() orig.CopyTo(ms) assert.Equal(t, orig, ms) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + ms.CopyTo(newExportPartialSuccess(&otlpcollectortrace.ExportTracePartialSuccess{}, &sharedState)) + }) } func TestExportPartialSuccess_RejectedSpans(t *testing.T) { @@ -35,6 +49,10 @@ func TestExportPartialSuccess_RejectedSpans(t *testing.T) { assert.Equal(t, int64(0), ms.RejectedSpans()) ms.SetRejectedSpans(int64(13)) assert.Equal(t, int64(13), ms.RejectedSpans()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newExportPartialSuccess(&otlpcollectortrace.ExportTracePartialSuccess{}, &sharedState).SetRejectedSpans(int64(13)) + }) } func TestExportPartialSuccess_ErrorMessage(t *testing.T) { @@ -42,6 +60,10 @@ func TestExportPartialSuccess_ErrorMessage(t *testing.T) { assert.Equal(t, "", ms.ErrorMessage()) ms.SetErrorMessage("error message") assert.Equal(t, "error message", ms.ErrorMessage()) + sharedState := internal.StateReadOnly + assert.Panics(t, func() { + newExportPartialSuccess(&otlpcollectortrace.ExportTracePartialSuccess{}, &sharedState).SetErrorMessage("error message") + }) } func generateTestExportPartialSuccess() ExportPartialSuccess { diff --git a/pdata/ptrace/ptraceotlp/grpc.go b/pdata/ptrace/ptraceotlp/grpc.go index fec514eb62c..b768b08e67a 100644 --- a/pdata/ptrace/ptraceotlp/grpc.go +++ b/pdata/ptrace/ptraceotlp/grpc.go @@ -10,6 +10,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "go.opentelemetry.io/collector/pdata/internal" otlpcollectortrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/trace/v1" "go.opentelemetry.io/collector/pdata/internal/otlp" ) @@ -40,7 +41,11 @@ type grpcClient struct { // Export implements the Client interface. func (c *grpcClient) Export(ctx context.Context, request ExportRequest, opts ...grpc.CallOption) (ExportResponse, error) { rsp, err := c.rawClient.Export(ctx, request.orig, opts...) - return ExportResponse{orig: rsp}, err + if err != nil { + return ExportResponse{}, err + } + state := internal.StateMutable + return ExportResponse{orig: rsp, state: &state}, err } func (c *grpcClient) unexported() {} @@ -80,6 +85,7 @@ type rawTracesServer struct { func (s rawTracesServer) Export(ctx context.Context, request *otlpcollectortrace.ExportTraceServiceRequest) (*otlpcollectortrace.ExportTraceServiceResponse, error) { otlp.MigrateTraces(request.ResourceSpans) - rsp, err := s.srv.Export(ctx, ExportRequest{orig: request}) + state := internal.StateMutable + rsp, err := s.srv.Export(ctx, ExportRequest{orig: request, state: &state}) return rsp.orig, err } diff --git a/pdata/ptrace/ptraceotlp/package_test.go b/pdata/ptrace/ptraceotlp/package_test.go new file mode 100644 index 00000000000..4b8a352c461 --- /dev/null +++ b/pdata/ptrace/ptraceotlp/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package ptraceotlp + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/pdata/ptrace/ptraceotlp/request.go b/pdata/ptrace/ptraceotlp/request.go index ae9f57100f7..0bdafc8a3af 100644 --- a/pdata/ptrace/ptraceotlp/request.go +++ b/pdata/ptrace/ptraceotlp/request.go @@ -18,19 +18,27 @@ var jsonUnmarshaler = &ptrace.JSONUnmarshaler{} // ExportRequest represents the request for gRPC/HTTP client/server. // It's a wrapper for ptrace.Traces data. type ExportRequest struct { - orig *otlpcollectortrace.ExportTraceServiceRequest + orig *otlpcollectortrace.ExportTraceServiceRequest + state *internal.State } // NewExportRequest returns an empty ExportRequest. func NewExportRequest() ExportRequest { - return ExportRequest{orig: &otlpcollectortrace.ExportTraceServiceRequest{}} + state := internal.StateMutable + return ExportRequest{ + orig: &otlpcollectortrace.ExportTraceServiceRequest{}, + state: &state, + } } // NewExportRequestFromTraces returns a ExportRequest from ptrace.Traces. // Because ExportRequest is a wrapper for ptrace.Traces, // any changes to the provided Traces struct will be reflected in the ExportRequest and vice versa. func NewExportRequestFromTraces(td ptrace.Traces) ExportRequest { - return ExportRequest{orig: internal.GetOrigTraces(internal.Traces(td))} + return ExportRequest{ + orig: internal.GetOrigTraces(internal.Traces(td)), + state: internal.GetTracesState(internal.Traces(td)), + } } // MarshalProto marshals ExportRequest into proto bytes. @@ -67,5 +75,5 @@ func (ms ExportRequest) UnmarshalJSON(data []byte) error { } func (ms ExportRequest) Traces() ptrace.Traces { - return ptrace.Traces(internal.NewTraces(ms.orig)) + return ptrace.Traces(internal.NewTraces(ms.orig, ms.state)) } diff --git a/pdata/ptrace/ptraceotlp/response.go b/pdata/ptrace/ptraceotlp/response.go index 3301131fd0a..78096bff77c 100644 --- a/pdata/ptrace/ptraceotlp/response.go +++ b/pdata/ptrace/ptraceotlp/response.go @@ -8,18 +8,24 @@ import ( jsoniter "github.com/json-iterator/go" + "go.opentelemetry.io/collector/pdata/internal" otlpcollectortrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/trace/v1" "go.opentelemetry.io/collector/pdata/internal/json" ) // ExportResponse represents the response for gRPC/HTTP client/server. type ExportResponse struct { - orig *otlpcollectortrace.ExportTraceServiceResponse + orig *otlpcollectortrace.ExportTraceServiceResponse + state *internal.State } // NewExportResponse returns an empty ExportResponse. func NewExportResponse() ExportResponse { - return ExportResponse{orig: &otlpcollectortrace.ExportTraceServiceResponse{}} + state := internal.StateMutable + return ExportResponse{ + orig: &otlpcollectortrace.ExportTraceServiceResponse{}, + state: &state, + } } // MarshalProto marshals ExportResponse into proto bytes. @@ -64,11 +70,11 @@ func (ms ExportResponse) unmarshalJsoniter(iter *jsoniter.Iterator) { // PartialSuccess returns the ExportLogsPartialSuccess associated with this ExportResponse. func (ms ExportResponse) PartialSuccess() ExportPartialSuccess { - return newExportPartialSuccess(&ms.orig.PartialSuccess) + return newExportPartialSuccess(&ms.orig.PartialSuccess, ms.state) } func (ms ExportPartialSuccess) unmarshalJsoniter(iter *jsoniter.Iterator) { - iter.ReadObjectCB(func(iterator *jsoniter.Iterator, f string) bool { + iter.ReadObjectCB(func(_ *jsoniter.Iterator, f string) bool { switch f { case "rejected_spans", "rejectedSpans": ms.orig.RejectedSpans = json.ReadInt64(iter) diff --git a/pdata/ptrace/traces.go b/pdata/ptrace/traces.go index 8f1f1c7fe8a..a4b71e17853 100644 --- a/pdata/ptrace/traces.go +++ b/pdata/ptrace/traces.go @@ -13,18 +13,28 @@ import ( type Traces internal.Traces func newTraces(orig *otlpcollectortrace.ExportTraceServiceRequest) Traces { - return Traces(internal.NewTraces(orig)) + state := internal.StateMutable + return Traces(internal.NewTraces(orig, &state)) } func (ms Traces) getOrig() *otlpcollectortrace.ExportTraceServiceRequest { return internal.GetOrigTraces(internal.Traces(ms)) } +func (ms Traces) getState() *internal.State { + return internal.GetTracesState(internal.Traces(ms)) +} + // NewTraces creates a new Traces struct. func NewTraces() Traces { return newTraces(&otlpcollectortrace.ExportTraceServiceRequest{}) } +// IsReadOnly returns true if this Traces instance is read-only. +func (ms Traces) IsReadOnly() bool { + return *ms.getState() == internal.StateReadOnly +} + // CopyTo copies the Traces instance overriding the destination. func (ms Traces) CopyTo(dest Traces) { ms.ResourceSpans().CopyTo(dest.ResourceSpans()) @@ -46,5 +56,10 @@ func (ms Traces) SpanCount() int { // ResourceSpans returns the ResourceSpansSlice associated with this Metrics. func (ms Traces) ResourceSpans() ResourceSpansSlice { - return newResourceSpansSlice(&ms.getOrig().ResourceSpans) + return newResourceSpansSlice(&ms.getOrig().ResourceSpans, internal.GetTracesState(internal.Traces(ms))) +} + +// MarkReadOnly marks the Traces as shared so that no further modifications can be done on it. +func (ms Traces) MarkReadOnly() { + internal.SetTracesState(internal.Traces(ms), internal.StateReadOnly) } diff --git a/pdata/ptrace/traces_test.go b/pdata/ptrace/traces_test.go index 6145ca7b995..8884349485f 100644 --- a/pdata/ptrace/traces_test.go +++ b/pdata/ptrace/traces_test.go @@ -5,6 +5,7 @@ package ptrace import ( "testing" + "time" gogoproto "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/assert" @@ -13,6 +14,7 @@ import ( otlpcollectortrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/trace/v1" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/pcommon" ) func TestSpanCount(t *testing.T) { @@ -113,3 +115,66 @@ func TestTracesCopyTo(t *testing.T) { traces.CopyTo(tracesCopy) assert.EqualValues(t, traces, tracesCopy) } + +func TestReadOnlyTracesInvalidUsage(t *testing.T) { + traces := NewTraces() + assert.False(t, traces.IsReadOnly()) + res := traces.ResourceSpans().AppendEmpty().Resource() + res.Attributes().PutStr("k1", "v1") + traces.MarkReadOnly() + assert.True(t, traces.IsReadOnly()) + assert.Panics(t, func() { res.Attributes().PutStr("k2", "v2") }) +} + +func BenchmarkTracesUsage(b *testing.B) { + traces := NewTraces() + fillTestResourceSpansSlice(traces.ResourceSpans()) + ts := pcommon.NewTimestampFromTime(time.Now()) + + b.ReportAllocs() + b.ResetTimer() + + for bb := 0; bb < b.N; bb++ { + for i := 0; i < traces.ResourceSpans().Len(); i++ { + rs := traces.ResourceSpans().At(i) + res := rs.Resource() + res.Attributes().PutStr("foo", "bar") + v, ok := res.Attributes().Get("foo") + assert.True(b, ok) + assert.Equal(b, "bar", v.Str()) + v.SetStr("new-bar") + assert.Equal(b, "new-bar", v.Str()) + res.Attributes().Remove("foo") + for j := 0; j < rs.ScopeSpans().Len(); j++ { + iss := rs.ScopeSpans().At(j) + iss.Scope().SetName("new_test_name") + assert.Equal(b, "new_test_name", iss.Scope().Name()) + for k := 0; k < iss.Spans().Len(); k++ { + s := iss.Spans().At(k) + s.SetName("new_span") + assert.Equal(b, "new_span", s.Name()) + s.SetStartTimestamp(ts) + assert.Equal(b, ts, s.StartTimestamp()) + s.SetEndTimestamp(ts) + assert.Equal(b, ts, s.EndTimestamp()) + s.SetTraceID([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}) + assert.Equal(b, pcommon.TraceID([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}), s.TraceID()) + s.SetSpanID([8]byte{1, 2, 3, 4, 5, 6, 7, 8}) + assert.Equal(b, pcommon.SpanID([8]byte{1, 2, 3, 4, 5, 6, 7, 8}), s.SpanID()) + } + s := iss.Spans().AppendEmpty() + s.SetName("another_span") + s.SetStartTimestamp(ts) + s.SetEndTimestamp(ts) + s.SetTraceID([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}) + s.SetParentSpanID([8]byte{1, 2, 3, 4, 5, 6, 7, 8}) + s.SetSpanID([8]byte{1, 2, 3, 4, 5, 6, 7, 8}) + s.Attributes().PutStr("foo1", "bar1") + s.Attributes().PutStr("foo2", "bar2") + iss.Spans().RemoveIf(func(lr Span) bool { + return lr.Name() == "another_span" + }) + } + } + } +} diff --git a/processor/README.md b/processor/README.md index 8345f235837..f52dbc10374 100644 --- a/processor/README.md +++ b/processor/README.md @@ -21,26 +21,18 @@ The [contrib repository](https://github.com/open-telemetry/opentelemetry-collect ## Recommended Processors -By default, no processors are enabled. Depending on the data source, it may be recommended that multiple processors be enabled. Processors must be -enabled for every data source: Not all processors support all data sources. +By default, no processors are enabled. Depending on the data source, it may be +recommended that multiple processors be enabled. Processors must be enabled +for every data source and not all processors support all data sources. In addition, it is important to note that the order of processors matters. The order in each section below is the best practice. Refer to the individual processor documentation for more information. -### Traces - 1. [memory_limiter](memorylimiterprocessor/README.md) -2. *any sampling processors* +2. Any sampling or initial filtering processors 3. Any processor relying on sending source from `Context` (e.g. `k8sattributes`) 3. [batch](batchprocessor/README.md) -4. *any other processors* - -### Metrics - -1. [memory_limiter](memorylimiterprocessor/README.md) -2. Any processor relying on sending source from `Context` (e.g. `k8sattributes`) -3. [batch](batchprocessor/README.md) -4. *any other processors* +4. Any other processors ## Data Ownership @@ -114,4 +106,4 @@ data cloning described in Exclusive Ownership section. ## Ordering Processors The order processors are specified in a pipeline is important as this is the -order in which each processor is applied to traces and metrics. +order in which each processor is applied. diff --git a/processor/batchprocessor/README.md b/processor/batchprocessor/README.md index c63566d05bd..85ae733d28a 100644 --- a/processor/batchprocessor/README.md +++ b/processor/batchprocessor/README.md @@ -1,12 +1,16 @@ # Batch Processor -| Status | | -| ------------------------ | --------------------- | -| Stability | traces [beta] | -| | metrics [beta] | -| | logs [beta] | -| Supported pipeline types | traces, metrics, logs | -| Distributions | [core], [contrib] | + +| Status | | +| ------------- |-----------| +| Stability | [beta]: traces, metrics, logs | +| Distributions | [core], [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aprocessor%2Fbatch%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aprocessor%2Fbatch) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aprocessor%2Fbatch%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aprocessor%2Fbatch) | + +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + The batch processor accepts spans, metrics, or logs and places them into batches. Batching helps better compress the data and reduce the number of @@ -109,7 +113,3 @@ metadata-key values. The number of batch processors currently in use is exported as the `otelcol_processor_batch_metadata_cardinality` metric. - -[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta -[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib -[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol diff --git a/processor/batchprocessor/batch_processor.go b/processor/batchprocessor/batch_processor.go index cb258867fb4..4853eef524a 100644 --- a/processor/batchprocessor/batch_processor.go +++ b/processor/batchprocessor/batch_processor.go @@ -110,7 +110,7 @@ var _ consumer.Metrics = (*batchProcessor)(nil) var _ consumer.Logs = (*batchProcessor)(nil) // newBatchProcessor returns a new batch processor component. -func newBatchProcessor(set processor.CreateSettings, cfg *Config, batchFunc func() batch, useOtel bool) (*batchProcessor, error) { +func newBatchProcessor(set processor.CreateSettings, cfg *Config, batchFunc func() batch) (*batchProcessor, error) { // use lower-case, to be consistent with http/2 headers. mks := make([]string, len(cfg.MetadataKeys)) for i, k := range cfg.MetadataKeys { @@ -136,7 +136,7 @@ func newBatchProcessor(set processor.CreateSettings, cfg *Config, batchFunc func } } - bpt, err := newBatchProcessorTelemetry(set, bp.batcher.currentMetadataCardinality, useOtel) + bpt, err := newBatchProcessorTelemetry(set, bp.batcher.currentMetadataCardinality) if err != nil { return nil, fmt.Errorf("error creating batch processor telemetry: %w", err) } @@ -350,18 +350,18 @@ func (bp *batchProcessor) ConsumeLogs(ctx context.Context, ld plog.Logs) error { } // newBatchTracesProcessor creates a new batch processor that batches traces by size or with timeout -func newBatchTracesProcessor(set processor.CreateSettings, next consumer.Traces, cfg *Config, useOtel bool) (*batchProcessor, error) { - return newBatchProcessor(set, cfg, func() batch { return newBatchTraces(next) }, useOtel) +func newBatchTracesProcessor(set processor.CreateSettings, next consumer.Traces, cfg *Config) (*batchProcessor, error) { + return newBatchProcessor(set, cfg, func() batch { return newBatchTraces(next) }) } // newBatchMetricsProcessor creates a new batch processor that batches metrics by size or with timeout -func newBatchMetricsProcessor(set processor.CreateSettings, next consumer.Metrics, cfg *Config, useOtel bool) (*batchProcessor, error) { - return newBatchProcessor(set, cfg, func() batch { return newBatchMetrics(next) }, useOtel) +func newBatchMetricsProcessor(set processor.CreateSettings, next consumer.Metrics, cfg *Config) (*batchProcessor, error) { + return newBatchProcessor(set, cfg, func() batch { return newBatchMetrics(next) }) } // newBatchLogsProcessor creates a new batch processor that batches logs by size or with timeout -func newBatchLogsProcessor(set processor.CreateSettings, next consumer.Logs, cfg *Config, useOtel bool) (*batchProcessor, error) { - return newBatchProcessor(set, cfg, func() batch { return newBatchLogs(next) }, useOtel) +func newBatchLogsProcessor(set processor.CreateSettings, next consumer.Logs, cfg *Config) (*batchProcessor, error) { + return newBatchProcessor(set, cfg, func() batch { return newBatchLogs(next) }) } type batchTraces struct { diff --git a/processor/batchprocessor/batch_processor_test.go b/processor/batchprocessor/batch_processor_test.go index 11eaa9b071f..a3a618c0f3e 100644 --- a/processor/batchprocessor/batch_processor_test.go +++ b/processor/batchprocessor/batch_processor_test.go @@ -84,7 +84,7 @@ func TestBatchProcessorSpansDelivered(t *testing.T) { cfg.SendBatchSize = 128 creationSet := processortest.NewNopCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchTracesProcessor(creationSet, sink, cfg, false) + batcher, err := newBatchTracesProcessor(creationSet, sink, cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -127,7 +127,7 @@ func TestBatchProcessorSpansDeliveredEnforceBatchSize(t *testing.T) { cfg.SendBatchMaxSize = 130 creationSet := processortest.NewNopCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchTracesProcessor(creationSet, sink, cfg, false) + batcher, err := newBatchTracesProcessor(creationSet, sink, cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -168,7 +168,7 @@ func TestBatchProcessorSentBySize(t *testing.T) { telemetryTest(t, testBatchProcessorSentBySize) } -func testBatchProcessorSentBySize(t *testing.T, tel testTelemetry, useOtel bool) { +func testBatchProcessorSentBySize(t *testing.T, tel testTelemetry) { sizer := &ptrace.ProtoMarshaler{} sink := new(consumertest.TracesSink) cfg := createDefaultConfig().(*Config) @@ -177,7 +177,7 @@ func testBatchProcessorSentBySize(t *testing.T, tel testTelemetry, useOtel bool) cfg.Timeout = 500 * time.Millisecond creationSet := tel.NewProcessorCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchTracesProcessor(creationSet, sink, cfg, useOtel) + batcher, err := newBatchTracesProcessor(creationSet, sink, cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -223,7 +223,7 @@ func TestBatchProcessorSentBySizeWithMaxSize(t *testing.T) { telemetryTest(t, testBatchProcessorSentBySizeWithMaxSize) } -func testBatchProcessorSentBySizeWithMaxSize(t *testing.T, tel testTelemetry, useOtel bool) { +func testBatchProcessorSentBySizeWithMaxSize(t *testing.T, tel testTelemetry) { sink := new(consumertest.TracesSink) cfg := createDefaultConfig().(*Config) sendBatchSize := 20 @@ -233,7 +233,7 @@ func testBatchProcessorSentBySizeWithMaxSize(t *testing.T, tel testTelemetry, us cfg.Timeout = 500 * time.Millisecond creationSet := tel.NewProcessorCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchTracesProcessor(creationSet, sink, cfg, useOtel) + batcher, err := newBatchTracesProcessor(creationSet, sink, cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -280,7 +280,7 @@ func TestBatchProcessorSentByTimeout(t *testing.T) { creationSet := processortest.NewNopCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchTracesProcessor(creationSet, sink, cfg, false) + batcher, err := newBatchTracesProcessor(creationSet, sink, cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -327,7 +327,7 @@ func TestBatchProcessorTraceSendWhenClosing(t *testing.T) { creationSet := processortest.NewNopCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchTracesProcessor(creationSet, sink, &cfg, false) + batcher, err := newBatchTracesProcessor(creationSet, sink, &cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -358,7 +358,7 @@ func TestBatchMetricProcessor_ReceivingData(t *testing.T) { creationSet := processortest.NewNopCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchMetricsProcessor(creationSet, sink, &cfg, false) + batcher, err := newBatchMetricsProcessor(creationSet, sink, &cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -397,7 +397,7 @@ func TestBatchMetricProcessorBatchSize(t *testing.T) { telemetryTest(t, testBatchMetricProcessorBatchSize) } -func testBatchMetricProcessorBatchSize(t *testing.T, tel testTelemetry, useOtel bool) { +func testBatchMetricProcessorBatchSize(t *testing.T, tel testTelemetry) { sizer := &pmetric.ProtoMarshaler{} // Instantiate the batch processor with low config values to test data @@ -415,7 +415,7 @@ func testBatchMetricProcessorBatchSize(t *testing.T, tel testTelemetry, useOtel creationSet := tel.NewProcessorCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchMetricsProcessor(creationSet, sink, &cfg, useOtel) + batcher, err := newBatchMetricsProcessor(creationSet, sink, &cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -482,7 +482,7 @@ func TestBatchMetricsProcessor_Timeout(t *testing.T) { creationSet := processortest.NewNopCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchMetricsProcessor(creationSet, sink, &cfg, false) + batcher, err := newBatchMetricsProcessor(creationSet, sink, &cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -531,7 +531,7 @@ func TestBatchMetricProcessor_Shutdown(t *testing.T) { creationSet := processortest.NewNopCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchMetricsProcessor(creationSet, sink, &cfg, false) + batcher, err := newBatchMetricsProcessor(creationSet, sink, &cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -630,7 +630,7 @@ func runMetricsProcessorBenchmark(b *testing.B, cfg Config) { creationSet := processortest.NewNopCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed metricsPerRequest := 1000 - batcher, err := newBatchMetricsProcessor(creationSet, sink, &cfg, false) + batcher, err := newBatchMetricsProcessor(creationSet, sink, &cfg) require.NoError(b, err) require.NoError(b, batcher.Start(ctx, componenttest.NewNopHost())) @@ -677,7 +677,7 @@ func TestBatchLogProcessor_ReceivingData(t *testing.T) { creationSet := processortest.NewNopCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchLogsProcessor(creationSet, sink, &cfg, false) + batcher, err := newBatchLogsProcessor(creationSet, sink, &cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -716,7 +716,7 @@ func TestBatchLogProcessor_BatchSize(t *testing.T) { telemetryTest(t, testBatchLogProcessorBatchSize) } -func testBatchLogProcessorBatchSize(t *testing.T, tel testTelemetry, useOtel bool) { +func testBatchLogProcessorBatchSize(t *testing.T, tel testTelemetry) { sizer := &plog.ProtoMarshaler{} // Instantiate the batch processor with low config values to test data @@ -732,7 +732,7 @@ func testBatchLogProcessorBatchSize(t *testing.T, tel testTelemetry, useOtel boo creationSet := tel.NewProcessorCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchLogsProcessor(creationSet, sink, &cfg, useOtel) + batcher, err := newBatchLogsProcessor(creationSet, sink, &cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -780,7 +780,7 @@ func TestBatchLogsProcessor_Timeout(t *testing.T) { creationSet := processortest.NewNopCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchLogsProcessor(creationSet, sink, &cfg, false) + batcher, err := newBatchLogsProcessor(creationSet, sink, &cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -829,7 +829,7 @@ func TestBatchLogProcessor_Shutdown(t *testing.T) { creationSet := processortest.NewNopCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchLogsProcessor(creationSet, sink, &cfg, false) + batcher, err := newBatchLogsProcessor(creationSet, sink, &cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -908,7 +908,7 @@ func TestBatchProcessorSpansBatchedByMetadata(t *testing.T) { cfg.MetadataKeys = []string{"token1", "token2"} creationSet := processortest.NewNopCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchTracesProcessor(creationSet, sink, cfg, false) + batcher, err := newBatchTracesProcessor(creationSet, sink, cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -1001,7 +1001,7 @@ func TestBatchProcessorMetadataCardinalityLimit(t *testing.T) { cfg.MetadataKeys = []string{"token"} cfg.MetadataCardinalityLimit = cardLimit creationSet := processortest.NewNopCreateSettings() - batcher, err := newBatchTracesProcessor(creationSet, sink, cfg, false) + batcher, err := newBatchTracesProcessor(creationSet, sink, cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) @@ -1034,7 +1034,7 @@ func TestBatchProcessorMetadataCardinalityLimit(t *testing.T) { func TestBatchZeroConfig(t *testing.T) { // This is a no-op configuration. No need for a timer, no - // minimum, no mxaimum, just a pass through. + // minimum, no maximum, just a pass through. cfg := Config{} require.NoError(t, cfg.Validate()) @@ -1044,9 +1044,10 @@ func TestBatchZeroConfig(t *testing.T) { sink := new(consumertest.LogsSink) creationSet := processortest.NewNopCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchLogsProcessor(creationSet, sink, &cfg, false) + batcher, err := newBatchLogsProcessor(creationSet, sink, &cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) + defer func() { require.NoError(t, batcher.Shutdown(context.Background())) }() expect := 0 for requestNum := 0; requestNum < requestCount; requestNum++ { @@ -1084,9 +1085,10 @@ func TestBatchSplitOnly(t *testing.T) { sink := new(consumertest.LogsSink) creationSet := processortest.NewNopCreateSettings() creationSet.MetricsLevel = configtelemetry.LevelDetailed - batcher, err := newBatchLogsProcessor(creationSet, sink, &cfg, false) + batcher, err := newBatchLogsProcessor(creationSet, sink, &cfg) require.NoError(t, err) require.NoError(t, batcher.Start(context.Background(), componenttest.NewNopHost())) + defer func() { require.NoError(t, batcher.Shutdown(context.Background())) }() for requestNum := 0; requestNum < requestCount; requestNum++ { ld := testdata.GenerateLogs(logsPerRequest) diff --git a/processor/batchprocessor/factory.go b/processor/batchprocessor/factory.go index b7b57d84111..3af85a816cc 100644 --- a/processor/batchprocessor/factory.go +++ b/processor/batchprocessor/factory.go @@ -1,6 +1,8 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +//go:generate mdatagen metadata.yaml + package batchprocessor // import "go.opentelemetry.io/collector/processor/batchprocessor" import ( @@ -9,14 +11,11 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/consumer" - "go.opentelemetry.io/collector/internal/obsreportconfig" "go.opentelemetry.io/collector/processor" + "go.opentelemetry.io/collector/processor/batchprocessor/internal/metadata" ) const ( - // The value of "type" key in configuration. - typeStr = "batch" - defaultSendBatchSize = uint32(8192) defaultTimeout = 200 * time.Millisecond @@ -29,11 +28,11 @@ const ( // NewFactory returns a new factory for the Batch processor. func NewFactory() processor.Factory { return processor.NewFactory( - typeStr, + metadata.Type, createDefaultConfig, - processor.WithTraces(createTraces, component.StabilityLevelStable), - processor.WithMetrics(createMetrics, component.StabilityLevelStable), - processor.WithLogs(createLogs, component.StabilityLevelStable)) + processor.WithTraces(createTraces, metadata.TracesStability), + processor.WithMetrics(createMetrics, metadata.MetricsStability), + processor.WithLogs(createLogs, metadata.LogsStability)) } func createDefaultConfig() component.Config { @@ -50,7 +49,7 @@ func createTraces( cfg component.Config, nextConsumer consumer.Traces, ) (processor.Traces, error) { - return newBatchTracesProcessor(set, nextConsumer, cfg.(*Config), obsreportconfig.UseOtelForInternalMetricsfeatureGate.IsEnabled()) + return newBatchTracesProcessor(set, nextConsumer, cfg.(*Config)) } func createMetrics( @@ -59,7 +58,7 @@ func createMetrics( cfg component.Config, nextConsumer consumer.Metrics, ) (processor.Metrics, error) { - return newBatchMetricsProcessor(set, nextConsumer, cfg.(*Config), obsreportconfig.UseOtelForInternalMetricsfeatureGate.IsEnabled()) + return newBatchMetricsProcessor(set, nextConsumer, cfg.(*Config)) } func createLogs( @@ -68,5 +67,5 @@ func createLogs( cfg component.Config, nextConsumer consumer.Logs, ) (processor.Logs, error) { - return newBatchLogsProcessor(set, nextConsumer, cfg.(*Config), obsreportconfig.UseOtelForInternalMetricsfeatureGate.IsEnabled()) + return newBatchLogsProcessor(set, nextConsumer, cfg.(*Config)) } diff --git a/processor/batchprocessor/factory_test.go b/processor/batchprocessor/factory_test.go index 1be144c794a..83371f0c1f1 100644 --- a/processor/batchprocessor/factory_test.go +++ b/processor/batchprocessor/factory_test.go @@ -29,12 +29,15 @@ func TestCreateProcessor(t *testing.T) { tp, err := factory.CreateTracesProcessor(context.Background(), creationSet, cfg, nil) assert.NotNil(t, tp) assert.NoError(t, err, "cannot create trace processor") + assert.NoError(t, tp.Shutdown(context.Background())) mp, err := factory.CreateMetricsProcessor(context.Background(), creationSet, cfg, nil) assert.NotNil(t, mp) assert.NoError(t, err, "cannot create metric processor") + assert.NoError(t, mp.Shutdown(context.Background())) lp, err := factory.CreateLogsProcessor(context.Background(), creationSet, cfg, nil) assert.NotNil(t, lp) assert.NoError(t, err, "cannot create logs processor") + assert.NoError(t, lp.Shutdown(context.Background())) } diff --git a/processor/batchprocessor/go.mod b/processor/batchprocessor/go.mod index c32394b97ec..7dd14964033 100644 --- a/processor/batchprocessor/go.mod +++ b/processor/batchprocessor/go.mod @@ -1,63 +1,55 @@ module go.opentelemetry.io/collector/processor/batchprocessor -go 1.20 +go 1.21 require ( - contrib.go.opencensus.io/exporter/prometheus v0.4.2 - github.com/prometheus/client_golang v1.16.0 - github.com/prometheus/client_model v0.4.0 - github.com/prometheus/common v0.44.0 + github.com/prometheus/client_golang v1.19.0 + github.com/prometheus/client_model v0.6.0 + github.com/prometheus/common v0.48.0 github.com/stretchr/testify v1.8.4 - go.opencensus.io v0.24.0 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 - go.opentelemetry.io/collector/confmap v0.85.0 - go.opentelemetry.io/collector/consumer v0.85.0 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/collector/processor v0.85.0 - go.opentelemetry.io/otel v1.18.0 - go.opentelemetry.io/otel/exporters/prometheus v0.41.0 - go.opentelemetry.io/otel/metric v1.18.0 - go.opentelemetry.io/otel/sdk v1.18.0 - go.opentelemetry.io/otel/sdk/metric v0.41.0 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 + go.opentelemetry.io/collector/confmap v0.96.0 + go.opentelemetry.io/collector/consumer v0.96.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/collector/processor v0.96.0 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 + go.opentelemetry.io/otel/sdk/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 - go.uber.org/zap v1.26.0 + go.uber.org/zap v1.27.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect - github.com/prometheus/statsd_exporter v0.22.7 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -69,20 +61,10 @@ replace go.opentelemetry.io/collector/component => ../../component replace go.opentelemetry.io/collector/confmap => ../../confmap -replace go.opentelemetry.io/collector/exporter => ../../exporter - -replace go.opentelemetry.io/collector/extension => ../../extension - replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata -replace go.opentelemetry.io/collector/receiver => ../../receiver - -replace go.opentelemetry.io/collector/semconv => ../../semconv - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension - replace go.opentelemetry.io/collector/consumer => ../../consumer retract ( @@ -90,10 +72,4 @@ retract ( v0.69.0 // Release failed, use v0.69.1 ) -replace go.opentelemetry.io/collector/connector => ../../connector - -replace go.opentelemetry.io/collector/config/confignet => ../../config/confignet - replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry - -replace go.opentelemetry.io/collector/service => ../../service diff --git a/processor/batchprocessor/go.sum b/processor/batchprocessor/go.sum index e3381082600..06616cda85d 100644 --- a/processor/batchprocessor/go.sum +++ b/processor/batchprocessor/go.sum @@ -1,581 +1,126 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/processor/batchprocessor/internal/metadata/generated_status.go b/processor/batchprocessor/internal/metadata/generated_status.go new file mode 100644 index 00000000000..b3956d2b0a2 --- /dev/null +++ b/processor/batchprocessor/internal/metadata/generated_status.go @@ -0,0 +1,29 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("batch") + scopeName = "go.opentelemetry.io/collector/processor/batchprocessor" +) + +const ( + TracesStability = component.StabilityLevelBeta + MetricsStability = component.StabilityLevelBeta + LogsStability = component.StabilityLevelBeta +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} diff --git a/processor/batchprocessor/metadata.yaml b/processor/batchprocessor/metadata.yaml new file mode 100644 index 00000000000..f535dc6c6c7 --- /dev/null +++ b/processor/batchprocessor/metadata.yaml @@ -0,0 +1,7 @@ +type: batch + +status: + class: processor + stability: + beta: [traces, metrics, logs] + distributions: [core, contrib] diff --git a/processor/batchprocessor/metrics.go b/processor/batchprocessor/metrics.go index 85b8ad2b37c..d10727813eb 100644 --- a/processor/batchprocessor/metrics.go +++ b/processor/batchprocessor/metrics.go @@ -5,14 +5,9 @@ package batchprocessor // import "go.opentelemetry.io/collector/processor/batchp import ( "context" - "errors" - "go.opencensus.io/stats" - "go.opencensus.io/stats/view" - "go.opencensus.io/tag" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" - sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.uber.org/multierr" "go.opentelemetry.io/collector/config/configtelemetry" @@ -25,76 +20,17 @@ const ( scopeName = "go.opentelemetry.io/collector/processor/batchprocessor" ) -var ( - processorTagKey = tag.MustNewKey(obsmetrics.ProcessorKey) - statBatchSizeTriggerSend = stats.Int64("batch_size_trigger_send", "Number of times the batch was sent due to a size trigger", stats.UnitDimensionless) - statTimeoutTriggerSend = stats.Int64("timeout_trigger_send", "Number of times the batch was sent due to a timeout trigger", stats.UnitDimensionless) - statBatchSendSize = stats.Int64("batch_send_size", "Number of units in the batch", stats.UnitDimensionless) - statBatchSendSizeBytes = stats.Int64("batch_send_size_bytes", "Number of bytes in batch that was sent", stats.UnitBytes) -) - type trigger int const ( + typeStr = "batch" triggerTimeout trigger = iota triggerBatchSize ) -func init() { - // TODO: Find a way to handle the error. - _ = view.Register(metricViews()...) -} - -// MetricViews returns the metrics views related to batching -func metricViews() []*view.View { - processorTagKeys := []tag.Key{processorTagKey} - - countBatchSizeTriggerSendView := &view.View{ - Name: processorhelper.BuildCustomMetricName(typeStr, statBatchSizeTriggerSend.Name()), - Measure: statBatchSizeTriggerSend, - Description: statBatchSizeTriggerSend.Description(), - TagKeys: processorTagKeys, - Aggregation: view.Sum(), - } - - countTimeoutTriggerSendView := &view.View{ - Name: processorhelper.BuildCustomMetricName(typeStr, statTimeoutTriggerSend.Name()), - Measure: statTimeoutTriggerSend, - Description: statTimeoutTriggerSend.Description(), - TagKeys: processorTagKeys, - Aggregation: view.Sum(), - } - - distributionBatchSendSizeView := &view.View{ - Name: processorhelper.BuildCustomMetricName(typeStr, statBatchSendSize.Name()), - Measure: statBatchSendSize, - Description: statBatchSendSize.Description(), - TagKeys: processorTagKeys, - Aggregation: view.Distribution(10, 25, 50, 75, 100, 250, 500, 750, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 50000, 100000), - } - - distributionBatchSendSizeBytesView := &view.View{ - Name: processorhelper.BuildCustomMetricName(typeStr, statBatchSendSizeBytes.Name()), - Measure: statBatchSendSizeBytes, - Description: statBatchSendSizeBytes.Description(), - TagKeys: processorTagKeys, - Aggregation: view.Distribution(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), - } - - return []*view.View{ - countBatchSizeTriggerSendView, - countTimeoutTriggerSendView, - distributionBatchSendSizeView, - distributionBatchSendSizeBytesView, - } -} - type batchProcessorTelemetry struct { level configtelemetry.Level detailed bool - useOtel bool exportCtx context.Context @@ -106,25 +42,15 @@ type batchProcessorTelemetry struct { batchMetadataCardinality metric.Int64ObservableUpDownCounter } -func newBatchProcessorTelemetry(set processor.CreateSettings, currentMetadataCardinality func() int, useOtel bool) (*batchProcessorTelemetry, error) { - exportCtx, err := tag.New(context.Background(), tag.Insert(processorTagKey, set.ID.String())) - if err != nil { - return nil, err - } - +func newBatchProcessorTelemetry(set processor.CreateSettings, currentMetadataCardinality func() int) (*batchProcessorTelemetry, error) { bpt := &batchProcessorTelemetry{ - useOtel: useOtel, processorAttr: []attribute.KeyValue{attribute.String(obsmetrics.ProcessorKey, set.ID.String())}, - exportCtx: exportCtx, + exportCtx: context.Background(), level: set.MetricsLevel, detailed: set.MetricsLevel == configtelemetry.LevelDetailed, } - // ignore instrument name error as per workaround in https://github.com/open-telemetry/opentelemetry-collector/issues/8346 - // if err != nil { - // return nil, err - // } - if err = bpt.createOtelMetrics(set.MeterProvider, currentMetadataCardinality); err != nil && !errors.Is(err, sdkmetric.ErrInstrumentName) { + if err := bpt.createOtelMetrics(set.MeterProvider, currentMetadataCardinality); err != nil { return nil, err } @@ -132,10 +58,6 @@ func newBatchProcessorTelemetry(set processor.CreateSettings, currentMetadataCar } func (bpt *batchProcessorTelemetry) createOtelMetrics(mp metric.MeterProvider, currentMetadataCardinality func() int) error { - if !bpt.useOtel { - return nil - } - var errors, err error meter := mp.Meter(scopeName) @@ -182,29 +104,6 @@ func (bpt *batchProcessorTelemetry) createOtelMetrics(mp metric.MeterProvider, c } func (bpt *batchProcessorTelemetry) record(trigger trigger, sent, bytes int64) { - if bpt.useOtel { - bpt.recordWithOtel(trigger, sent, bytes) - } else { - bpt.recordWithOC(trigger, sent, bytes) - } -} - -func (bpt *batchProcessorTelemetry) recordWithOC(trigger trigger, sent, bytes int64) { - var triggerMeasure *stats.Int64Measure - switch trigger { - case triggerBatchSize: - triggerMeasure = statBatchSizeTriggerSend - case triggerTimeout: - triggerMeasure = statTimeoutTriggerSend - } - - stats.Record(bpt.exportCtx, triggerMeasure.M(1), statBatchSendSize.M(sent)) - if bpt.detailed { - stats.Record(bpt.exportCtx, statBatchSendSizeBytes.M(bytes)) - } -} - -func (bpt *batchProcessorTelemetry) recordWithOtel(trigger trigger, sent, bytes int64) { switch trigger { case triggerBatchSize: bpt.batchSizeTriggerSend.Add(bpt.exportCtx, 1, metric.WithAttributes(bpt.processorAttr...)) diff --git a/processor/batchprocessor/metrics_test.go b/processor/batchprocessor/metrics_test.go index 2546f0094b8..47345e99d57 100644 --- a/processor/batchprocessor/metrics_test.go +++ b/processor/batchprocessor/metrics_test.go @@ -11,14 +11,12 @@ import ( "net/http/httptest" "testing" - ocprom "contrib.go.opencensus.io/exporter/prometheus" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" io_prometheus_client "github.com/prometheus/client_model/go" "github.com/prometheus/common/expfmt" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opencensus.io/stats/view" otelprom "go.opentelemetry.io/otel/exporters/prometheus" sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" @@ -29,23 +27,8 @@ import ( "go.opentelemetry.io/collector/processor/processortest" ) -func TestBatchProcessorMetrics(t *testing.T) { - viewNames := []string{ - "batch_size_trigger_send", - "timeout_trigger_send", - "batch_send_size", - "batch_send_size_bytes", - } - views := metricViews() - for i, viewName := range viewNames { - assert.Equal(t, "processor/batch/"+viewName, views[i].Name) - } -} - type testTelemetry struct { - meter view.Meter promHandler http.Handler - useOtel bool meterProvider *sdkmetric.MeterProvider } @@ -63,52 +46,28 @@ type expectedMetrics struct { timeoutTrigger float64 } -func telemetryTest(t *testing.T, testFunc func(t *testing.T, tel testTelemetry, useOtel bool)) { - t.Run("WithOC", func(t *testing.T) { - testFunc(t, setupTelemetry(t, false), false) - }) - +func telemetryTest(t *testing.T, testFunc func(t *testing.T, tel testTelemetry)) { t.Run("WithOTel", func(t *testing.T) { - testFunc(t, setupTelemetry(t, true), true) + testFunc(t, setupTelemetry(t)) }) } -func setupTelemetry(t *testing.T, useOtel bool) testTelemetry { - // Unregister the views first since they are registered by the init, this way we reset them. - views := metricViews() - view.Unregister(views...) - require.NoError(t, view.Register(views...)) - - telemetry := testTelemetry{ - meter: view.NewMeter(), - useOtel: useOtel, - } - - if useOtel { - promReg := prometheus.NewRegistry() - exporter, err := otelprom.New(otelprom.WithRegisterer(promReg), otelprom.WithoutUnits(), otelprom.WithoutScopeInfo()) - require.NoError(t, err) +func setupTelemetry(t *testing.T) testTelemetry { + telemetry := testTelemetry{} - telemetry.meterProvider = sdkmetric.NewMeterProvider( - sdkmetric.WithResource(resource.Empty()), - sdkmetric.WithReader(exporter), - sdkmetric.WithView(batchViews()...), - ) - - telemetry.promHandler = promhttp.HandlerFor(promReg, promhttp.HandlerOpts{}) - - t.Cleanup(func() { assert.NoError(t, telemetry.meterProvider.Shutdown(context.Background())) }) - } else { - promReg := prometheus.NewRegistry() + promReg := prometheus.NewRegistry() + exporter, err := otelprom.New(otelprom.WithRegisterer(promReg), otelprom.WithoutUnits(), otelprom.WithoutScopeInfo(), otelprom.WithoutCounterSuffixes()) + require.NoError(t, err) - ocExporter, err := ocprom.NewExporter(ocprom.Options{Registry: promReg}) - require.NoError(t, err) + telemetry.meterProvider = sdkmetric.NewMeterProvider( + sdkmetric.WithResource(resource.Empty()), + sdkmetric.WithReader(exporter), + sdkmetric.WithView(batchViews()...), + ) - telemetry.promHandler = ocExporter + telemetry.promHandler = promhttp.HandlerFor(promReg, promhttp.HandlerOpts{}) - view.RegisterExporter(ocExporter) - t.Cleanup(func() { view.UnregisterExporter(ocExporter) }) - } + t.Cleanup(func() { assert.NoError(t, telemetry.meterProvider.Shutdown(context.Background())) }) return telemetry } @@ -116,17 +75,12 @@ func setupTelemetry(t *testing.T, useOtel bool) testTelemetry { func (tt *testTelemetry) NewProcessorCreateSettings() processor.CreateSettings { settings := processortest.NewNopCreateSettings() settings.MeterProvider = tt.meterProvider - settings.ID = component.NewID(typeStr) + settings.ID = component.MustNewID("batch") return settings } func (tt *testTelemetry) assertMetrics(t *testing.T, expected expectedMetrics) { - for _, v := range metricViews() { - // Forces a flush for the opencensus view data. - _, _ = view.RetrieveData(v.Name) - } - req, err := http.NewRequest(http.MethodGet, "/metrics", nil) require.NoError(t, err) @@ -195,18 +149,13 @@ func (tt *testTelemetry) assertBoundaries(t *testing.T, expected []float64, hist for i := range expected { if math.Abs(expected[i]-got[i]) > 0.00001 { - assert.Failf(t, "unexpected boundary", "boundary for metric '%s' did no match, expected '%f' got '%f'", metric, expected[i], got[i]) + assert.Failf(t, "unexpected boundary", "boundary for metric '%s' did not match, expected '%f' got '%f'", metric, expected[i], got[i]) } } } func (tt *testTelemetry) getMetric(t *testing.T, name string, mtype io_prometheus_client.MetricType, got map[string]*io_prometheus_client.MetricFamily) *io_prometheus_client.Metric { - if tt.useOtel && mtype == io_prometheus_client.MetricType_COUNTER { - // OTel Go suffixes counters with `_total` - name += "_total" - } - metricFamily, ok := got[name] require.True(t, ok, "expected metric '%s' not found", name) require.Equal(t, mtype, metricFamily.GetType()) @@ -232,7 +181,7 @@ func getSingleMetric(metric *io_prometheus_client.MetricFamily) (*io_prometheus_ func assertFloat(t *testing.T, expected, got float64, metric string) { if math.Abs(expected-got) > 0.00001 { - assert.Failf(t, "unexpected metric value", "value for metric '%s' did no match, expected '%f' got '%f'", metric, expected, got) + assert.Failf(t, "unexpected metric value", "value for metric '%s' did not match, expected '%f' got '%f'", metric, expected, got) } } diff --git a/processor/batchprocessor/package_test.go b/processor/batchprocessor/package_test.go new file mode 100644 index 00000000000..58d64e47b57 --- /dev/null +++ b/processor/batchprocessor/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package batchprocessor + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/processor/batchprocessor/splitlogs_test.go b/processor/batchprocessor/splitlogs_test.go index 62c1b878337..d112cd1069e 100644 --- a/processor/batchprocessor/splitlogs_test.go +++ b/processor/batchprocessor/splitlogs_test.go @@ -19,7 +19,7 @@ func TestSplitLogs_noop(t *testing.T) { assert.Equal(t, td, split) i := 0 - td.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().RemoveIf(func(_ plog.LogRecord) bool { + td.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().RemoveIf(func(plog.LogRecord) bool { i++ return i > 5 }) diff --git a/processor/batchprocessor/splitmetrics_test.go b/processor/batchprocessor/splitmetrics_test.go index dea4b6f2d6c..e81cc73b5db 100644 --- a/processor/batchprocessor/splitmetrics_test.go +++ b/processor/batchprocessor/splitmetrics_test.go @@ -19,7 +19,7 @@ func TestSplitMetrics_noop(t *testing.T) { assert.Equal(t, td, split) i := 0 - td.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().RemoveIf(func(_ pmetric.Metric) bool { + td.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().RemoveIf(func(pmetric.Metric) bool { i++ return i > 5 }) diff --git a/processor/batchprocessor/splittraces_test.go b/processor/batchprocessor/splittraces_test.go index 94f115801dd..5316aab66a2 100644 --- a/processor/batchprocessor/splittraces_test.go +++ b/processor/batchprocessor/splittraces_test.go @@ -19,7 +19,7 @@ func TestSplitTraces_noop(t *testing.T) { assert.Equal(t, td, split) i := 0 - td.ResourceSpans().At(0).ScopeSpans().At(0).Spans().RemoveIf(func(_ ptrace.Span) bool { + td.ResourceSpans().At(0).ScopeSpans().At(0).Spans().RemoveIf(func(ptrace.Span) bool { i++ return i > 5 }) diff --git a/processor/go.mod b/processor/go.mod index afc84145c6e..ebb68ddd8da 100644 --- a/processor/go.mod +++ b/processor/go.mod @@ -1,64 +1,54 @@ module go.opentelemetry.io/collector/processor -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opencensus.io v0.24.0 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 - go.opentelemetry.io/collector/consumer v0.85.0 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/otel v1.18.0 - go.opentelemetry.io/otel/metric v1.18.0 - go.opentelemetry.io/otel/sdk/metric v0.41.0 - go.opentelemetry.io/otel/trace v1.18.0 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 + go.opentelemetry.io/collector/consumer v0.96.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 - go.uber.org/zap v1.26.0 + go.uber.org/zap v1.27.0 ) require ( - contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect - github.com/prometheus/statsd_exporter v0.22.7 // indirect - go.opentelemetry.io/collector/confmap v0.85.0 // indirect - go.opentelemetry.io/collector/exporter v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/receiver v0.85.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect - go.opentelemetry.io/otel/sdk v1.18.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector/confmap v0.96.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -70,24 +60,8 @@ replace go.opentelemetry.io/collector/confmap => ../confmap replace go.opentelemetry.io/collector/consumer => ../consumer -replace go.opentelemetry.io/collector/exporter => ../exporter - -replace go.opentelemetry.io/collector/extension => ../extension - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../extension/zpagesextension - replace go.opentelemetry.io/collector/featuregate => ../featuregate replace go.opentelemetry.io/collector/pdata => ../pdata -replace go.opentelemetry.io/collector/receiver => ../receiver - -replace go.opentelemetry.io/collector/semconv => ../semconv - -replace go.opentelemetry.io/collector/connector => ../connector - -replace go.opentelemetry.io/collector/config/confignet => ../config/confignet - replace go.opentelemetry.io/collector/config/configtelemetry => ../config/configtelemetry - -replace go.opentelemetry.io/collector/service => ../service diff --git a/processor/go.sum b/processor/go.sum index 15d68a28c23..06616cda85d 100644 --- a/processor/go.sum +++ b/processor/go.sum @@ -1,582 +1,126 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/processor/memorylimiterprocessor/README.md b/processor/memorylimiterprocessor/README.md index e0e4f22a22e..6f5e51da789 100644 --- a/processor/memorylimiterprocessor/README.md +++ b/processor/memorylimiterprocessor/README.md @@ -1,68 +1,85 @@ # Memory Limiter Processor -| Status | | -| ------------------------ | --------------------- | -| Stability | [beta] | -| Supported pipeline types | traces, metrics, logs | -| Distributions | [core], [contrib] | + +| Status | | +| ------------- |-----------| +| Stability | [beta]: traces, metrics, logs | +| Distributions | [core], [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aprocessor%2Fmemorylimiter%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aprocessor%2Fmemorylimiter) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aprocessor%2Fmemorylimiter%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aprocessor%2Fmemorylimiter) | + +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + + +## Overview The memory limiter processor is used to prevent out of memory situations on the collector. Given that the amount and type of data the collector processes is -environment specific and resource utilization of the collector is also dependent +environment-specific and resource utilization of the collector is also dependent on the configured processors, it is important to put checks in place regarding memory usage. - -The memory_limiter processor allows to perform periodic checks of memory -usage if it exceeds defined limits will begin refusing data and forcing GC to reduce -memory consumption. -The memory_limiter uses soft and hard memory limits. Hard limit is always above or equal -the soft limit. +## Functionality + +The memory limiter processor performs periodic checks of memory +usage and will begin refusing data and forcing GC to reduce +memory consumption when defined limits have been exceeded. -When the memory usage exceeds the soft limit the processor will enter the memory limited -mode and will start refusing the data by returning errors to the preceding component +The processor uses soft and hard memory limits. The hard limit is defined via the +`limit_mib` configuration option, and is always above or equal +to the soft limit. The difference between the soft limit and hard limit is defined via +the `spike_limit_mib` configuration option. + +The processor will enter memory limited mode and will start refusing the data when +memory usage exceeds the soft limit. This is done by returning errors to the preceding component in the pipeline that made the ConsumeLogs/Trace/Metrics function call. -The preceding component should be normally a receiver. In memory limited mode the error returned by ConsumeLogs/Trace/Metrics function is a non-permanent error. When receivers see this error they are expected to retry sending -the same data. The receivers may also apply a backpressure to their data sources -in order to slow down the inflow of data into the Collector and allow the memory usage -to go below the limits. +the same data. The receivers may also apply backpressure to their own data sources +in order to slow the inflow of data into the Collector, and to allow memory usage +to go below the set limits. ->Warning: if the component preceding the memory limiter in the pipeline does not correctly -retry and send the data again after ConsumeLogs/Trace/Metrics functions return then that -data will be permanently lost. We consider such components incorrectly implemented. +> Warning: Data will be permanently lost if the component preceding the memory limiter +> in the telemetry pipeline does not correctly retry sending data after it has +> been refused by the memory limiter. +> We consider such components to be incorrectly implemented. -When the memory usage is above the hard limit in addition to refusing the data the -processor will forcedly perform garbage collection in order to try to free memory. +When the memory usage is above the hard limit the processor will additionally +force garbage collection to be performed. -When the memory usage drop below the soft limit, the normal operation is resumed (data -will no longer be refused and no forced garbage collection will be performed). +Normal operation is resumed when memory usage drops below the soft limit, meaning data +will no longer be refused and the processor won't force garbage collection to +be performed. -The difference between the soft limit and hard limits is defined via `spike_limit_mib` -configuration option. The value of this option should be selected in a way that ensures -that between the memory check intervals the memory usage cannot increase by more than this -value (otherwise memory usage may exceed the hard limit - even if temporarily). -A good starting point for `spike_limit_mib` is 20% of the hard limit. Bigger -`spike_limit_mib` values may be necessary for spiky traffic or for longer check intervals. +## Best Practices Note that while the processor can help mitigate out of memory situations, it is not a replacement for properly sizing and configuring the collector. Keep in mind that if the soft limit is crossed, the collector will return errors to all receive operations until enough memory is freed. This may -eventually result in dropped data since the receivers may not be able to hold back -and retry the data indefinitely. +eventually result in dropped data since the receivers may not be able to +retry the data indefinitely. + +It is highly recommended to configure the `GOMEMLIMIT` +[environment variable](https://pkg.go.dev/runtime#hdr-Environment_Variables) as well +as the `memory_limiter` processor on every collector. `GOMEMLIMIT` should be set to +80% of the hard memory limit of your collector. For the `memory_limiter` processor, the +best practice is to add it as the first processor in a pipeline. This is to ensure that backpressure +can be sent to applicable receivers and minimize the likelihood of dropped data when the +`memory_limiter` gets triggered. + +The value of the `spike_limit_mib` configuration option should be selected in a way +that ensures that memory usage cannot increase by more than this value within a single +memory check interval. Otherwise, memory usage may exceed the hard limit, even if temporarily. +A good starting point for `spike_limit_mib` is 20% of the hard limit. Bigger +`spike_limit_mib` values may be necessary for spiky traffic or for longer check intervals. + -It is highly recommended to configure `ballastextension` as well as the -`memory_limiter` processor on every collector. The ballast should be configured to -be 1/3 to 1/2 of the memory allocated to the collector. The memory_limiter -processor should be the first processor defined in the pipeline (immediately after -the receivers). This is to ensure that backpressure can be sent to applicable -receivers and minimize the likelihood of dropped data when the memory_limiter gets -triggered. +## Configuration -Please refer to [config.go](./config.go) for the config spec. +Please refer to [memorylimiter.go](../../internal/memorylimiter/memorylimiter.go) for the config spec. The following configuration options **must be changed**: - `check_interval` (default = 0s): Time between measurements of memory @@ -107,9 +124,6 @@ processors: spike_limit_percentage: 30 ``` -Refer to [config.yaml](./testdata/config.yaml) for detailed +Refer to [config.yaml](../../internal/memorylimiter/testdata/config.yaml) for detailed examples on using the processor. -[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta -[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib -[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol diff --git a/processor/memorylimiterprocessor/config.go b/processor/memorylimiterprocessor/config.go index e16ebeb67ee..8d7f28e14e5 100644 --- a/processor/memorylimiterprocessor/config.go +++ b/processor/memorylimiterprocessor/config.go @@ -1,43 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -// Package memorylimiterprocessor provides a processor for OpenTelemetry Service pipeline -// that refuses data on the pipeline according to the current state of memory usage. package memorylimiterprocessor // import "go.opentelemetry.io/collector/processor/memorylimiterprocessor" +import "go.opentelemetry.io/collector/internal/memorylimiter" -import ( - "time" - - "go.opentelemetry.io/collector/component" -) - -// Config defines configuration for memory memoryLimiter processor. -type Config struct { - // CheckInterval is the time between measurements of memory usage for the - // purposes of avoiding going over the limits. Defaults to zero, so no - // checks will be performed. - CheckInterval time.Duration `mapstructure:"check_interval"` - - // MemoryLimitMiB is the maximum amount of memory, in MiB, targeted to be - // allocated by the process. - MemoryLimitMiB uint32 `mapstructure:"limit_mib"` - - // MemorySpikeLimitMiB is the maximum, in MiB, spike expected between the - // measurements of memory usage. - MemorySpikeLimitMiB uint32 `mapstructure:"spike_limit_mib"` - - // MemoryLimitPercentage is the maximum amount of memory, in %, targeted to be - // allocated by the process. The fixed memory settings MemoryLimitMiB has a higher precedence. - MemoryLimitPercentage uint32 `mapstructure:"limit_percentage"` - - // MemorySpikePercentage is the maximum, in percents against the total memory, - // spike expected between the measurements of memory usage. - MemorySpikePercentage uint32 `mapstructure:"spike_limit_percentage"` -} - -var _ component.Config = (*Config)(nil) - -// Validate checks if the processor configuration is valid -func (cfg *Config) Validate() error { - return nil -} +type Config = memorylimiter.Config diff --git a/processor/memorylimiterprocessor/config_test.go b/processor/memorylimiterprocessor/config_test.go deleted file mode 100644 index 076d037dba0..00000000000 --- a/processor/memorylimiterprocessor/config_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package memorylimiterprocessor - -import ( - "path/filepath" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/confmap" - "go.opentelemetry.io/collector/confmap/confmaptest" -) - -func TestUnmarshalDefaultConfig(t *testing.T) { - factory := NewFactory() - cfg := factory.CreateDefaultConfig() - assert.NoError(t, component.UnmarshalConfig(confmap.New(), cfg)) - assert.Equal(t, factory.CreateDefaultConfig(), cfg) -} - -func TestUnmarshalConfig(t *testing.T) { - cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) - require.NoError(t, err) - factory := NewFactory() - cfg := factory.CreateDefaultConfig() - assert.NoError(t, component.UnmarshalConfig(cm, cfg)) - assert.Equal(t, - &Config{ - CheckInterval: 5 * time.Second, - MemoryLimitMiB: 4000, - MemorySpikeLimitMiB: 500, - }, cfg) -} diff --git a/processor/memorylimiterprocessor/factory.go b/processor/memorylimiterprocessor/factory.go index 6f345a14c6a..67ae80c996b 100644 --- a/processor/memorylimiterprocessor/factory.go +++ b/processor/memorylimiterprocessor/factory.go @@ -1,6 +1,8 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +//go:generate mdatagen metadata.yaml + package memorylimiterprocessor // import "go.opentelemetry.io/collector/processor/memorylimiterprocessor" import ( @@ -10,34 +12,30 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/processor" + "go.opentelemetry.io/collector/processor/memorylimiterprocessor/internal/metadata" "go.opentelemetry.io/collector/processor/processorhelper" ) -const ( - // The value of "type" Attribute Key in configuration. - typeStr = "memory_limiter" -) - var processorCapabilities = consumer.Capabilities{MutatesData: false} type factory struct { // memoryLimiters stores memoryLimiter instances with unique configs that multiple processors can reuse. // This avoids running multiple memory checks (ie: GC) for every processor using the same processor config. - memoryLimiters map[component.Config]*memoryLimiter + memoryLimiters map[component.Config]*memoryLimiterProcessor lock sync.Mutex } // NewFactory returns a new factory for the Memory Limiter processor. func NewFactory() processor.Factory { f := &factory{ - memoryLimiters: map[component.Config]*memoryLimiter{}, + memoryLimiters: map[component.Config]*memoryLimiterProcessor{}, } return processor.NewFactory( - typeStr, + metadata.Type, createDefaultConfig, - processor.WithTraces(f.createTracesProcessor, component.StabilityLevelBeta), - processor.WithMetrics(f.createMetricsProcessor, component.StabilityLevelBeta), - processor.WithLogs(f.createLogsProcessor, component.StabilityLevelBeta)) + processor.WithTraces(f.createTracesProcessor, metadata.TracesStability), + processor.WithMetrics(f.createMetricsProcessor, metadata.MetricsStability), + processor.WithLogs(f.createLogsProcessor, metadata.LogsStability)) } // CreateDefaultConfig creates the default configuration for processor. Notice @@ -99,7 +97,7 @@ func (f *factory) createLogsProcessor( // getMemoryLimiter checks if we have a cached memoryLimiter with a specific config, // otherwise initialize and add one to the store. -func (f *factory) getMemoryLimiter(set processor.CreateSettings, cfg component.Config) (*memoryLimiter, error) { +func (f *factory) getMemoryLimiter(set processor.CreateSettings, cfg component.Config) (*memoryLimiterProcessor, error) { f.lock.Lock() defer f.lock.Unlock() @@ -107,7 +105,7 @@ func (f *factory) getMemoryLimiter(set processor.CreateSettings, cfg component.C return memLimiter, nil } - memLimiter, err := newMemoryLimiter(set, cfg.(*Config)) + memLimiter, err := newMemoryLimiterProcessor(set, cfg.(*Config)) if err != nil { return nil, err } diff --git a/processor/memorylimiterprocessor/factory_test.go b/processor/memorylimiterprocessor/factory_test.go index e7a274dba06..b8cca4c6d20 100644 --- a/processor/memorylimiterprocessor/factory_test.go +++ b/processor/memorylimiterprocessor/factory_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/internal/memorylimiter" "go.opentelemetry.io/collector/processor/processortest" ) @@ -31,38 +32,25 @@ func TestCreateProcessor(t *testing.T) { cfg := factory.CreateDefaultConfig() - // This processor can't be created with the default config. - tp, err := factory.CreateTracesProcessor(context.Background(), processortest.NewNopCreateSettings(), cfg, consumertest.NewNop()) - assert.Nil(t, tp) - assert.Error(t, err, "created processor with invalid settings") - - mp, err := factory.CreateMetricsProcessor(context.Background(), processortest.NewNopCreateSettings(), cfg, consumertest.NewNop()) - assert.Nil(t, mp) - assert.Error(t, err, "created processor with invalid settings") - - lp, err := factory.CreateLogsProcessor(context.Background(), processortest.NewNopCreateSettings(), cfg, consumertest.NewNop()) - assert.Nil(t, lp) - assert.Error(t, err, "created processor with invalid settings") - // Create processor with a valid config. pCfg := cfg.(*Config) pCfg.MemoryLimitMiB = 5722 pCfg.MemorySpikeLimitMiB = 1907 pCfg.CheckInterval = 100 * time.Millisecond - tp, err = factory.CreateTracesProcessor(context.Background(), processortest.NewNopCreateSettings(), cfg, consumertest.NewNop()) + tp, err := factory.CreateTracesProcessor(context.Background(), processortest.NewNopCreateSettings(), cfg, consumertest.NewNop()) assert.NoError(t, err) assert.NotNil(t, tp) // test if we can shutdown a monitoring routine that has not started - assert.ErrorIs(t, tp.Shutdown(context.Background()), errShutdownNotStarted) + assert.ErrorIs(t, tp.Shutdown(context.Background()), memorylimiter.ErrShutdownNotStarted) assert.NoError(t, tp.Start(context.Background(), componenttest.NewNopHost())) - mp, err = factory.CreateMetricsProcessor(context.Background(), processortest.NewNopCreateSettings(), cfg, consumertest.NewNop()) + mp, err := factory.CreateMetricsProcessor(context.Background(), processortest.NewNopCreateSettings(), cfg, consumertest.NewNop()) assert.NoError(t, err) assert.NotNil(t, mp) assert.NoError(t, mp.Start(context.Background(), componenttest.NewNopHost())) - lp, err = factory.CreateLogsProcessor(context.Background(), processortest.NewNopCreateSettings(), cfg, consumertest.NewNop()) + lp, err := factory.CreateLogsProcessor(context.Background(), processortest.NewNopCreateSettings(), cfg, consumertest.NewNop()) assert.NoError(t, err) assert.NotNil(t, lp) assert.NoError(t, lp.Start(context.Background(), componenttest.NewNopHost())) @@ -71,11 +59,11 @@ func TestCreateProcessor(t *testing.T) { assert.NoError(t, tp.Shutdown(context.Background())) assert.NoError(t, mp.Shutdown(context.Background())) // verify that no monitoring routine is running - assert.Error(t, tp.Shutdown(context.Background())) + assert.ErrorIs(t, tp.Shutdown(context.Background()), memorylimiter.ErrShutdownNotStarted) // start and shutdown a new monitoring routine assert.NoError(t, lp.Start(context.Background(), componenttest.NewNopHost())) assert.NoError(t, lp.Shutdown(context.Background())) // calling it again should throw an error - assert.ErrorIs(t, lp.Shutdown(context.Background()), errShutdownNotStarted) + assert.ErrorIs(t, lp.Shutdown(context.Background()), memorylimiter.ErrShutdownNotStarted) } diff --git a/processor/memorylimiterprocessor/go.mod b/processor/memorylimiterprocessor/go.mod index 07dd7ceb11c..a82f08150c3 100644 --- a/processor/memorylimiterprocessor/go.mod +++ b/processor/memorylimiterprocessor/go.mod @@ -1,56 +1,62 @@ module go.opentelemetry.io/collector/processor/memorylimiterprocessor -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 - go.opentelemetry.io/collector/confmap v0.85.0 - go.opentelemetry.io/collector/consumer v0.85.0 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/collector/processor v0.85.0 - go.uber.org/zap v1.26.0 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/consumer v0.96.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/collector/processor v0.96.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 ) require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/shirou/gopsutil/v3 v3.24.1 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/sdk v1.18.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/confmap v0.96.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -62,20 +68,10 @@ replace go.opentelemetry.io/collector/component => ../../component replace go.opentelemetry.io/collector/confmap => ../../confmap -replace go.opentelemetry.io/collector/exporter => ../../exporter - -replace go.opentelemetry.io/collector/extension => ../../extension - replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata -replace go.opentelemetry.io/collector/receiver => ../../receiver - -replace go.opentelemetry.io/collector/semconv => ../../semconv - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension - replace go.opentelemetry.io/collector/consumer => ../../consumer retract ( @@ -83,10 +79,4 @@ retract ( v0.69.0 // Release failed, use v0.69.1 ) -replace go.opentelemetry.io/collector/connector => ../../connector - -replace go.opentelemetry.io/collector/config/confignet => ../../config/confignet - replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry - -replace go.opentelemetry.io/collector/service => ../../service diff --git a/processor/memorylimiterprocessor/go.sum b/processor/memorylimiterprocessor/go.sum index 22c6f66a665..7a84d36f2e3 100644 --- a/processor/memorylimiterprocessor/go.sum +++ b/processor/memorylimiterprocessor/go.sum @@ -1,57 +1,30 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -60,17 +33,16 @@ github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NI github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -82,15 +54,18 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= -github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= +github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -99,7 +74,6 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= @@ -110,51 +84,38 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -162,17 +123,14 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -180,38 +138,17 @@ 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/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/processor/memorylimiterprocessor/internal/metadata/generated_status.go b/processor/memorylimiterprocessor/internal/metadata/generated_status.go new file mode 100644 index 00000000000..0b2058d89df --- /dev/null +++ b/processor/memorylimiterprocessor/internal/metadata/generated_status.go @@ -0,0 +1,29 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("memory_limiter") + scopeName = "go.opentelemetry.io/collector/processor/memorylimiterprocessor" +) + +const ( + TracesStability = component.StabilityLevelBeta + MetricsStability = component.StabilityLevelBeta + LogsStability = component.StabilityLevelBeta +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} diff --git a/processor/memorylimiterprocessor/memorylimiter.go b/processor/memorylimiterprocessor/memorylimiter.go index 0520e13339a..6d7368bfb6a 100644 --- a/processor/memorylimiterprocessor/memorylimiter.go +++ b/processor/memorylimiterprocessor/memorylimiter.go @@ -5,17 +5,9 @@ package memorylimiterprocessor // import "go.opentelemetry.io/collector/processo import ( "context" - "errors" - "fmt" - "runtime" - "sync" - "sync/atomic" - "time" - - "go.uber.org/zap" "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/internal/iruntime" + "go.opentelemetry.io/collector/internal/memorylimiter" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/ptrace" @@ -23,87 +15,17 @@ import ( "go.opentelemetry.io/collector/processor/processorhelper" ) -const ( - mibBytes = 1024 * 1024 -) - -var ( - // errDataRefused will be returned to callers of ConsumeTraceData to indicate - // that data is being refused due to high memory usage. - errDataRefused = errors.New("data refused due to high memory usage") - - // Construction errors - - errCheckIntervalOutOfRange = errors.New( - "checkInterval must be greater than zero") - - errLimitOutOfRange = errors.New( - "memAllocLimit or memoryLimitPercentage must be greater than zero") - - errMemSpikeLimitOutOfRange = errors.New( - "memSpikeLimit must be smaller than memAllocLimit") - - errPercentageLimitOutOfRange = errors.New( - "memoryLimitPercentage and memorySpikePercentage must be greater than zero and less than or equal to hundred", - ) - - errShutdownNotStarted = errors.New("no existing monitoring routine is running") -) - -// make it overridable by tests -var getMemoryFn = iruntime.TotalMemory - -type memoryLimiter struct { - usageChecker memUsageChecker - - memCheckWait time.Duration - ballastSize uint64 - - // mustRefuse is used to indicate when data should be refused. - mustRefuse *atomic.Bool - - ticker *time.Ticker - - lastGCDone time.Time - - // The function to read the mem values is set as a reference to help with - // testing different values. - readMemStatsFn func(m *runtime.MemStats) - - // Fields used for logging. - logger *zap.Logger - configMismatchedLogged bool - - obsrep *processorhelper.ObsReport - - refCounterLock sync.Mutex - refCounter int +type memoryLimiterProcessor struct { + memlimiter *memorylimiter.MemoryLimiter + obsrep *processorhelper.ObsReport } -// Minimum interval between forced GC when in soft limited mode. We don't want to -// do GCs too frequently since it is a CPU-heavy operation. -const minGCIntervalWhenSoftLimited = 10 * time.Second - // newMemoryLimiter returns a new memorylimiter processor. -func newMemoryLimiter(set processor.CreateSettings, cfg *Config) (*memoryLimiter, error) { - if cfg.CheckInterval <= 0 { - return nil, errCheckIntervalOutOfRange - } - if cfg.MemoryLimitMiB == 0 && cfg.MemoryLimitPercentage == 0 { - return nil, errLimitOutOfRange - } - - logger := set.Logger - usageChecker, err := getMemUsageChecker(cfg, logger) +func newMemoryLimiterProcessor(set processor.CreateSettings, cfg *Config) (*memoryLimiterProcessor, error) { + ml, err := memorylimiter.NewMemoryLimiter(cfg, set.Logger) if err != nil { return nil, err } - - logger.Info("Memory limiter configured", - zap.Uint64("limit_mib", usageChecker.memAllocLimit/mibBytes), - zap.Uint64("spike_limit_mib", usageChecker.memSpikeLimit/mibBytes), - zap.Duration("check_interval", cfg.CheckInterval)) - obsrep, err := processorhelper.NewObsReport(processorhelper.ObsReportSettings{ ProcessorID: set.ID, ProcessorCreateSettings: set, @@ -112,230 +34,72 @@ func newMemoryLimiter(set processor.CreateSettings, cfg *Config) (*memoryLimiter return nil, err } - ml := &memoryLimiter{ - usageChecker: *usageChecker, - memCheckWait: cfg.CheckInterval, - ticker: time.NewTicker(cfg.CheckInterval), - readMemStatsFn: runtime.ReadMemStats, - logger: logger, - mustRefuse: &atomic.Bool{}, - obsrep: obsrep, + p := &memoryLimiterProcessor{ + memlimiter: ml, + obsrep: obsrep, } - return ml, nil -} - -func getMemUsageChecker(cfg *Config, logger *zap.Logger) (*memUsageChecker, error) { - memAllocLimit := uint64(cfg.MemoryLimitMiB) * mibBytes - memSpikeLimit := uint64(cfg.MemorySpikeLimitMiB) * mibBytes - if cfg.MemoryLimitMiB != 0 { - return newFixedMemUsageChecker(memAllocLimit, memSpikeLimit) - } - totalMemory, err := getMemoryFn() - if err != nil { - return nil, fmt.Errorf("failed to get total memory, use fixed memory settings (limit_mib): %w", err) - } - logger.Info("Using percentage memory limiter", - zap.Uint64("total_memory_mib", totalMemory/mibBytes), - zap.Uint32("limit_percentage", cfg.MemoryLimitPercentage), - zap.Uint32("spike_limit_percentage", cfg.MemorySpikePercentage)) - return newPercentageMemUsageChecker(totalMemory, uint64(cfg.MemoryLimitPercentage), uint64(cfg.MemorySpikePercentage)) + return p, nil } -func (ml *memoryLimiter) start(_ context.Context, host component.Host) error { - extensions := host.GetExtensions() - for _, extension := range extensions { - if ext, ok := extension.(interface{ GetBallastSize() uint64 }); ok { - ml.ballastSize = ext.GetBallastSize() - break - } - } - ml.startMonitoring() - return nil +func (p *memoryLimiterProcessor) start(ctx context.Context, host component.Host) error { + return p.memlimiter.Start(ctx, host) } -func (ml *memoryLimiter) shutdown(context.Context) error { - ml.refCounterLock.Lock() - defer ml.refCounterLock.Unlock() - - if ml.refCounter == 0 { - return errShutdownNotStarted - } else if ml.refCounter == 1 { - ml.ticker.Stop() - } - ml.refCounter-- - return nil +func (p *memoryLimiterProcessor) shutdown(ctx context.Context) error { + return p.memlimiter.Shutdown(ctx) } -func (ml *memoryLimiter) processTraces(ctx context.Context, td ptrace.Traces) (ptrace.Traces, error) { +func (p *memoryLimiterProcessor) processTraces(ctx context.Context, td ptrace.Traces) (ptrace.Traces, error) { numSpans := td.SpanCount() - if ml.mustRefuse.Load() { + if p.memlimiter.MustRefuse() { // TODO: actually to be 100% sure that this is "refused" and not "dropped" // it is necessary to check the pipeline to see if this is directly connected // to a receiver (ie.: a receiver is on the call stack). For now it // assumes that the pipeline is properly configured and a receiver is on the // callstack and that the receiver will correctly retry the refused data again. - ml.obsrep.TracesRefused(ctx, numSpans) - - return td, errDataRefused + p.obsrep.TracesRefused(ctx, numSpans) + return td, memorylimiter.ErrDataRefused } // Even if the next consumer returns error record the data as accepted by // this processor. - ml.obsrep.TracesAccepted(ctx, numSpans) + p.obsrep.TracesAccepted(ctx, numSpans) return td, nil } -func (ml *memoryLimiter) processMetrics(ctx context.Context, md pmetric.Metrics) (pmetric.Metrics, error) { +func (p *memoryLimiterProcessor) processMetrics(ctx context.Context, md pmetric.Metrics) (pmetric.Metrics, error) { numDataPoints := md.DataPointCount() - if ml.mustRefuse.Load() { + if p.memlimiter.MustRefuse() { // TODO: actually to be 100% sure that this is "refused" and not "dropped" // it is necessary to check the pipeline to see if this is directly connected // to a receiver (ie.: a receiver is on the call stack). For now it // assumes that the pipeline is properly configured and a receiver is on the // callstack. - ml.obsrep.MetricsRefused(ctx, numDataPoints) - return md, errDataRefused + p.obsrep.MetricsRefused(ctx, numDataPoints) + return md, memorylimiter.ErrDataRefused } // Even if the next consumer returns error record the data as accepted by // this processor. - ml.obsrep.MetricsAccepted(ctx, numDataPoints) + p.obsrep.MetricsAccepted(ctx, numDataPoints) return md, nil } -func (ml *memoryLimiter) processLogs(ctx context.Context, ld plog.Logs) (plog.Logs, error) { +func (p *memoryLimiterProcessor) processLogs(ctx context.Context, ld plog.Logs) (plog.Logs, error) { numRecords := ld.LogRecordCount() - if ml.mustRefuse.Load() { + if p.memlimiter.MustRefuse() { // TODO: actually to be 100% sure that this is "refused" and not "dropped" // it is necessary to check the pipeline to see if this is directly connected // to a receiver (ie.: a receiver is on the call stack). For now it // assumes that the pipeline is properly configured and a receiver is on the // callstack. - ml.obsrep.LogsRefused(ctx, numRecords) - - return ld, errDataRefused + p.obsrep.LogsRefused(ctx, numRecords) + return ld, memorylimiter.ErrDataRefused } // Even if the next consumer returns error record the data as accepted by // this processor. - ml.obsrep.LogsAccepted(ctx, numRecords) + p.obsrep.LogsAccepted(ctx, numRecords) return ld, nil } - -func (ml *memoryLimiter) readMemStats() *runtime.MemStats { - ms := &runtime.MemStats{} - ml.readMemStatsFn(ms) - // If proper configured ms.Alloc should be at least ml.ballastSize but since - // a misconfiguration is possible check for that here. - if ms.Alloc >= ml.ballastSize { - ms.Alloc -= ml.ballastSize - } else if !ml.configMismatchedLogged { - // This indicates misconfiguration. Log it once. - ml.configMismatchedLogged = true - ml.logger.Warn(`"size_mib" in ballast extension is likely incorrectly configured.`) - } - - return ms -} - -// startMonitoring starts a single ticker'd goroutine per instance -// that will check memory usage every checkInterval period. -func (ml *memoryLimiter) startMonitoring() { - ml.refCounterLock.Lock() - defer ml.refCounterLock.Unlock() - - ml.refCounter++ - if ml.refCounter == 1 { - go func() { - for range ml.ticker.C { - ml.checkMemLimits() - } - }() - } -} - -func memstatToZapField(ms *runtime.MemStats) zap.Field { - return zap.Uint64("cur_mem_mib", ms.Alloc/mibBytes) -} - -func (ml *memoryLimiter) doGCandReadMemStats() *runtime.MemStats { - runtime.GC() - ml.lastGCDone = time.Now() - ms := ml.readMemStats() - ml.logger.Info("Memory usage after GC.", memstatToZapField(ms)) - return ms -} - -func (ml *memoryLimiter) checkMemLimits() { - ms := ml.readMemStats() - - ml.logger.Debug("Currently used memory.", memstatToZapField(ms)) - - if ml.usageChecker.aboveHardLimit(ms) { - ml.logger.Warn("Memory usage is above hard limit. Forcing a GC.", memstatToZapField(ms)) - ms = ml.doGCandReadMemStats() - } - - // Remember current state. - wasRefusing := ml.mustRefuse.Load() - - // Check if the memory usage is above the soft limit. - mustRefuse := ml.usageChecker.aboveSoftLimit(ms) - - if wasRefusing && !mustRefuse { - // Was previously refusing but enough memory is available now, no need to limit. - ml.logger.Info("Memory usage back within limits. Resuming normal operation.", memstatToZapField(ms)) - } - - if !wasRefusing && mustRefuse { - // We are above soft limit, do a GC if it wasn't done recently and see if - // it brings memory usage below the soft limit. - if time.Since(ml.lastGCDone) > minGCIntervalWhenSoftLimited { - ml.logger.Info("Memory usage is above soft limit. Forcing a GC.", memstatToZapField(ms)) - ms = ml.doGCandReadMemStats() - // Check the limit again to see if GC helped. - mustRefuse = ml.usageChecker.aboveSoftLimit(ms) - } - - if mustRefuse { - ml.logger.Warn("Memory usage is above soft limit. Refusing data.", memstatToZapField(ms)) - } - } - - ml.mustRefuse.Store(mustRefuse) -} - -type memUsageChecker struct { - memAllocLimit uint64 - memSpikeLimit uint64 -} - -func (d memUsageChecker) aboveSoftLimit(ms *runtime.MemStats) bool { - return ms.Alloc >= d.memAllocLimit-d.memSpikeLimit -} - -func (d memUsageChecker) aboveHardLimit(ms *runtime.MemStats) bool { - return ms.Alloc >= d.memAllocLimit -} - -func newFixedMemUsageChecker(memAllocLimit, memSpikeLimit uint64) (*memUsageChecker, error) { - if memSpikeLimit >= memAllocLimit { - return nil, errMemSpikeLimitOutOfRange - } - if memSpikeLimit == 0 { - // If spike limit is unspecified use 20% of mem limit. - memSpikeLimit = memAllocLimit / 5 - } - return &memUsageChecker{ - memAllocLimit: memAllocLimit, - memSpikeLimit: memSpikeLimit, - }, nil -} - -func newPercentageMemUsageChecker(totalMemory uint64, percentageLimit, percentageSpike uint64) (*memUsageChecker, error) { - if percentageLimit > 100 || percentageLimit <= 0 || percentageSpike > 100 || percentageSpike <= 0 { - return nil, errPercentageLimitOutOfRange - } - return newFixedMemUsageChecker(percentageLimit*totalMemory/100, percentageSpike*totalMemory/100) -} diff --git a/processor/memorylimiterprocessor/memorylimiter_test.go b/processor/memorylimiterprocessor/memorylimiter_test.go index c13e1b90b8b..626bf877d7c 100644 --- a/processor/memorylimiterprocessor/memorylimiter_test.go +++ b/processor/memorylimiterprocessor/memorylimiter_test.go @@ -6,20 +6,17 @@ package memorylimiterprocessor import ( "context" "runtime" - "sync/atomic" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.uber.org/zap" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" - "go.opentelemetry.io/collector/config/configtelemetry" - "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/internal/iruntime" + "go.opentelemetry.io/collector/internal/memorylimiter" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/ptrace" @@ -29,420 +26,6 @@ import ( "go.opentelemetry.io/collector/processor/processortest" ) -func TestNew(t *testing.T) { - type args struct { - nextConsumer consumer.Traces - checkInterval time.Duration - memoryLimitMiB uint32 - memorySpikeLimitMiB uint32 - } - sink := new(consumertest.TracesSink) - tests := []struct { - name string - args args - wantErr error - }{ - { - name: "zero_checkInterval", - args: args{ - nextConsumer: sink, - }, - wantErr: errCheckIntervalOutOfRange, - }, - { - name: "zero_memAllocLimit", - args: args{ - nextConsumer: sink, - checkInterval: 100 * time.Millisecond, - }, - wantErr: errLimitOutOfRange, - }, - { - name: "memSpikeLimit_gt_memAllocLimit", - args: args{ - nextConsumer: sink, - checkInterval: 100 * time.Millisecond, - memoryLimitMiB: 1, - memorySpikeLimitMiB: 2, - }, - wantErr: errMemSpikeLimitOutOfRange, - }, - { - name: "success", - args: args{ - nextConsumer: sink, - checkInterval: 100 * time.Millisecond, - memoryLimitMiB: 1024, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cfg := createDefaultConfig().(*Config) - cfg.CheckInterval = tt.args.checkInterval - cfg.MemoryLimitMiB = tt.args.memoryLimitMiB - cfg.MemorySpikeLimitMiB = tt.args.memorySpikeLimitMiB - got, err := newMemoryLimiter(processortest.NewNopCreateSettings(), cfg) - if tt.wantErr != nil { - assert.ErrorIs(t, err, tt.wantErr) - return - } - assert.NoError(t, err) - assert.NoError(t, got.start(context.Background(), componenttest.NewNopHost())) - assert.NoError(t, got.shutdown(context.Background())) - }) - } -} - -// TestMetricsMemoryPressureResponse manipulates results from querying memory and -// check expected side effects. -func TestMetricsMemoryPressureResponse(t *testing.T) { - var currentMemAlloc uint64 - ml := &memoryLimiter{ - usageChecker: memUsageChecker{ - memAllocLimit: 1024, - }, - mustRefuse: &atomic.Bool{}, - readMemStatsFn: func(ms *runtime.MemStats) { - ms.Alloc = currentMemAlloc - }, - obsrep: newObsReport(t), - logger: zap.NewNop(), - } - mp, err := processorhelper.NewMetricsProcessor( - context.Background(), - processortest.NewNopCreateSettings(), - &Config{}, - consumertest.NewNop(), - ml.processMetrics, - processorhelper.WithCapabilities(processorCapabilities), - processorhelper.WithShutdown(ml.shutdown)) - require.NoError(t, err) - - ctx := context.Background() - md := pmetric.NewMetrics() - - // Below memAllocLimit. - currentMemAlloc = 800 - ml.checkMemLimits() - assert.NoError(t, mp.ConsumeMetrics(ctx, md)) - - // Above memAllocLimit. - currentMemAlloc = 1800 - ml.checkMemLimits() - assert.Equal(t, errDataRefused, mp.ConsumeMetrics(ctx, md)) - - // Check ballast effect - ml.ballastSize = 1000 - - // Below memAllocLimit accounting for ballast. - currentMemAlloc = 800 + ml.ballastSize - ml.checkMemLimits() - assert.NoError(t, mp.ConsumeMetrics(ctx, md)) - - // Above memAllocLimit even accountiing for ballast. - currentMemAlloc = 1800 + ml.ballastSize - ml.checkMemLimits() - assert.Equal(t, errDataRefused, mp.ConsumeMetrics(ctx, md)) - - // Restore ballast to default. - ml.ballastSize = 0 - - // Check spike limit - ml.usageChecker.memSpikeLimit = 512 - - // Below memSpikeLimit. - currentMemAlloc = 500 - ml.checkMemLimits() - assert.NoError(t, mp.ConsumeMetrics(ctx, md)) - - // Above memSpikeLimit. - currentMemAlloc = 550 - ml.checkMemLimits() - assert.Equal(t, errDataRefused, mp.ConsumeMetrics(ctx, md)) - -} - -// TestTraceMemoryPressureResponse manipulates results from querying memory and -// check expected side effects. -func TestTraceMemoryPressureResponse(t *testing.T) { - var currentMemAlloc uint64 - ml := &memoryLimiter{ - usageChecker: memUsageChecker{ - memAllocLimit: 1024, - }, - mustRefuse: &atomic.Bool{}, - readMemStatsFn: func(ms *runtime.MemStats) { - ms.Alloc = currentMemAlloc - }, - obsrep: newObsReport(t), - logger: zap.NewNop(), - } - tp, err := processorhelper.NewTracesProcessor( - context.Background(), - processortest.NewNopCreateSettings(), - &Config{}, - consumertest.NewNop(), - ml.processTraces, - processorhelper.WithCapabilities(processorCapabilities), - processorhelper.WithShutdown(ml.shutdown)) - require.NoError(t, err) - - ctx := context.Background() - td := ptrace.NewTraces() - - // Below memAllocLimit. - currentMemAlloc = 800 - ml.checkMemLimits() - assert.NoError(t, tp.ConsumeTraces(ctx, td)) - - // Above memAllocLimit. - currentMemAlloc = 1800 - ml.checkMemLimits() - assert.Equal(t, errDataRefused, tp.ConsumeTraces(ctx, td)) - - // Check ballast effect - ml.ballastSize = 1000 - - // Below memAllocLimit accounting for ballast. - currentMemAlloc = 800 + ml.ballastSize - ml.checkMemLimits() - assert.NoError(t, tp.ConsumeTraces(ctx, td)) - - // Above memAllocLimit even accountiing for ballast. - currentMemAlloc = 1800 + ml.ballastSize - ml.checkMemLimits() - assert.Equal(t, errDataRefused, tp.ConsumeTraces(ctx, td)) - - // Restore ballast to default. - ml.ballastSize = 0 - - // Check spike limit - ml.usageChecker.memSpikeLimit = 512 - - // Below memSpikeLimit. - currentMemAlloc = 500 - ml.checkMemLimits() - assert.NoError(t, tp.ConsumeTraces(ctx, td)) - - // Above memSpikeLimit. - currentMemAlloc = 550 - ml.checkMemLimits() - assert.Equal(t, errDataRefused, tp.ConsumeTraces(ctx, td)) - -} - -// TestLogMemoryPressureResponse manipulates results from querying memory and -// check expected side effects. -func TestLogMemoryPressureResponse(t *testing.T) { - var currentMemAlloc uint64 - ml := &memoryLimiter{ - usageChecker: memUsageChecker{ - memAllocLimit: 1024, - }, - mustRefuse: &atomic.Bool{}, - readMemStatsFn: func(ms *runtime.MemStats) { - ms.Alloc = currentMemAlloc - }, - obsrep: newObsReport(t), - logger: zap.NewNop(), - } - lp, err := processorhelper.NewLogsProcessor( - context.Background(), - processortest.NewNopCreateSettings(), - &Config{}, - consumertest.NewNop(), - ml.processLogs, - processorhelper.WithCapabilities(processorCapabilities), - processorhelper.WithShutdown(ml.shutdown)) - require.NoError(t, err) - - ctx := context.Background() - ld := plog.NewLogs() - - // Below memAllocLimit. - currentMemAlloc = 800 - ml.checkMemLimits() - assert.NoError(t, lp.ConsumeLogs(ctx, ld)) - - // Above memAllocLimit. - currentMemAlloc = 1800 - ml.checkMemLimits() - assert.Equal(t, errDataRefused, lp.ConsumeLogs(ctx, ld)) - - // Check ballast effect - ml.ballastSize = 1000 - - // Below memAllocLimit accounting for ballast. - currentMemAlloc = 800 + ml.ballastSize - ml.checkMemLimits() - assert.NoError(t, lp.ConsumeLogs(ctx, ld)) - - // Above memAllocLimit even accountiing for ballast. - currentMemAlloc = 1800 + ml.ballastSize - ml.checkMemLimits() - assert.Equal(t, errDataRefused, lp.ConsumeLogs(ctx, ld)) - - // Restore ballast to default. - ml.ballastSize = 0 - - // Check spike limit - ml.usageChecker.memSpikeLimit = 512 - - // Below memSpikeLimit. - currentMemAlloc = 500 - ml.checkMemLimits() - assert.NoError(t, lp.ConsumeLogs(ctx, ld)) - - // Above memSpikeLimit. - currentMemAlloc = 550 - ml.checkMemLimits() - assert.Equal(t, errDataRefused, lp.ConsumeLogs(ctx, ld)) -} - -func TestGetDecision(t *testing.T) { - t.Run("fixed_limit", func(t *testing.T) { - d, err := getMemUsageChecker(&Config{MemoryLimitMiB: 100, MemorySpikeLimitMiB: 20}, zap.NewNop()) - require.NoError(t, err) - assert.Equal(t, &memUsageChecker{ - memAllocLimit: 100 * mibBytes, - memSpikeLimit: 20 * mibBytes, - }, d) - }) - t.Run("fixed_limit_error", func(t *testing.T) { - d, err := getMemUsageChecker(&Config{MemoryLimitMiB: 20, MemorySpikeLimitMiB: 100}, zap.NewNop()) - require.Error(t, err) - assert.Nil(t, d) - }) - - t.Cleanup(func() { - getMemoryFn = iruntime.TotalMemory - }) - getMemoryFn = func() (uint64, error) { - return 100 * mibBytes, nil - } - t.Run("percentage_limit", func(t *testing.T) { - d, err := getMemUsageChecker(&Config{MemoryLimitPercentage: 50, MemorySpikePercentage: 10}, zap.NewNop()) - require.NoError(t, err) - assert.Equal(t, &memUsageChecker{ - memAllocLimit: 50 * mibBytes, - memSpikeLimit: 10 * mibBytes, - }, d) - }) - t.Run("percentage_limit_error", func(t *testing.T) { - d, err := getMemUsageChecker(&Config{MemoryLimitPercentage: 101, MemorySpikePercentage: 10}, zap.NewNop()) - require.Error(t, err) - assert.Nil(t, d) - d, err = getMemUsageChecker(&Config{MemoryLimitPercentage: 99, MemorySpikePercentage: 101}, zap.NewNop()) - require.Error(t, err) - assert.Nil(t, d) - }) -} - -func TestRefuseDecision(t *testing.T) { - decison1000Limit30Spike30, err := newPercentageMemUsageChecker(1000, 60, 30) - require.NoError(t, err) - decison1000Limit60Spike50, err := newPercentageMemUsageChecker(1000, 60, 50) - require.NoError(t, err) - decison1000Limit40Spike20, err := newPercentageMemUsageChecker(1000, 40, 20) - require.NoError(t, err) - decison1000Limit40Spike60, err := newPercentageMemUsageChecker(1000, 40, 60) - require.Error(t, err) - assert.Nil(t, decison1000Limit40Spike60) - - tests := []struct { - name string - usageChecker memUsageChecker - ms *runtime.MemStats - shouldRefuse bool - }{ - { - name: "should refuse over limit", - usageChecker: *decison1000Limit30Spike30, - ms: &runtime.MemStats{Alloc: 600}, - shouldRefuse: true, - }, - { - name: "should not refuse", - usageChecker: *decison1000Limit30Spike30, - ms: &runtime.MemStats{Alloc: 100}, - shouldRefuse: false, - }, - { - name: "should not refuse spike, fixed usageChecker", - usageChecker: memUsageChecker{ - memAllocLimit: 600, - memSpikeLimit: 500, - }, - ms: &runtime.MemStats{Alloc: 300}, - shouldRefuse: true, - }, - { - name: "should refuse, spike, percentage usageChecker", - usageChecker: *decison1000Limit60Spike50, - ms: &runtime.MemStats{Alloc: 300}, - shouldRefuse: true, - }, - { - name: "should refuse, spike, percentage usageChecker", - usageChecker: *decison1000Limit40Spike20, - ms: &runtime.MemStats{Alloc: 250}, - shouldRefuse: true, - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - shouldRefuse := test.usageChecker.aboveSoftLimit(test.ms) - assert.Equal(t, test.shouldRefuse, shouldRefuse) - }) - } -} - -func TestBallastSize(t *testing.T) { - cfg := createDefaultConfig().(*Config) - cfg.CheckInterval = 10 * time.Second - cfg.MemoryLimitMiB = 1024 - got, err := newMemoryLimiter(processortest.NewNopCreateSettings(), cfg) - require.NoError(t, err) - require.NoError(t, got.start(context.Background(), &host{ballastSize: 113})) - assert.Equal(t, uint64(113), got.ballastSize) - require.NoError(t, got.shutdown(context.Background())) -} - -type host struct { - ballastSize uint64 - component.Host -} - -func (h *host) GetExtensions() map[component.ID]component.Component { - ret := make(map[component.ID]component.Component) - ret[component.NewID("ballast")] = &ballastExtension{ballastSize: h.ballastSize} - return ret -} - -type ballastExtension struct { - ballastSize uint64 - component.StartFunc - component.ShutdownFunc -} - -func (be *ballastExtension) GetBallastSize() uint64 { - return be.ballastSize -} - -func newObsReport(t *testing.T) *processorhelper.ObsReport { - set := processorhelper.ObsReportSettings{ - ProcessorID: component.NewID(typeStr), - ProcessorCreateSettings: processortest.NewNopCreateSettings(), - } - set.ProcessorCreateSettings.MetricsLevel = configtelemetry.LevelNone - - proc, err := processorhelper.NewObsReport(set) - require.NoError(t, err) - - return proc -} - func TestNoDataLoss(t *testing.T) { // Create an exporter. exporter := internal.NewMockExporter() @@ -470,7 +53,7 @@ func TestNoDataLoss(t *testing.T) { set := processortest.NewNopCreateSettings() - limiter, err := newMemoryLimiter(set, cfg) + limiter, err := newMemoryLimiterProcessor(set, cfg) require.NoError(t, err) processor, err := processorhelper.NewLogsProcessor(context.Background(), processor.CreateSettings{}, cfg, exporter, @@ -525,3 +108,379 @@ func TestNoDataLoss(t *testing.T) { err = processor.Shutdown(context.Background()) require.NoError(t, err) } + +// TestMetricsMemoryPressureResponse manipulates results from querying memory and +// check expected side effects. +func TestMetricsMemoryPressureResponse(t *testing.T) { + md := pmetric.NewMetrics() + ctx := context.Background() + + tests := []struct { + name string + mlCfg *Config + ballastSize uint64 + memAlloc uint64 + expectError bool + }{ + { + name: "Below memAllocLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 1, + }, + ballastSize: 0, + memAlloc: 800, + expectError: false, + }, + { + name: "Above memAllocLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 1, + }, + ballastSize: 0, + memAlloc: 1800, + expectError: true, + }, + { + name: "Below memAllocLimit accounting for ballast", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 1, + }, + ballastSize: 1000, + memAlloc: 800, + expectError: false, + }, + { + name: "Above memAllocLimit even accounting for ballast", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 1, + }, + ballastSize: 1000, + memAlloc: 1800, + expectError: true, + }, + { + name: "Below memSpikeLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 10, + }, + ballastSize: 0, + memAlloc: 800, + expectError: false, + }, + { + name: "Above memSpikeLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 11, + }, + ballastSize: 0, + memAlloc: 800, + expectError: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + memorylimiter.GetMemoryFn = totalMemory + memorylimiter.ReadMemStatsFn = func(ms *runtime.MemStats) { + ms.Alloc = tt.memAlloc + tt.ballastSize + } + + ml, err := newMemoryLimiterProcessor(processortest.NewNopCreateSettings(), tt.mlCfg) + require.NoError(t, err) + mp, err := processorhelper.NewMetricsProcessor( + context.Background(), + processortest.NewNopCreateSettings(), + tt.mlCfg, + consumertest.NewNop(), + ml.processMetrics, + processorhelper.WithCapabilities(processorCapabilities), + processorhelper.WithStart(ml.start), + processorhelper.WithShutdown(ml.shutdown)) + require.NoError(t, err) + + assert.NoError(t, mp.Start(ctx, &host{ballastSize: tt.ballastSize})) + ml.memlimiter.CheckMemLimits() + err = mp.ConsumeMetrics(ctx, md) + if tt.expectError { + assert.Equal(t, memorylimiter.ErrDataRefused, err) + } else { + assert.NoError(t, err) + } + assert.NoError(t, mp.Shutdown(ctx)) + }) + } + t.Cleanup(func() { + memorylimiter.GetMemoryFn = iruntime.TotalMemory + memorylimiter.ReadMemStatsFn = runtime.ReadMemStats + }) +} + +// TestTraceMemoryPressureResponse manipulates results from querying memory and +// check expected side effects. +func TestTraceMemoryPressureResponse(t *testing.T) { + td := ptrace.NewTraces() + ctx := context.Background() + + tests := []struct { + name string + mlCfg *Config + ballastSize uint64 + memAlloc uint64 + expectError bool + }{ + { + name: "Below memAllocLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 1, + }, + ballastSize: 0, + memAlloc: 800, + expectError: false, + }, + { + name: "Above memAllocLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 1, + }, + ballastSize: 0, + memAlloc: 1800, + expectError: true, + }, + { + name: "Below memAllocLimit accounting for ballast", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 1, + }, + ballastSize: 1000, + memAlloc: 800, + expectError: false, + }, + { + name: "Above memAllocLimit even accounting for ballast", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 1, + }, + ballastSize: 1000, + memAlloc: 1800, + expectError: true, + }, + { + name: "Below memSpikeLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 10, + }, + ballastSize: 0, + memAlloc: 800, + expectError: false, + }, + { + name: "Above memSpikeLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 11, + }, + ballastSize: 0, + memAlloc: 800, + expectError: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + memorylimiter.GetMemoryFn = totalMemory + memorylimiter.ReadMemStatsFn = func(ms *runtime.MemStats) { + ms.Alloc = tt.memAlloc + tt.ballastSize + } + + ml, err := newMemoryLimiterProcessor(processortest.NewNopCreateSettings(), tt.mlCfg) + require.NoError(t, err) + tp, err := processorhelper.NewTracesProcessor( + context.Background(), + processortest.NewNopCreateSettings(), + tt.mlCfg, + consumertest.NewNop(), + ml.processTraces, + processorhelper.WithCapabilities(processorCapabilities), + processorhelper.WithStart(ml.start), + processorhelper.WithShutdown(ml.shutdown)) + require.NoError(t, err) + + assert.NoError(t, tp.Start(ctx, &host{ballastSize: tt.ballastSize})) + ml.memlimiter.CheckMemLimits() + err = tp.ConsumeTraces(ctx, td) + if tt.expectError { + assert.Equal(t, memorylimiter.ErrDataRefused, err) + } else { + assert.NoError(t, err) + } + assert.NoError(t, tp.Shutdown(ctx)) + }) + } + t.Cleanup(func() { + memorylimiter.GetMemoryFn = iruntime.TotalMemory + memorylimiter.ReadMemStatsFn = runtime.ReadMemStats + }) +} + +// TestLogMemoryPressureResponse manipulates results from querying memory and +// check expected side effects. +func TestLogMemoryPressureResponse(t *testing.T) { + ld := plog.NewLogs() + ctx := context.Background() + + tests := []struct { + name string + mlCfg *Config + ballastSize uint64 + memAlloc uint64 + expectError bool + }{ + { + name: "Below memAllocLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 1, + }, + ballastSize: 0, + memAlloc: 800, + expectError: false, + }, + { + name: "Above memAllocLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 1, + }, + ballastSize: 0, + memAlloc: 1800, + expectError: true, + }, + { + name: "Below memAllocLimit accounting for ballast", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 1, + }, + ballastSize: 1000, + memAlloc: 800, + expectError: false, + }, + { + name: "Above memAllocLimit even accounting for ballast", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 1, + }, + ballastSize: 1000, + memAlloc: 1800, + expectError: true, + }, + { + name: "Below memSpikeLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 10, + }, + ballastSize: 0, + memAlloc: 800, + expectError: false, + }, + { + name: "Above memSpikeLimit", + mlCfg: &Config{ + CheckInterval: time.Second, + MemoryLimitPercentage: 50, + MemorySpikePercentage: 11, + }, + ballastSize: 0, + memAlloc: 800, + expectError: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + memorylimiter.GetMemoryFn = totalMemory + memorylimiter.ReadMemStatsFn = func(ms *runtime.MemStats) { + ms.Alloc = tt.memAlloc + tt.ballastSize + } + + ml, err := newMemoryLimiterProcessor(processortest.NewNopCreateSettings(), tt.mlCfg) + require.NoError(t, err) + tp, err := processorhelper.NewLogsProcessor( + context.Background(), + processortest.NewNopCreateSettings(), + tt.mlCfg, + consumertest.NewNop(), + ml.processLogs, + processorhelper.WithCapabilities(processorCapabilities), + processorhelper.WithStart(ml.start), + processorhelper.WithShutdown(ml.shutdown)) + require.NoError(t, err) + + assert.NoError(t, tp.Start(ctx, &host{ballastSize: tt.ballastSize})) + ml.memlimiter.CheckMemLimits() + err = tp.ConsumeLogs(ctx, ld) + if tt.expectError { + assert.Equal(t, memorylimiter.ErrDataRefused, err) + } else { + assert.NoError(t, err) + } + assert.NoError(t, tp.Shutdown(ctx)) + }) + } + t.Cleanup(func() { + memorylimiter.GetMemoryFn = iruntime.TotalMemory + memorylimiter.ReadMemStatsFn = runtime.ReadMemStats + }) +} + +type host struct { + ballastSize uint64 + component.Host +} + +func (h *host) GetExtensions() map[component.ID]component.Component { + ret := make(map[component.ID]component.Component) + ret[component.MustNewID("ballast")] = &ballastExtension{ballastSize: h.ballastSize} + return ret +} + +type ballastExtension struct { + ballastSize uint64 + component.StartFunc + component.ShutdownFunc +} + +func (be *ballastExtension) GetBallastSize() uint64 { + return be.ballastSize +} + +func totalMemory() (uint64, error) { + return uint64(2048), nil +} diff --git a/processor/memorylimiterprocessor/metadata.yaml b/processor/memorylimiterprocessor/metadata.yaml new file mode 100644 index 00000000000..bc9e1829149 --- /dev/null +++ b/processor/memorylimiterprocessor/metadata.yaml @@ -0,0 +1,7 @@ +type: memory_limiter + +status: + class: processor + stability: + beta: [traces, metrics, logs] + distributions: [core, contrib] diff --git a/processor/memorylimiterprocessor/package_test.go b/processor/memorylimiterprocessor/package_test.go new file mode 100644 index 00000000000..77bee80493d --- /dev/null +++ b/processor/memorylimiterprocessor/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package memorylimiterprocessor + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/processor/package_test.go b/processor/package_test.go new file mode 100644 index 00000000000..b6dea1fee4c --- /dev/null +++ b/processor/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package processor + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/processor/processor.go b/processor/processor.go index 5bb3f5953cb..98feba69a57 100644 --- a/processor/processor.go +++ b/processor/processor.go @@ -5,6 +5,7 @@ package processor // import "go.opentelemetry.io/collector/processor" import ( "context" + "errors" "fmt" "go.uber.org/zap" @@ -13,6 +14,10 @@ import ( "go.opentelemetry.io/collector/consumer" ) +var ( + errNilNextConsumer = errors.New("nil next Consumer") +) + // Traces is a processor that can consume traces. type Traces interface { component.Component @@ -229,6 +234,9 @@ func NewBuilder(cfgs map[component.ID]component.Config, factories map[component. // CreateTraces creates a Traces processor based on the settings and config. func (b *Builder) CreateTraces(ctx context.Context, set CreateSettings, next consumer.Traces) (Traces, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("processor %q is not configured", set.ID) @@ -245,6 +253,9 @@ func (b *Builder) CreateTraces(ctx context.Context, set CreateSettings, next con // CreateMetrics creates a Metrics processor based on the settings and config. func (b *Builder) CreateMetrics(ctx context.Context, set CreateSettings, next consumer.Metrics) (Metrics, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("processor %q is not configured", set.ID) @@ -261,6 +272,9 @@ func (b *Builder) CreateMetrics(ctx context.Context, set CreateSettings, next co // CreateLogs creates a Logs processor based on the settings and config. func (b *Builder) CreateLogs(ctx context.Context, set CreateSettings, next consumer.Logs) (Logs, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("processor %q is not configured", set.ID) diff --git a/processor/processor_test.go b/processor/processor_test.go index 11d70512186..83207ba6955 100644 --- a/processor/processor_test.go +++ b/processor/processor_test.go @@ -17,43 +17,43 @@ import ( ) func TestNewFactory(t *testing.T) { - const typeStr = "test" + var testType = component.MustNewType("test") defaultCfg := struct{}{} factory := NewFactory( - typeStr, + testType, func() component.Config { return &defaultCfg }) - assert.EqualValues(t, typeStr, factory.Type()) + assert.EqualValues(t, testType, factory.Type()) assert.EqualValues(t, &defaultCfg, factory.CreateDefaultConfig()) - _, err := factory.CreateTracesProcessor(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err := factory.CreateTracesProcessor(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.Error(t, err) - _, err = factory.CreateMetricsProcessor(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err = factory.CreateMetricsProcessor(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.Error(t, err) - _, err = factory.CreateLogsProcessor(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err = factory.CreateLogsProcessor(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.Error(t, err) } func TestNewFactoryWithOptions(t *testing.T) { - const typeStr = "test" + var testType = component.MustNewType("test") defaultCfg := struct{}{} factory := NewFactory( - typeStr, + testType, func() component.Config { return &defaultCfg }, WithTraces(createTraces, component.StabilityLevelAlpha), WithMetrics(createMetrics, component.StabilityLevelBeta), WithLogs(createLogs, component.StabilityLevelUnmaintained)) - assert.EqualValues(t, typeStr, factory.Type()) + assert.EqualValues(t, testType, factory.Type()) assert.EqualValues(t, &defaultCfg, factory.CreateDefaultConfig()) assert.Equal(t, component.StabilityLevelAlpha, factory.TracesProcessorStability()) - _, err := factory.CreateTracesProcessor(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err := factory.CreateTracesProcessor(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelBeta, factory.MetricsProcessorStability()) - _, err = factory.CreateMetricsProcessor(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err = factory.CreateMetricsProcessor(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) assert.Equal(t, component.StabilityLevelUnmaintained, factory.LogsProcessorStability()) - _, err = factory.CreateLogsProcessor(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err = factory.CreateLogsProcessor(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.NoError(t, err) } @@ -64,8 +64,8 @@ func TestMakeFactoryMap(t *testing.T) { out map[component.Type]Factory } - p1 := NewFactory("p1", nil) - p2 := NewFactory("p2", nil) + p1 := NewFactory(component.MustNewType("p1"), nil) + p2 := NewFactory(component.MustNewType("p2"), nil) testCases := []testCase{ { name: "different names", @@ -77,7 +77,7 @@ func TestMakeFactoryMap(t *testing.T) { }, { name: "same name", - in: []Factory{p1, p2, NewFactory("p1", nil)}, + in: []Factory{p1, p2, NewFactory(component.MustNewType("p1"), nil)}, }, } @@ -98,9 +98,9 @@ func TestMakeFactoryMap(t *testing.T) { func TestBuilder(t *testing.T) { defaultCfg := struct{}{} factories, err := MakeFactoryMap([]Factory{ - NewFactory("err", nil), + NewFactory(component.MustNewType("err"), nil), NewFactory( - "all", + component.MustNewType("all"), func() component.Config { return &defaultCfg }, WithTraces(createTraces, component.StabilityLevelDevelopment), WithMetrics(createMetrics, component.StabilityLevelAlpha), @@ -110,27 +110,50 @@ func TestBuilder(t *testing.T) { require.NoError(t, err) testCases := []struct { - name string - id component.ID - err string + name string + id component.ID + err string + nextTraces consumer.Traces + nextLogs consumer.Logs + nextMetrics consumer.Metrics }{ { - name: "unknown", - id: component.NewID("unknown"), - err: "processor factory not available for: \"unknown\"", + name: "unknown", + id: component.MustNewID("unknown"), + err: "processor factory not available for: \"unknown\"", + nextTraces: consumertest.NewNop(), + nextLogs: consumertest.NewNop(), + nextMetrics: consumertest.NewNop(), + }, + { + name: "err", + id: component.MustNewID("err"), + err: "telemetry type is not supported", + nextTraces: consumertest.NewNop(), + nextLogs: consumertest.NewNop(), + nextMetrics: consumertest.NewNop(), }, { - name: "err", - id: component.NewID("err"), - err: "telemetry type is not supported", + name: "all", + id: component.MustNewID("all"), + nextTraces: consumertest.NewNop(), + nextLogs: consumertest.NewNop(), + nextMetrics: consumertest.NewNop(), }, { - name: "all", - id: component.NewID("all"), + name: "all/named", + id: component.MustNewIDWithName("all", "named"), + nextTraces: consumertest.NewNop(), + nextLogs: consumertest.NewNop(), + nextMetrics: consumertest.NewNop(), }, { - name: "all/named", - id: component.NewIDWithName("all", "named"), + name: "no next consumer", + id: component.MustNewID("unknown"), + err: "nil next Consumer", + nextTraces: nil, + nextLogs: nil, + nextMetrics: nil, }, } @@ -139,7 +162,7 @@ func TestBuilder(t *testing.T) { cfgs := map[component.ID]component.Config{tt.id: defaultCfg} b := NewBuilder(cfgs, factories) - te, err := b.CreateTraces(context.Background(), createSettings(tt.id), nil) + te, err := b.CreateTraces(context.Background(), createSettings(tt.id), tt.nextTraces) if tt.err != "" { assert.EqualError(t, err, tt.err) assert.Nil(t, te) @@ -148,7 +171,7 @@ func TestBuilder(t *testing.T) { assert.Equal(t, nopInstance, te) } - me, err := b.CreateMetrics(context.Background(), createSettings(tt.id), nil) + me, err := b.CreateMetrics(context.Background(), createSettings(tt.id), tt.nextMetrics) if tt.err != "" { assert.EqualError(t, err, tt.err) assert.Nil(t, me) @@ -157,7 +180,7 @@ func TestBuilder(t *testing.T) { assert.Equal(t, nopInstance, me) } - le, err := b.CreateLogs(context.Background(), createSettings(tt.id), nil) + le, err := b.CreateLogs(context.Background(), createSettings(tt.id), tt.nextLogs) if tt.err != "" { assert.EqualError(t, err, tt.err) assert.Nil(t, le) @@ -173,7 +196,7 @@ func TestBuilderMissingConfig(t *testing.T) { defaultCfg := struct{}{} factories, err := MakeFactoryMap([]Factory{ NewFactory( - "all", + component.MustNewType("all"), func() component.Config { return &defaultCfg }, WithTraces(createTraces, component.StabilityLevelDevelopment), WithMetrics(createMetrics, component.StabilityLevelAlpha), @@ -184,30 +207,30 @@ func TestBuilderMissingConfig(t *testing.T) { require.NoError(t, err) bErr := NewBuilder(map[component.ID]component.Config{}, factories) - missingID := component.NewIDWithName("all", "missing") + missingID := component.MustNewIDWithName("all", "missing") - te, err := bErr.CreateTraces(context.Background(), createSettings(missingID), nil) + te, err := bErr.CreateTraces(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "processor \"all/missing\" is not configured") assert.Nil(t, te) - me, err := bErr.CreateMetrics(context.Background(), createSettings(missingID), nil) + me, err := bErr.CreateMetrics(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "processor \"all/missing\" is not configured") assert.Nil(t, me) - le, err := bErr.CreateLogs(context.Background(), createSettings(missingID), nil) + le, err := bErr.CreateLogs(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "processor \"all/missing\" is not configured") assert.Nil(t, le) } func TestBuilderFactory(t *testing.T) { - factories, err := MakeFactoryMap([]Factory{NewFactory("foo", nil)}...) + factories, err := MakeFactoryMap([]Factory{NewFactory(component.MustNewType("foo"), nil)}...) require.NoError(t, err) - cfgs := map[component.ID]component.Config{component.NewID("foo"): struct{}{}} + cfgs := map[component.ID]component.Config{component.MustNewID("foo"): struct{}{}} b := NewBuilder(cfgs, factories) - assert.NotNil(t, b.Factory(component.NewID("foo").Type())) - assert.Nil(t, b.Factory(component.NewID("bar").Type())) + assert.NotNil(t, b.Factory(component.MustNewID("foo").Type())) + assert.Nil(t, b.Factory(component.MustNewID("bar").Type())) } var nopInstance = &nopProcessor{ diff --git a/processor/processorhelper/logs.go b/processor/processorhelper/logs.go index b392702584a..ade2f45a385 100644 --- a/processor/processorhelper/logs.go +++ b/processor/processorhelper/logs.go @@ -39,10 +39,6 @@ func NewLogsProcessor( return nil, errors.New("nil logsFunc") } - if nextConsumer == nil { - return nil, component.ErrNilNextConsumer - } - eventOptions := spanAttributes(set.ID) bs := fromOptions(options) logsConsumer, err := consumer.NewLogs(func(ctx context.Context, ld plog.Logs) error { diff --git a/processor/processorhelper/logs_test.go b/processor/processorhelper/logs_test.go index 383459dc689..0fe43773309 100644 --- a/processor/processorhelper/logs_test.go +++ b/processor/processorhelper/logs_test.go @@ -47,9 +47,6 @@ func TestNewLogsProcessor_WithOptions(t *testing.T) { func TestNewLogsProcessor_NilRequiredFields(t *testing.T) { _, err := NewLogsProcessor(context.Background(), processortest.NewNopCreateSettings(), &testLogsCfg, consumertest.NewNop(), nil) assert.Error(t, err) - - _, err = NewLogsProcessor(context.Background(), processortest.NewNopCreateSettings(), &testLogsCfg, nil, newTestLProcessor(nil)) - assert.Equal(t, component.ErrNilNextConsumer, err) } func TestNewLogsProcessor_ProcessLogError(t *testing.T) { diff --git a/processor/processorhelper/metrics.go b/processor/processorhelper/metrics.go index 08168c460d5..ac3802722d0 100644 --- a/processor/processorhelper/metrics.go +++ b/processor/processorhelper/metrics.go @@ -39,10 +39,6 @@ func NewMetricsProcessor( return nil, errors.New("nil metricsFunc") } - if nextConsumer == nil { - return nil, component.ErrNilNextConsumer - } - eventOptions := spanAttributes(set.ID) bs := fromOptions(options) metricsConsumer, err := consumer.NewMetrics(func(ctx context.Context, md pmetric.Metrics) error { diff --git a/processor/processorhelper/metrics_test.go b/processor/processorhelper/metrics_test.go index 19bd1b159a0..b965c4d45c3 100644 --- a/processor/processorhelper/metrics_test.go +++ b/processor/processorhelper/metrics_test.go @@ -47,9 +47,6 @@ func TestNewMetricsProcessor_WithOptions(t *testing.T) { func TestNewMetricsProcessor_NilRequiredFields(t *testing.T) { _, err := NewMetricsProcessor(context.Background(), processortest.NewNopCreateSettings(), &testMetricsCfg, consumertest.NewNop(), nil) assert.Error(t, err) - - _, err = NewMetricsProcessor(context.Background(), processortest.NewNopCreateSettings(), &testMetricsCfg, nil, newTestMProcessor(nil)) - assert.Equal(t, component.ErrNilNextConsumer, err) } func TestNewMetricsProcessor_ProcessMetricsError(t *testing.T) { diff --git a/processor/processorhelper/obsreport.go b/processor/processorhelper/obsreport.go index 66b53eb0f9f..9d1188f1408 100644 --- a/processor/processorhelper/obsreport.go +++ b/processor/processorhelper/obsreport.go @@ -5,20 +5,15 @@ package processorhelper // import "go.opentelemetry.io/collector/processor/proce import ( "context" - "errors" "strings" - "go.opencensus.io/stats" - "go.opencensus.io/tag" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" - sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.uber.org/multierr" "go.uber.org/zap" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configtelemetry" - "go.opentelemetry.io/collector/internal/obsreportconfig" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" "go.opentelemetry.io/collector/processor" ) @@ -43,13 +38,11 @@ func BuildCustomMetricName(configType, metric string) string { // ObsReport is a helper to add observability to a processor. type ObsReport struct { - level configtelemetry.Level - mutators []tag.Mutator + level configtelemetry.Level logger *zap.Logger - useOtelForMetrics bool - otelAttrs []attribute.KeyValue + otelAttrs []attribute.KeyValue acceptedSpansCounter metric.Int64Counter refusedSpansCounter metric.Int64Counter @@ -70,25 +63,19 @@ type ObsReportSettings struct { // NewObsReport creates a new Processor. func NewObsReport(cfg ObsReportSettings) (*ObsReport, error) { - return newObsReport(cfg, obsreportconfig.UseOtelForInternalMetricsfeatureGate.IsEnabled()) + return newObsReport(cfg) } -func newObsReport(cfg ObsReportSettings, useOtel bool) (*ObsReport, error) { +func newObsReport(cfg ObsReportSettings) (*ObsReport, error) { report := &ObsReport{ - level: cfg.ProcessorCreateSettings.MetricsLevel, - mutators: []tag.Mutator{tag.Upsert(obsmetrics.TagKeyProcessor, cfg.ProcessorID.String(), tag.WithTTL(tag.TTLNoPropagation))}, - logger: cfg.ProcessorCreateSettings.Logger, - useOtelForMetrics: useOtel, + level: cfg.ProcessorCreateSettings.MetricsLevel, + logger: cfg.ProcessorCreateSettings.Logger, otelAttrs: []attribute.KeyValue{ attribute.String(obsmetrics.ProcessorKey, cfg.ProcessorID.String()), }, } - // ignore instrument name error as per workaround in https://github.com/open-telemetry/opentelemetry-collector/issues/8346 - // if err := proc.createOtelMetrics(cfg); err != nil { - // return nil, err - // } - if err := report.createOtelMetrics(cfg); err != nil && !errors.Is(err, sdkmetric.ErrInstrumentName) { + if err := report.createOtelMetrics(cfg); err != nil { return nil, err } @@ -96,9 +83,6 @@ func newObsReport(cfg ObsReportSettings, useOtel bool) (*ObsReport, error) { } func (or *ObsReport) createOtelMetrics(cfg ObsReportSettings) error { - if !or.useOtelForMetrics { - return nil - } meter := cfg.ProcessorCreateSettings.MeterProvider.Meter(processorScope) var errors, err error @@ -168,7 +152,7 @@ func (or *ObsReport) createOtelMetrics(cfg ObsReportSettings) error { return errors } -func (or *ObsReport) recordWithOtel(ctx context.Context, dataType component.DataType, accepted, refused, dropped int64) { +func (or *ObsReport) recordData(ctx context.Context, dataType component.DataType, accepted, refused, dropped int64) { var acceptedCount, refusedCount, droppedCount metric.Int64Counter switch dataType { case component.DataTypeTraces: @@ -190,42 +174,6 @@ func (or *ObsReport) recordWithOtel(ctx context.Context, dataType component.Data droppedCount.Add(ctx, dropped, metric.WithAttributes(or.otelAttrs...)) } -func (or *ObsReport) recordWithOC(ctx context.Context, dataType component.DataType, accepted, refused, dropped int64) { - var acceptedMeasure, refusedMeasure, droppedMeasure *stats.Int64Measure - - switch dataType { - case component.DataTypeTraces: - acceptedMeasure = obsmetrics.ProcessorAcceptedSpans - refusedMeasure = obsmetrics.ProcessorRefusedSpans - droppedMeasure = obsmetrics.ProcessorDroppedSpans - case component.DataTypeMetrics: - acceptedMeasure = obsmetrics.ProcessorAcceptedMetricPoints - refusedMeasure = obsmetrics.ProcessorRefusedMetricPoints - droppedMeasure = obsmetrics.ProcessorDroppedMetricPoints - case component.DataTypeLogs: - acceptedMeasure = obsmetrics.ProcessorAcceptedLogRecords - refusedMeasure = obsmetrics.ProcessorRefusedLogRecords - droppedMeasure = obsmetrics.ProcessorDroppedLogRecords - } - - // ignore the error for now; should not happen - _ = stats.RecordWithTags( - ctx, - or.mutators, - acceptedMeasure.M(accepted), - refusedMeasure.M(refused), - droppedMeasure.M(dropped), - ) -} - -func (or *ObsReport) recordData(ctx context.Context, dataType component.DataType, accepted, refused, dropped int64) { - if or.useOtelForMetrics { - or.recordWithOtel(ctx, dataType, accepted, refused, dropped) - } else { - or.recordWithOC(ctx, dataType, accepted, refused, dropped) - } -} - // TracesAccepted reports that the trace data was accepted. func (or *ObsReport) TracesAccepted(ctx context.Context, numSpans int) { if or.level != configtelemetry.LevelNone { diff --git a/processor/processorhelper/obsreport_test.go b/processor/processorhelper/obsreport_test.go index cd0ea4a8f26..2cd4500e299 100644 --- a/processor/processorhelper/obsreport_test.go +++ b/processor/processorhelper/obsreport_test.go @@ -11,23 +11,23 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/obsreport/obsreporttest" - "go.opentelemetry.io/collector/processor/processortest" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/processor" ) var ( - processorID = component.NewID("fakeProcessor") + processorID = component.MustNewID("fakeProcessor") ) func TestProcessorTraceData(t *testing.T) { - testTelemetry(t, processorID, func(t *testing.T, tt obsreporttest.TestTelemetry, useOtel bool) { + testTelemetry(t, processorID, func(t *testing.T, tt componenttest.TestTelemetry) { const acceptedSpans = 27 const refusedSpans = 19 const droppedSpans = 13 obsrep, err := newObsReport(ObsReportSettings{ ProcessorID: processorID, - ProcessorCreateSettings: processortest.NewCreateSettings(processorID, tt.TelemetrySettings), - }, useOtel) + ProcessorCreateSettings: processor.CreateSettings{ID: processorID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) require.NoError(t, err) obsrep.TracesAccepted(context.Background(), acceptedSpans) obsrep.TracesRefused(context.Background(), refusedSpans) @@ -38,15 +38,15 @@ func TestProcessorTraceData(t *testing.T) { } func TestProcessorMetricsData(t *testing.T) { - testTelemetry(t, processorID, func(t *testing.T, tt obsreporttest.TestTelemetry, useOtel bool) { + testTelemetry(t, processorID, func(t *testing.T, tt componenttest.TestTelemetry) { const acceptedPoints = 29 const refusedPoints = 11 const droppedPoints = 17 obsrep, err := newObsReport(ObsReportSettings{ ProcessorID: processorID, - ProcessorCreateSettings: processortest.NewCreateSettings(processorID, tt.TelemetrySettings), - }, useOtel) + ProcessorCreateSettings: processor.CreateSettings{ID: processorID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) require.NoError(t, err) obsrep.MetricsAccepted(context.Background(), acceptedPoints) obsrep.MetricsRefused(context.Background(), refusedPoints) @@ -79,15 +79,15 @@ func TestBuildProcessorCustomMetricName(t *testing.T) { } func TestProcessorLogRecords(t *testing.T) { - testTelemetry(t, processorID, func(t *testing.T, tt obsreporttest.TestTelemetry, useOtel bool) { + testTelemetry(t, processorID, func(t *testing.T, tt componenttest.TestTelemetry) { const acceptedRecords = 29 const refusedRecords = 11 const droppedRecords = 17 obsrep, err := newObsReport(ObsReportSettings{ ProcessorID: processorID, - ProcessorCreateSettings: processortest.NewCreateSettings(processorID, tt.TelemetrySettings), - }, useOtel) + ProcessorCreateSettings: processor.CreateSettings{ID: processorID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) require.NoError(t, err) obsrep.LogsAccepted(context.Background(), acceptedRecords) obsrep.LogsRefused(context.Background(), refusedRecords) @@ -97,20 +97,87 @@ func TestProcessorLogRecords(t *testing.T) { }) } -func testTelemetry(t *testing.T, id component.ID, testFunc func(t *testing.T, tt obsreporttest.TestTelemetry, useOtel bool)) { - t.Run("WithOC", func(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(id) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) +func TestCheckProcessorTracesViews(t *testing.T) { + tt, err := componenttest.SetupTelemetry(processorID) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + por, err := NewObsReport(ObsReportSettings{ + ProcessorID: processorID, + ProcessorCreateSettings: processor.CreateSettings{ID: processorID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) + assert.NoError(t, err) + + por.TracesAccepted(context.Background(), 7) + por.TracesRefused(context.Background(), 8) + por.TracesDropped(context.Background(), 9) + + assert.NoError(t, tt.CheckProcessorTraces(7, 8, 9)) + assert.Error(t, tt.CheckProcessorTraces(0, 0, 0)) + assert.Error(t, tt.CheckProcessorTraces(7, 0, 0)) + assert.Error(t, tt.CheckProcessorTraces(7, 8, 0)) + assert.Error(t, tt.CheckProcessorTraces(7, 0, 9)) + assert.Error(t, tt.CheckProcessorTraces(0, 8, 0)) + assert.Error(t, tt.CheckProcessorTraces(0, 8, 9)) + assert.Error(t, tt.CheckProcessorTraces(0, 0, 9)) +} + +func TestCheckProcessorMetricsViews(t *testing.T) { + tt, err := componenttest.SetupTelemetry(processorID) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - testFunc(t, tt, false) + por, err := NewObsReport(ObsReportSettings{ + ProcessorID: processorID, + ProcessorCreateSettings: processor.CreateSettings{ID: processorID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, }) + assert.NoError(t, err) + + por.MetricsAccepted(context.Background(), 7) + por.MetricsRefused(context.Background(), 8) + por.MetricsDropped(context.Background(), 9) + + assert.NoError(t, tt.CheckProcessorMetrics(7, 8, 9)) + assert.Error(t, tt.CheckProcessorMetrics(0, 0, 0)) + assert.Error(t, tt.CheckProcessorMetrics(7, 0, 0)) + assert.Error(t, tt.CheckProcessorMetrics(7, 8, 0)) + assert.Error(t, tt.CheckProcessorMetrics(7, 0, 9)) + assert.Error(t, tt.CheckProcessorMetrics(0, 8, 0)) + assert.Error(t, tt.CheckProcessorMetrics(0, 8, 9)) + assert.Error(t, tt.CheckProcessorMetrics(0, 0, 9)) +} + +func TestCheckProcessorLogViews(t *testing.T) { + tt, err := componenttest.SetupTelemetry(processorID) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + por, err := NewObsReport(ObsReportSettings{ + ProcessorID: processorID, + ProcessorCreateSettings: processor.CreateSettings{ID: processorID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) + assert.NoError(t, err) + + por.LogsAccepted(context.Background(), 7) + por.LogsRefused(context.Background(), 8) + por.LogsDropped(context.Background(), 9) + + assert.NoError(t, tt.CheckProcessorLogs(7, 8, 9)) + assert.Error(t, tt.CheckProcessorLogs(0, 0, 0)) + assert.Error(t, tt.CheckProcessorLogs(7, 0, 0)) + assert.Error(t, tt.CheckProcessorLogs(7, 8, 0)) + assert.Error(t, tt.CheckProcessorLogs(7, 0, 9)) + assert.Error(t, tt.CheckProcessorLogs(0, 8, 0)) + assert.Error(t, tt.CheckProcessorLogs(0, 8, 9)) + assert.Error(t, tt.CheckProcessorLogs(0, 0, 9)) +} +func testTelemetry(t *testing.T, id component.ID, testFunc func(t *testing.T, tt componenttest.TestTelemetry)) { t.Run("WithOTel", func(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(id) + tt, err := componenttest.SetupTelemetry(id) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - testFunc(t, tt, true) + testFunc(t, tt) }) } diff --git a/processor/processorhelper/package_test.go b/processor/processorhelper/package_test.go new file mode 100644 index 00000000000..e9823cee56e --- /dev/null +++ b/processor/processorhelper/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package processorhelper + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/processor/processorhelper/traces.go b/processor/processorhelper/traces.go index 703fa98e076..578f65c7efa 100644 --- a/processor/processorhelper/traces.go +++ b/processor/processorhelper/traces.go @@ -39,10 +39,6 @@ func NewTracesProcessor( return nil, errors.New("nil tracesFunc") } - if nextConsumer == nil { - return nil, component.ErrNilNextConsumer - } - eventOptions := spanAttributes(set.ID) bs := fromOptions(options) traceConsumer, err := consumer.NewTraces(func(ctx context.Context, td ptrace.Traces) error { diff --git a/processor/processorhelper/traces_test.go b/processor/processorhelper/traces_test.go index 1ba4f6d1951..f2a59473a44 100644 --- a/processor/processorhelper/traces_test.go +++ b/processor/processorhelper/traces_test.go @@ -47,9 +47,6 @@ func TestNewTracesProcessor_WithOptions(t *testing.T) { func TestNewTracesProcessor_NilRequiredFields(t *testing.T) { _, err := NewTracesProcessor(context.Background(), processortest.NewNopCreateSettings(), &testTracesCfg, consumertest.NewNop(), nil) assert.Error(t, err) - - _, err = NewTracesProcessor(context.Background(), processortest.NewNopCreateSettings(), &testTracesCfg, nil, newTestTProcessor(nil)) - assert.Equal(t, component.ErrNilNextConsumer, err) } func TestNewTracesProcessor_ProcessTraceError(t *testing.T) { diff --git a/processor/processortest/nop_processor.go b/processor/processortest/nop_processor.go index 3ff229f182f..0651bc5b6ba 100644 --- a/processor/processortest/nop_processor.go +++ b/processor/processortest/nop_processor.go @@ -13,11 +13,12 @@ import ( "go.opentelemetry.io/collector/processor" ) -const typeStr = "nop" +var nopType = component.MustNewType("nop") -// NewNopCreateSettings returns a new nop settings for Create* functions. +// NewNopCreateSettings returns a new nop settings for Create*Processor functions. func NewNopCreateSettings() processor.CreateSettings { return processor.CreateSettings{ + ID: component.NewID(nopType), TelemetrySettings: componenttest.NewNopTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo(), } @@ -26,7 +27,7 @@ func NewNopCreateSettings() processor.CreateSettings { // NewNopFactory returns a component.ProcessorFactory that constructs nop processors. func NewNopFactory() processor.Factory { return processor.NewFactory( - "nop", + nopType, func() component.Config { return &nopConfig{} }, processor.WithTraces(createTracesProcessor, component.StabilityLevelStable), processor.WithMetrics(createMetricsProcessor, component.StabilityLevelStable), @@ -52,25 +53,17 @@ var nopInstance = &nopProcessor{ Consumer: consumertest.NewNop(), } -// nopProcessor stores consumed traces and metrics for testing purposes. +// nopProcessor acts as a processor for testing purposes. type nopProcessor struct { component.StartFunc component.ShutdownFunc consumertest.Consumer } -// NewNopBuilder returns a processor.Builder that constructs nop receivers. +// NewNopBuilder returns a processor.Builder that constructs nop processors. func NewNopBuilder() *processor.Builder { nopFactory := NewNopFactory() return processor.NewBuilder( - map[component.ID]component.Config{component.NewID(typeStr): nopFactory.CreateDefaultConfig()}, - map[component.Type]processor.Factory{typeStr: nopFactory}) -} - -func NewCreateSettings(id component.ID, set component.TelemetrySettings) processor.CreateSettings { - return processor.CreateSettings{ - ID: id, - TelemetrySettings: set, - BuildInfo: component.NewDefaultBuildInfo(), - } + map[component.ID]component.Config{component.NewID(nopType): nopFactory.CreateDefaultConfig()}, + map[component.Type]processor.Factory{nopType: nopFactory}) } diff --git a/processor/processortest/nop_processor_test.go b/processor/processortest/nop_processor_test.go index 44f581bd2eb..77e9131ed62 100644 --- a/processor/processortest/nop_processor_test.go +++ b/processor/processortest/nop_processor_test.go @@ -22,7 +22,7 @@ import ( func TestNewNopFactory(t *testing.T) { factory := NewNopFactory() require.NotNil(t, factory) - assert.Equal(t, component.Type("nop"), factory.Type()) + assert.Equal(t, component.MustNewType("nop"), factory.Type()) cfg := factory.CreateDefaultConfig() assert.Equal(t, &nopConfig{}, cfg) @@ -55,7 +55,7 @@ func TestNewNopBuilder(t *testing.T) { factory := NewNopFactory() cfg := factory.CreateDefaultConfig() set := NewNopCreateSettings() - set.ID = component.NewID(typeStr) + set.ID = component.NewID(nopType) traces, err := factory.CreateTracesProcessor(context.Background(), set, cfg, consumertest.NewNop()) require.NoError(t, err) diff --git a/processor/processortest/package_test.go b/processor/processortest/package_test.go new file mode 100644 index 00000000000..892271a45a5 --- /dev/null +++ b/processor/processortest/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package processortest + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/processor/processortest/shutdown_verifier.go b/processor/processortest/shutdown_verifier.go index d37b3515f84..e0c3becac24 100644 --- a/processor/processortest/shutdown_verifier.go +++ b/processor/processortest/shutdown_verifier.go @@ -22,12 +22,10 @@ func verifyTracesDoesNotProduceAfterShutdown(t *testing.T, factory processor.Fac // Create a proc and output its produce to a sink. nextSink := new(consumertest.TracesSink) proc, err := factory.CreateTracesProcessor(context.Background(), NewNopCreateSettings(), cfg, nextSink) - if err != nil { - if errors.Is(err, component.ErrDataTypeIsNotSupported) { - return - } - require.NoError(t, err) + if errors.Is(err, component.ErrDataTypeIsNotSupported) { + return } + require.NoError(t, err) assert.NoError(t, proc.Start(context.Background(), componenttest.NewNopHost())) // Send some traces to the proc. @@ -44,9 +42,57 @@ func verifyTracesDoesNotProduceAfterShutdown(t *testing.T, factory processor.Fac assert.EqualValues(t, generatedCount, nextSink.SpanCount()) } +func verifyLogsDoesNotProduceAfterShutdown(t *testing.T, factory processor.Factory, cfg component.Config) { + // Create a proc and output its produce to a sink. + nextSink := new(consumertest.LogsSink) + proc, err := factory.CreateLogsProcessor(context.Background(), NewNopCreateSettings(), cfg, nextSink) + if errors.Is(err, component.ErrDataTypeIsNotSupported) { + return + } + require.NoError(t, err) + assert.NoError(t, proc.Start(context.Background(), componenttest.NewNopHost())) + + // Send some logs to the proc. + const generatedCount = 10 + for i := 0; i < generatedCount; i++ { + require.NoError(t, proc.ConsumeLogs(context.Background(), testdata.GenerateLogs(1))) + } + + // Now shutdown the proc. + assert.NoError(t, proc.Shutdown(context.Background())) + + // The Shutdown() is done. It means the proc must have sent everything we + // gave it to the next sink. + assert.EqualValues(t, generatedCount, nextSink.LogRecordCount()) +} + +func verifyMetricsDoesNotProduceAfterShutdown(t *testing.T, factory processor.Factory, cfg component.Config) { + // Create a proc and output its produce to a sink. + nextSink := new(consumertest.MetricsSink) + proc, err := factory.CreateMetricsProcessor(context.Background(), NewNopCreateSettings(), cfg, nextSink) + if errors.Is(err, component.ErrDataTypeIsNotSupported) { + return + } + require.NoError(t, err) + assert.NoError(t, proc.Start(context.Background(), componenttest.NewNopHost())) + + // Send some metrics to the proc. testdata.GenerateMetrics creates metrics with 2 data points each. + const generatedCount = 10 + for i := 0; i < generatedCount; i++ { + require.NoError(t, proc.ConsumeMetrics(context.Background(), testdata.GenerateMetrics(1))) + } + + // Now shutdown the proc. + assert.NoError(t, proc.Shutdown(context.Background())) + + // The Shutdown() is done. It means the proc must have sent everything we + // gave it to the next sink. + assert.EqualValues(t, generatedCount*2, nextSink.DataPointCount()) +} + // VerifyShutdown verifies the processor doesn't produce telemetry data after shutdown. func VerifyShutdown(t *testing.T, factory processor.Factory, cfg component.Config) { verifyTracesDoesNotProduceAfterShutdown(t, factory, cfg) - // TODO: add metrics and logs verification. - // TODO: add other shutdown verifications. + verifyLogsDoesNotProduceAfterShutdown(t, factory, cfg) + verifyMetricsDoesNotProduceAfterShutdown(t, factory, cfg) } diff --git a/processor/processortest/shutdown_verifier_test.go b/processor/processortest/shutdown_verifier_test.go new file mode 100644 index 00000000000..70ae639068f --- /dev/null +++ b/processor/processortest/shutdown_verifier_test.go @@ -0,0 +1,103 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package processortest + +import ( + "context" + "testing" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/collector/processor" +) + +func TestShutdownVerifier(t *testing.T) { + f := processor.NewFactory( + component.MustNewType("passthrough"), + func() component.Config { return struct{}{} }, + processor.WithTraces(createPassthroughTracesProcessor, component.StabilityLevelStable), + processor.WithMetrics(createPassthroughMetricsProcessor, component.StabilityLevelStable), + processor.WithLogs(createPassthroughLogsProcessor, component.StabilityLevelStable), + ) + VerifyShutdown(t, f, &struct{}{}) +} + +func TestShutdownVerifierLogsOnly(t *testing.T) { + f := processor.NewFactory( + component.MustNewType("passthrough"), + func() component.Config { return struct{}{} }, + processor.WithLogs(createPassthroughLogsProcessor, component.StabilityLevelStable), + ) + VerifyShutdown(t, f, &struct{}{}) +} + +func TestShutdownVerifierMetricsOnly(t *testing.T) { + f := processor.NewFactory( + component.MustNewType("passthrough"), + func() component.Config { return struct{}{} }, + processor.WithMetrics(createPassthroughMetricsProcessor, component.StabilityLevelStable), + ) + VerifyShutdown(t, f, &struct{}{}) +} + +func TestShutdownVerifierTracesOnly(t *testing.T) { + f := processor.NewFactory( + component.MustNewType("passthrough"), + func() component.Config { return struct{}{} }, + processor.WithTraces(createPassthroughTracesProcessor, component.StabilityLevelStable), + ) + VerifyShutdown(t, f, &struct{}{}) +} + +type passthroughProcessor struct { + processor.Traces + nextLogs consumer.Logs + nextMetrics consumer.Metrics + nextTraces consumer.Traces +} + +func (passthroughProcessor) Start(context.Context, component.Host) error { + return nil +} + +func (passthroughProcessor) Shutdown(context.Context) error { + return nil +} + +func (passthroughProcessor) Capabilities() consumer.Capabilities { + return consumer.Capabilities{} +} + +func createPassthroughLogsProcessor(_ context.Context, _ processor.CreateSettings, _ component.Config, logs consumer.Logs) (processor.Logs, error) { + return passthroughProcessor{ + nextLogs: logs, + }, nil +} + +func createPassthroughMetricsProcessor(_ context.Context, _ processor.CreateSettings, _ component.Config, metrics consumer.Metrics) (processor.Metrics, error) { + return passthroughProcessor{ + nextMetrics: metrics, + }, nil +} + +func createPassthroughTracesProcessor(_ context.Context, _ processor.CreateSettings, _ component.Config, traces consumer.Traces) (processor.Traces, error) { + return passthroughProcessor{ + nextTraces: traces, + }, nil +} + +func (p passthroughProcessor) ConsumeTraces(ctx context.Context, td ptrace.Traces) error { + return p.nextTraces.ConsumeTraces(ctx, td) +} + +func (p passthroughProcessor) ConsumeMetrics(ctx context.Context, md pmetric.Metrics) error { + return p.nextMetrics.ConsumeMetrics(ctx, md) +} + +func (p passthroughProcessor) ConsumeLogs(ctx context.Context, ld plog.Logs) error { + return p.nextLogs.ConsumeLogs(ctx, ld) +} diff --git a/processor/processortest/unhealthy_processor.go b/processor/processortest/unhealthy_processor.go new file mode 100644 index 00000000000..196787de97c --- /dev/null +++ b/processor/processortest/unhealthy_processor.go @@ -0,0 +1,70 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package processortest // import "go.opentelemetry.io/collector/processor/processortest" + +import ( + "context" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/processor" +) + +// NewUnhealthyProcessorCreateSettings returns a new nop settings for Create*Processor functions. +func NewUnhealthyProcessorCreateSettings() processor.CreateSettings { + return processor.CreateSettings{ + TelemetrySettings: componenttest.NewNopTelemetrySettings(), + BuildInfo: component.NewDefaultBuildInfo(), + } +} + +// NewUnhealthyProcessorFactory returns a component.ProcessorFactory that constructs nop processors. +func NewUnhealthyProcessorFactory() processor.Factory { + return processor.NewFactory( + component.MustNewType("unhealthy"), + func() component.Config { + return &struct{}{} + }, + processor.WithTraces(createUnhealthyTracesProcessor, component.StabilityLevelStable), + processor.WithMetrics(createUnhealthyMetricsProcessor, component.StabilityLevelStable), + processor.WithLogs(createUnhealthyLogsProcessor, component.StabilityLevelStable), + ) +} + +func createUnhealthyTracesProcessor(_ context.Context, set processor.CreateSettings, _ component.Config, _ consumer.Traces) (processor.Traces, error) { + return &unhealthyProcessor{ + Consumer: consumertest.NewNop(), + telemetry: set.TelemetrySettings, + }, nil +} + +func createUnhealthyMetricsProcessor(_ context.Context, set processor.CreateSettings, _ component.Config, _ consumer.Metrics) (processor.Metrics, error) { + return &unhealthyProcessor{ + Consumer: consumertest.NewNop(), + telemetry: set.TelemetrySettings, + }, nil +} + +func createUnhealthyLogsProcessor(_ context.Context, set processor.CreateSettings, _ component.Config, _ consumer.Logs) (processor.Logs, error) { + return &unhealthyProcessor{ + Consumer: consumertest.NewNop(), + telemetry: set.TelemetrySettings, + }, nil +} + +type unhealthyProcessor struct { + component.StartFunc + component.ShutdownFunc + consumertest.Consumer + telemetry component.TelemetrySettings +} + +func (p unhealthyProcessor) Start(context.Context, component.Host) error { + go func() { + p.telemetry.ReportStatus(component.NewStatusEvent(component.StatusRecoverableError)) + }() + return nil +} diff --git a/processor/processortest/unhealthy_processor_test.go b/processor/processortest/unhealthy_processor_test.go new file mode 100644 index 00000000000..f00c4236a19 --- /dev/null +++ b/processor/processortest/unhealthy_processor_test.go @@ -0,0 +1,49 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package processortest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" +) + +func TestNewUnhealthyProcessorFactory(t *testing.T) { + factory := NewUnhealthyProcessorFactory() + require.NotNil(t, factory) + assert.Equal(t, component.MustNewType("unhealthy"), factory.Type()) + cfg := factory.CreateDefaultConfig() + assert.Equal(t, &struct{}{}, cfg) + + traces, err := factory.CreateTracesProcessor(context.Background(), NewUnhealthyProcessorCreateSettings(), cfg, consumertest.NewNop()) + require.NoError(t, err) + assert.Equal(t, consumer.Capabilities{MutatesData: false}, traces.Capabilities()) + assert.NoError(t, traces.Start(context.Background(), componenttest.NewNopHost())) + assert.NoError(t, traces.ConsumeTraces(context.Background(), ptrace.NewTraces())) + assert.NoError(t, traces.Shutdown(context.Background())) + + metrics, err := factory.CreateMetricsProcessor(context.Background(), NewUnhealthyProcessorCreateSettings(), cfg, consumertest.NewNop()) + require.NoError(t, err) + assert.Equal(t, consumer.Capabilities{MutatesData: false}, metrics.Capabilities()) + assert.NoError(t, metrics.Start(context.Background(), componenttest.NewNopHost())) + assert.NoError(t, metrics.ConsumeMetrics(context.Background(), pmetric.NewMetrics())) + assert.NoError(t, metrics.Shutdown(context.Background())) + + logs, err := factory.CreateLogsProcessor(context.Background(), NewUnhealthyProcessorCreateSettings(), cfg, consumertest.NewNop()) + require.NoError(t, err) + assert.Equal(t, consumer.Capabilities{MutatesData: false}, logs.Capabilities()) + assert.NoError(t, logs.Start(context.Background(), componenttest.NewNopHost())) + assert.NoError(t, logs.ConsumeLogs(context.Background(), plog.NewLogs())) + assert.NoError(t, logs.Shutdown(context.Background())) +} diff --git a/receiver/README.md b/receiver/README.md index 5c5555525f6..ee2b74a8c9c 100644 --- a/receiver/README.md +++ b/receiver/README.md @@ -2,24 +2,16 @@ A receiver is how data gets into the OpenTelemetry Collector. Generally, a receiver accepts data in a specified format, translates it into the internal -format and passes it to [processors](../processor/README.md) and -[exporters](../exporter/README.md) defined in the applicable -pipelines. +format and passes it to [processors](../processor/README.md) and [exporters](../exporter/README.md) defined +in the applicable pipelines. -Available trace receivers (sorted alphabetically): - -- [OTLP Receiver](otlpreceiver/README.md) - -Available metric receivers (sorted alphabetically): - -- [OTLP Receiver](otlpreceiver/README.md) - -Available log receivers (sorted alphabetically): +This repository hosts the following receiver available in traces, metrics +and logs pipelines: - [OTLP Receiver](otlpreceiver/README.md) The [contrib repository](https://github.com/open-telemetry/opentelemetry-collector-contrib) - has more receivers that can be added to custom builds of the collector. +has more receivers available in its builds. ## Configuring Receivers diff --git a/receiver/go.mod b/receiver/go.mod index 7fea3d1f124..468ae1f821d 100644 --- a/receiver/go.mod +++ b/receiver/go.mod @@ -1,64 +1,54 @@ module go.opentelemetry.io/collector/receiver -go 1.20 +go 1.21 require ( github.com/stretchr/testify v1.8.4 - go.opencensus.io v0.24.0 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 - go.opentelemetry.io/collector/consumer v0.85.0 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/otel v1.18.0 - go.opentelemetry.io/otel/metric v1.18.0 - go.opentelemetry.io/otel/sdk v1.18.0 - go.opentelemetry.io/otel/sdk/metric v0.41.0 - go.opentelemetry.io/otel/trace v1.18.0 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 + go.opentelemetry.io/collector/consumer v0.96.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 - go.uber.org/zap v1.26.0 + go.uber.org/zap v1.27.0 ) require ( - contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect - github.com/prometheus/statsd_exporter v0.22.7 // indirect - go.opentelemetry.io/collector/confmap v0.85.0 // indirect - go.opentelemetry.io/collector/exporter v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/processor v0.85.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector/confmap v0.96.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -70,26 +60,10 @@ replace go.opentelemetry.io/collector/confmap => ../confmap replace go.opentelemetry.io/collector/consumer => ../consumer -replace go.opentelemetry.io/collector/exporter => ../exporter - -replace go.opentelemetry.io/collector/extension => ../extension - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../extension/zpagesextension - replace go.opentelemetry.io/collector/featuregate => ../featuregate replace go.opentelemetry.io/collector/pdata => ../pdata -replace go.opentelemetry.io/collector/processor => ../processor - -replace go.opentelemetry.io/collector/semconv => ../semconv - retract v0.76.0 // Depends on retracted pdata v1.0.0-rc10 module -replace go.opentelemetry.io/collector/connector => ../connector - -replace go.opentelemetry.io/collector/config/confignet => ../config/confignet - replace go.opentelemetry.io/collector/config/configtelemetry => ../config/configtelemetry - -replace go.opentelemetry.io/collector/service => ../service diff --git a/receiver/go.sum b/receiver/go.sum index 15d68a28c23..06616cda85d 100644 --- a/receiver/go.sum +++ b/receiver/go.sum @@ -1,582 +1,126 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/receiver/otlpreceiver/README.md b/receiver/otlpreceiver/README.md index 603e320def3..0d6e5ef5a2c 100644 --- a/receiver/otlpreceiver/README.md +++ b/receiver/otlpreceiver/README.md @@ -1,12 +1,18 @@ # OTLP Receiver -| Status | | -| ------------------------ | --------------------- | -| Stability | traces [stable] | -| | metrics [stable] | -| | logs [beta] | -| Supported pipeline types | traces, metrics, logs | -| Distributions | [core], [contrib] | + +| Status | | +| ------------- |-----------| +| Stability | [beta]: logs | +| | [stable]: traces, metrics | +| Distributions | [core], [contrib] | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Areceiver%2Fotlp%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Areceiver%2Fotlp) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Areceiver%2Fotlp%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Areceiver%2Fotlp) | + +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[stable]: https://github.com/open-telemetry/opentelemetry-collector#stable +[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol +[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib + Receives data via gRPC or HTTP using [OTLP]( https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/otlp.md) @@ -30,7 +36,9 @@ The following settings are configurable: - `endpoint` (default = 0.0.0.0:4317 for grpc protocol, 0.0.0.0:4318 http protocol): host:port to which the receiver is going to receive data. The valid syntax is - described at https://github.com/grpc/grpc/blob/master/doc/naming.md. + described at https://github.com/grpc/grpc/blob/master/doc/naming.md. The + `component.UseLocalHostAsDefaultHost` feature gate changes these to localhost:4317 and + localhost:4318 respectively. This will become the default in a future release. ## Advanced Configuration diff --git a/receiver/otlpreceiver/config.go b/receiver/otlpreceiver/config.go index 2234e2532d9..8e512f5a278 100644 --- a/receiver/otlpreceiver/config.go +++ b/receiver/otlpreceiver/config.go @@ -22,7 +22,7 @@ const ( ) type HTTPConfig struct { - *confighttp.HTTPServerSettings `mapstructure:",squash"` + *confighttp.ServerConfig `mapstructure:",squash"` // The URL path to receive traces on. If omitted "/v1/traces" will be used. TracesURLPath string `mapstructure:"traces_url_path,omitempty"` @@ -36,8 +36,8 @@ type HTTPConfig struct { // Protocols is the configuration for the supported protocols. type Protocols struct { - GRPC *configgrpc.GRPCServerSettings `mapstructure:"grpc"` - HTTP *HTTPConfig `mapstructure:"http"` + GRPC *configgrpc.ServerConfig `mapstructure:"grpc"` + HTTP *HTTPConfig `mapstructure:"http"` } // Config defines configuration for OTLP receiver. @@ -60,7 +60,7 @@ func (cfg *Config) Validate() error { // Unmarshal a confmap.Conf into the config struct. func (cfg *Config) Unmarshal(conf *confmap.Conf) error { // first load the config normally - err := conf.Unmarshal(cfg, confmap.WithErrorUnused()) + err := conf.Unmarshal(cfg) if err != nil { return err } diff --git a/receiver/otlpreceiver/config.md b/receiver/otlpreceiver/config.md index 3f5ac4b9e1c..df6cf931a12 100644 --- a/receiver/otlpreceiver/config.md +++ b/receiver/otlpreceiver/config.md @@ -75,10 +75,10 @@ Config defines configuration for OTLP receiver. |-----------------------|-----------------------------------------------------------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------| | endpoint | string | 0.0.0.0:4318 | Endpoint configures the listening address for the server. | | tls | [configtls-TLSServerSetting](#configtls-tlsserversetting) | | TLSSetting struct exposes TLS client configuration. | -| cors | [confighttp-CORSSettings](#confighttp-corssettings) | | CORSSettings configures a receiver for HTTP cross-origin resource sharing (CORS). | +| cors | [confighttp-CORSConfig](#confighttp-corsconfig) | | CORSConfig configures a receiver for HTTP cross-origin resource sharing (CORS). | | max_request_body_size | int | 0 | MaxRequestBodySize configures the maximum allowed body size in bytes for a single request. The default `0` means there's no restriction | -### confighttp-CORSSettings +### confighttp-CORSConfig | Name | Type | Default | Docs | |-----------------|----------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| diff --git a/receiver/otlpreceiver/config_test.go b/receiver/otlpreceiver/config_test.go index 43e4fb2aa8b..031d8943cc3 100644 --- a/receiver/otlpreceiver/config_test.go +++ b/receiver/otlpreceiver/config_test.go @@ -86,13 +86,13 @@ func TestUnmarshalConfig(t *testing.T) { assert.Equal(t, &Config{ Protocols: Protocols{ - GRPC: &configgrpc.GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + GRPC: &configgrpc.ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "0.0.0.0:4317", Transport: "tcp", }, - TLSSetting: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CertFile: "test.crt", KeyFile: "test.key", }, @@ -116,15 +116,15 @@ func TestUnmarshalConfig(t *testing.T) { }, }, HTTP: &HTTPConfig{ - HTTPServerSettings: &confighttp.HTTPServerSettings{ + ServerConfig: &confighttp.ServerConfig{ Endpoint: "0.0.0.0:4318", - TLSSetting: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CertFile: "test.crt", KeyFile: "test.key", }, }, - CORS: &confighttp.CORSSettings{ + CORS: &confighttp.CORSConfig{ AllowedOrigins: []string{"https://*.test.com", "https://test.com"}, MaxAge: 7200, }, @@ -147,15 +147,15 @@ func TestUnmarshalConfigUnix(t *testing.T) { assert.Equal(t, &Config{ Protocols: Protocols{ - GRPC: &configgrpc.GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + GRPC: &configgrpc.ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "/tmp/grpc_otlp.sock", Transport: "unix", }, ReadBufferSize: 512 * 1024, }, HTTP: &HTTPConfig{ - HTTPServerSettings: &confighttp.HTTPServerSettings{ + ServerConfig: &confighttp.ServerConfig{ Endpoint: "/tmp/http_otlp.sock", }, TracesURLPath: defaultTracesURLPath, diff --git a/receiver/otlpreceiver/doc.go b/receiver/otlpreceiver/doc.go index 78378a5c082..f0974c12e2a 100644 --- a/receiver/otlpreceiver/doc.go +++ b/receiver/otlpreceiver/doc.go @@ -1,5 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +//go:generate mdatagen metadata.yaml + // Package otlpreceiver receives data in OTLP format. package otlpreceiver // import "go.opentelemetry.io/collector/receiver/otlpreceiver" diff --git a/receiver/otlpreceiver/encoder.go b/receiver/otlpreceiver/encoder.go index ca661b9c2e1..d37437c7ca9 100644 --- a/receiver/otlpreceiver/encoder.go +++ b/receiver/otlpreceiver/encoder.go @@ -21,9 +21,9 @@ const ( ) var ( - pbEncoder = &protoEncoder{} - jsEncoder = &jsonEncoder{} - jsonMarshaler = &jsonpb.Marshaler{} + pbEncoder = &protoEncoder{} + jsEncoder = &jsonEncoder{} + jsonPbMarshaler = &jsonpb.Marshaler{} ) type encoder interface { @@ -114,7 +114,7 @@ func (jsonEncoder) marshalLogsResponse(resp plogotlp.ExportResponse) ([]byte, er func (jsonEncoder) marshalStatus(resp *spb.Status) ([]byte, error) { buf := new(bytes.Buffer) - err := jsonMarshaler.Marshal(buf, resp) + err := jsonPbMarshaler.Marshal(buf, resp) return buf.Bytes(), err } diff --git a/receiver/otlpreceiver/factory.go b/receiver/otlpreceiver/factory.go index 11cf3dc6668..3e1df39032b 100644 --- a/receiver/otlpreceiver/factory.go +++ b/receiver/otlpreceiver/factory.go @@ -11,15 +11,15 @@ import ( "go.opentelemetry.io/collector/config/confighttp" "go.opentelemetry.io/collector/config/confignet" "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/internal/localhostgate" "go.opentelemetry.io/collector/internal/sharedcomponent" "go.opentelemetry.io/collector/receiver" + "go.opentelemetry.io/collector/receiver/otlpreceiver/internal/metadata" ) const ( - typeStr = "otlp" - - defaultGRPCEndpoint = "0.0.0.0:4317" - defaultHTTPEndpoint = "0.0.0.0:4318" + grpcPort = 4317 + httpPort = 4318 defaultTracesURLPath = "/v1/traces" defaultMetricsURLPath = "/v1/metrics" @@ -29,28 +29,29 @@ const ( // NewFactory creates a new OTLP receiver factory. func NewFactory() receiver.Factory { return receiver.NewFactory( - typeStr, + metadata.Type, createDefaultConfig, - receiver.WithTraces(createTraces, component.StabilityLevelStable), - receiver.WithMetrics(createMetrics, component.StabilityLevelStable), - receiver.WithLogs(createLog, component.StabilityLevelBeta)) + receiver.WithTraces(createTraces, metadata.TracesStability), + receiver.WithMetrics(createMetrics, metadata.MetricsStability), + receiver.WithLogs(createLog, metadata.LogsStability), + ) } // createDefaultConfig creates the default configuration for receiver. func createDefaultConfig() component.Config { return &Config{ Protocols: Protocols{ - GRPC: &configgrpc.GRPCServerSettings{ - NetAddr: confignet.NetAddr{ - Endpoint: defaultGRPCEndpoint, + GRPC: &configgrpc.ServerConfig{ + NetAddr: confignet.AddrConfig{ + Endpoint: localhostgate.EndpointForPort(grpcPort), Transport: "tcp", }, // We almost write 0 bytes, so no need to tune WriteBufferSize. ReadBufferSize: 512 * 1024, }, HTTP: &HTTPConfig{ - HTTPServerSettings: &confighttp.HTTPServerSettings{ - Endpoint: defaultHTTPEndpoint, + ServerConfig: &confighttp.ServerConfig{ + Endpoint: localhostgate.EndpointForPort(httpPort), }, TracesURLPath: defaultTracesURLPath, MetricsURLPath: defaultMetricsURLPath, @@ -68,16 +69,18 @@ func createTraces( nextConsumer consumer.Traces, ) (receiver.Traces, error) { oCfg := cfg.(*Config) - r, err := receivers.GetOrAdd(oCfg, func() (*otlpReceiver, error) { - return newOtlpReceiver(oCfg, set) - }) + r, err := receivers.LoadOrStore( + oCfg, + func() (*otlpReceiver, error) { + return newOtlpReceiver(oCfg, &set) + }, + &set.TelemetrySettings, + ) if err != nil { return nil, err } - if err = r.Unwrap().registerTraceConsumer(nextConsumer); err != nil { - return nil, err - } + r.Unwrap().registerTraceConsumer(nextConsumer) return r, nil } @@ -89,16 +92,18 @@ func createMetrics( consumer consumer.Metrics, ) (receiver.Metrics, error) { oCfg := cfg.(*Config) - r, err := receivers.GetOrAdd(oCfg, func() (*otlpReceiver, error) { - return newOtlpReceiver(oCfg, set) - }) + r, err := receivers.LoadOrStore( + oCfg, + func() (*otlpReceiver, error) { + return newOtlpReceiver(oCfg, &set) + }, + &set.TelemetrySettings, + ) if err != nil { return nil, err } - if err = r.Unwrap().registerMetricsConsumer(consumer); err != nil { - return nil, err - } + r.Unwrap().registerMetricsConsumer(consumer) return r, nil } @@ -110,16 +115,18 @@ func createLog( consumer consumer.Logs, ) (receiver.Logs, error) { oCfg := cfg.(*Config) - r, err := receivers.GetOrAdd(oCfg, func() (*otlpReceiver, error) { - return newOtlpReceiver(oCfg, set) - }) + r, err := receivers.LoadOrStore( + oCfg, + func() (*otlpReceiver, error) { + return newOtlpReceiver(oCfg, &set) + }, + &set.TelemetrySettings, + ) if err != nil { return nil, err } - if err = r.Unwrap().registerLogsConsumer(consumer); err != nil { - return nil, err - } + r.Unwrap().registerLogsConsumer(consumer) return r, nil } @@ -129,4 +136,4 @@ func createLog( // create separate objects, they must use one otlpReceiver object per configuration. // When the receiver is shutdown it should be removed from this map so the same configuration // can be recreated successfully. -var receivers = sharedcomponent.NewSharedComponents[*Config, *otlpReceiver]() +var receivers = sharedcomponent.NewMap[*Config, *otlpReceiver]() diff --git a/receiver/otlpreceiver/factory_test.go b/receiver/otlpreceiver/factory_test.go index 829c8934e5d..21a3a051f27 100644 --- a/receiver/otlpreceiver/factory_test.go +++ b/receiver/otlpreceiver/factory_test.go @@ -27,7 +27,7 @@ func TestCreateDefaultConfig(t *testing.T) { assert.NoError(t, componenttest.CheckConfigStruct(cfg)) } -func TestCreateReceiver(t *testing.T) { +func TestCreateSameReceiver(t *testing.T) { factory := NewFactory() cfg := factory.CreateDefaultConfig().(*Config) cfg.GRPC.NetAddr.Endpoint = testutil.GetAvailableLocalAddress(t) @@ -41,18 +41,25 @@ func TestCreateReceiver(t *testing.T) { mReceiver, err := factory.CreateMetricsReceiver(context.Background(), creationSet, cfg, consumertest.NewNop()) assert.NotNil(t, mReceiver) assert.NoError(t, err) + + lReceiver, err := factory.CreateMetricsReceiver(context.Background(), creationSet, cfg, consumertest.NewNop()) + assert.NotNil(t, lReceiver) + assert.NoError(t, err) + + assert.Same(t, tReceiver, mReceiver) + assert.Same(t, tReceiver, lReceiver) } func TestCreateTracesReceiver(t *testing.T) { factory := NewFactory() - defaultGRPCSettings := &configgrpc.GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + defaultGRPCSettings := &configgrpc.ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), Transport: "tcp", }, } defaultHTTPSettings := &HTTPConfig{ - HTTPServerSettings: &confighttp.HTTPServerSettings{ + ServerConfig: &confighttp.ServerConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), }, TracesURLPath: defaultTracesURLPath, @@ -61,9 +68,11 @@ func TestCreateTracesReceiver(t *testing.T) { } tests := []struct { - name string - cfg *Config - wantErr bool + name string + cfg *Config + wantStartErr bool + wantErr bool + sink consumer.Traces }{ { name: "default", @@ -73,13 +82,14 @@ func TestCreateTracesReceiver(t *testing.T) { HTTP: defaultHTTPSettings, }, }, + sink: consumertest.NewNop(), }, { name: "invalid_grpc_port", cfg: &Config{ Protocols: Protocols{ - GRPC: &configgrpc.GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + GRPC: &configgrpc.ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "localhost:112233", Transport: "tcp", }, @@ -87,7 +97,8 @@ func TestCreateTracesReceiver(t *testing.T) { HTTP: defaultHTTPSettings, }, }, - wantErr: true, + wantStartErr: true, + sink: consumertest.NewNop(), }, { name: "invalid_http_port", @@ -95,27 +106,36 @@ func TestCreateTracesReceiver(t *testing.T) { Protocols: Protocols{ GRPC: defaultGRPCSettings, HTTP: &HTTPConfig{ - HTTPServerSettings: &confighttp.HTTPServerSettings{ + ServerConfig: &confighttp.ServerConfig{ Endpoint: "localhost:112233", }, TracesURLPath: defaultTracesURLPath, }, }, }, - wantErr: true, + wantStartErr: true, + sink: consumertest.NewNop(), + }, + { + name: "no_http_or_grcp_config", + cfg: &Config{ + Protocols: Protocols{}, + }, + sink: consumertest.NewNop(), }, } ctx := context.Background() creationSet := receivertest.NewNopCreateSettings() for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - sink := new(consumertest.TracesSink) - tr, err := factory.CreateTracesReceiver(ctx, creationSet, tt.cfg, sink) - assert.NoError(t, err) - require.NotNil(t, tr) + tr, err := factory.CreateTracesReceiver(ctx, creationSet, tt.cfg, tt.sink) if tt.wantErr { + assert.Error(t, err) + return + } + assert.NoError(t, err) + if tt.wantStartErr { assert.Error(t, tr.Start(context.Background(), componenttest.NewNopHost())) - assert.NoError(t, tr.Shutdown(context.Background())) } else { assert.NoError(t, tr.Start(context.Background(), componenttest.NewNopHost())) assert.NoError(t, tr.Shutdown(context.Background())) @@ -126,14 +146,14 @@ func TestCreateTracesReceiver(t *testing.T) { func TestCreateMetricReceiver(t *testing.T) { factory := NewFactory() - defaultGRPCSettings := &configgrpc.GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + defaultGRPCSettings := &configgrpc.ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), Transport: "tcp", }, } defaultHTTPSettings := &HTTPConfig{ - HTTPServerSettings: &confighttp.HTTPServerSettings{ + ServerConfig: &confighttp.ServerConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), }, TracesURLPath: defaultTracesURLPath, @@ -142,9 +162,11 @@ func TestCreateMetricReceiver(t *testing.T) { } tests := []struct { - name string - cfg *Config - wantErr bool + name string + cfg *Config + wantStartErr bool + wantErr bool + sink consumer.Metrics }{ { name: "default", @@ -154,13 +176,14 @@ func TestCreateMetricReceiver(t *testing.T) { HTTP: defaultHTTPSettings, }, }, + sink: consumertest.NewNop(), }, { name: "invalid_grpc_address", cfg: &Config{ Protocols: Protocols{ - GRPC: &configgrpc.GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + GRPC: &configgrpc.ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "327.0.0.1:1122", Transport: "tcp", }, @@ -168,7 +191,8 @@ func TestCreateMetricReceiver(t *testing.T) { HTTP: defaultHTTPSettings, }, }, - wantErr: true, + wantStartErr: true, + sink: consumertest.NewNop(), }, { name: "invalid_http_address", @@ -176,25 +200,35 @@ func TestCreateMetricReceiver(t *testing.T) { Protocols: Protocols{ GRPC: defaultGRPCSettings, HTTP: &HTTPConfig{ - HTTPServerSettings: &confighttp.HTTPServerSettings{ + ServerConfig: &confighttp.ServerConfig{ Endpoint: "327.0.0.1:1122", }, MetricsURLPath: defaultMetricsURLPath, }, }, }, - wantErr: true, + wantStartErr: true, + sink: consumertest.NewNop(), + }, + { + name: "no_http_or_grcp_config", + cfg: &Config{ + Protocols: Protocols{}, + }, + sink: consumertest.NewNop(), }, } ctx := context.Background() creationSet := receivertest.NewNopCreateSettings() for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - sink := new(consumertest.MetricsSink) - mr, err := factory.CreateMetricsReceiver(ctx, creationSet, tt.cfg, sink) - assert.NoError(t, err) - require.NotNil(t, mr) + mr, err := factory.CreateMetricsReceiver(ctx, creationSet, tt.cfg, tt.sink) if tt.wantErr { + assert.Error(t, err) + return + } + assert.NoError(t, err) + if tt.wantStartErr { assert.Error(t, mr.Start(context.Background(), componenttest.NewNopHost())) } else { require.NoError(t, mr.Start(context.Background(), componenttest.NewNopHost())) @@ -206,14 +240,14 @@ func TestCreateMetricReceiver(t *testing.T) { func TestCreateLogReceiver(t *testing.T) { factory := NewFactory() - defaultGRPCSettings := &configgrpc.GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + defaultGRPCSettings := &configgrpc.ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), Transport: "tcp", }, } defaultHTTPSettings := &HTTPConfig{ - HTTPServerSettings: &confighttp.HTTPServerSettings{ + ServerConfig: &confighttp.ServerConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), }, TracesURLPath: defaultTracesURLPath, @@ -236,14 +270,14 @@ func TestCreateLogReceiver(t *testing.T) { HTTP: defaultHTTPSettings, }, }, - sink: new(consumertest.LogsSink), + sink: consumertest.NewNop(), }, { name: "invalid_grpc_address", cfg: &Config{ Protocols: Protocols{ - GRPC: &configgrpc.GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + GRPC: &configgrpc.ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: "327.0.0.1:1122", Transport: "tcp", }, @@ -252,7 +286,7 @@ func TestCreateLogReceiver(t *testing.T) { }, }, wantStartErr: true, - sink: new(consumertest.LogsSink), + sink: consumertest.NewNop(), }, { name: "invalid_http_address", @@ -260,7 +294,7 @@ func TestCreateLogReceiver(t *testing.T) { Protocols: Protocols{ GRPC: defaultGRPCSettings, HTTP: &HTTPConfig{ - HTTPServerSettings: &confighttp.HTTPServerSettings{ + ServerConfig: &confighttp.ServerConfig{ Endpoint: "327.0.0.1:1122", }, LogsURLPath: defaultLogsURLPath, @@ -268,30 +302,14 @@ func TestCreateLogReceiver(t *testing.T) { }, }, wantStartErr: true, - sink: new(consumertest.LogsSink), - }, - { - name: "no_next_consumer", - cfg: &Config{ - Protocols: Protocols{ - GRPC: defaultGRPCSettings, - HTTP: &HTTPConfig{ - HTTPServerSettings: &confighttp.HTTPServerSettings{ - Endpoint: "127.0.0.1:1122", - }, - }, - }, - }, - wantErr: true, - sink: nil, + sink: consumertest.NewNop(), }, { name: "no_http_or_grcp_config", cfg: &Config{ Protocols: Protocols{}, }, - wantErr: false, - sink: new(consumertest.LogsSink), + sink: consumertest.NewNop(), }, } ctx := context.Background() @@ -304,11 +322,8 @@ func TestCreateLogReceiver(t *testing.T) { return } assert.NoError(t, err) - require.NotNil(t, mr) - if tt.wantStartErr { assert.Error(t, mr.Start(context.Background(), componenttest.NewNopHost())) - assert.NoError(t, mr.Shutdown(context.Background())) } else { require.NoError(t, mr.Start(context.Background(), componenttest.NewNopHost())) assert.NoError(t, mr.Shutdown(context.Background())) diff --git a/receiver/otlpreceiver/go.mod b/receiver/otlpreceiver/go.mod index 9c0850d2eec..0ff401c1840 100644 --- a/receiver/otlpreceiver/go.mod +++ b/receiver/otlpreceiver/go.mod @@ -1,86 +1,84 @@ module go.opentelemetry.io/collector/receiver/otlpreceiver -go 1.20 +go 1.21 require ( github.com/gogo/protobuf v1.3.2 - github.com/klauspost/compress v1.17.0 + github.com/klauspost/compress v1.17.7 github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/configgrpc v0.85.0 - go.opentelemetry.io/collector/config/confighttp v0.85.0 - go.opentelemetry.io/collector/config/confignet v0.85.0 - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 - go.opentelemetry.io/collector/config/configtls v0.85.0 - go.opentelemetry.io/collector/confmap v0.85.0 - go.opentelemetry.io/collector/consumer v0.85.0 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/collector/receiver v0.85.0 - go.opentelemetry.io/collector/semconv v0.85.0 - go.uber.org/zap v1.26.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 - google.golang.org/grpc v1.58.1 - google.golang.org/protobuf v1.31.0 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/configgrpc v0.96.0 + go.opentelemetry.io/collector/config/confighttp v0.96.0 + go.opentelemetry.io/collector/config/confignet v0.96.0 + go.opentelemetry.io/collector/config/configtls v0.96.0 + go.opentelemetry.io/collector/confmap v0.96.0 + go.opentelemetry.io/collector/consumer v0.96.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/collector/receiver v0.96.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 + go.uber.org/zap v1.27.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 + google.golang.org/grpc v1.62.0 + google.golang.org/protobuf v1.32.0 ) require ( - cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68 // indirect - contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/felixge/httpsnoop v1.0.3 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/mostynb/go-grpc-compression v1.2.1 // indirect + github.com/mostynb/go-grpc-compression v1.2.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect - github.com/prometheus/statsd_exporter v0.22.7 // indirect - github.com/rs/cors v1.10.0 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/config/configauth v0.85.0 // indirect - go.opentelemetry.io/collector/config/configcompression v0.85.0 // indirect - go.opentelemetry.io/collector/config/configopaque v0.85.0 // indirect - go.opentelemetry.io/collector/config/internal v0.85.0 // indirect - go.opentelemetry.io/collector/exporter v0.85.0 // indirect - go.opentelemetry.io/collector/extension v0.85.0 // indirect - go.opentelemetry.io/collector/extension/auth v0.85.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 // indirect - go.opentelemetry.io/collector/processor v0.85.0 // indirect - go.opentelemetry.io/collector/service v0.0.0-20230915215502-07938f20fcc7 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 // indirect - go.opentelemetry.io/otel v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect - go.opentelemetry.io/otel/metric v1.18.0 // indirect - go.opentelemetry.io/otel/sdk v1.18.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect - go.opentelemetry.io/otel/trace v1.18.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/rs/cors v1.10.1 // indirect + go.opentelemetry.io/collector/config/configauth v0.96.0 // indirect + go.opentelemetry.io/collector/config/configcompression v0.96.0 // indirect + go.opentelemetry.io/collector/config/configopaque v1.3.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 // indirect + go.opentelemetry.io/collector/config/internal v0.96.0 // indirect + go.opentelemetry.io/collector/extension v0.96.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.96.0 // indirect + go.opentelemetry.io/collector/featuregate v1.3.0 // indirect + go.opentelemetry.io/contrib/config v0.4.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -108,10 +106,6 @@ replace go.opentelemetry.io/collector/config/internal => ../../config/internal replace go.opentelemetry.io/collector/confmap => ../../confmap -replace go.opentelemetry.io/collector/connector => ../../connector - -replace go.opentelemetry.io/collector/exporter => ../../exporter - replace go.opentelemetry.io/collector/extension => ../../extension replace go.opentelemetry.io/collector/extension/auth => ../../extension/auth @@ -120,16 +114,8 @@ replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata -replace go.opentelemetry.io/collector/processor => ../../processor - replace go.opentelemetry.io/collector/receiver => ../ -replace go.opentelemetry.io/collector/semconv => ../../semconv - -replace go.opentelemetry.io/collector/service => ../../service - -replace go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension - replace go.opentelemetry.io/collector/consumer => ../../consumer retract ( diff --git a/receiver/otlpreceiver/go.sum b/receiver/otlpreceiver/go.sum index 81ac3062768..6dc69bb0e99 100644 --- a/receiver/otlpreceiver/go.sum +++ b/receiver/otlpreceiver/go.sum @@ -1,607 +1,176 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68 h1:aRVqY1p2IJaBGStWMsQMpkAa83cPkCDLl80eOj0Rbz4= cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68/go.mod h1:1a3eRNYX12fs5UABBIXS8HXVvQbX9hRB/RkEBPORpe8= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mostynb/go-grpc-compression v1.2.1 h1:16tdYxBZSD8p9AUmvw4F7Nyc2T4/eE7XsIXrgxSEcJI= -github.com/mostynb/go-grpc-compression v1.2.1/go.mod h1:oidYvYyefMmhcuvU8fLJ8FfZyTyVzJ6SkmD5fIKgRe8= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/mostynb/go-grpc-compression v1.2.2 h1:XaDbnRvt2+1vgr0b/l0qh4mJAfIxE0bKXtz2Znl3GGI= +github.com/mostynb/go-grpc-compression v1.2.2/go.mod h1:GOCr2KBxXcblCuczg3YdLQlcin1/NfyDA348ckuCH6w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rs/cors v1.10.0 h1:62NOS1h+r8p1mW6FM0FSB0exioXLhd/sh15KpjWBZ+8= -github.com/rs/cors v1.10.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/contrib/config v0.4.0 h1:Xb+ncYOqseLroMuBesGNRgVQolXcXOhMj7EhGwJCdHs= +go.opentelemetry.io/contrib/config v0.4.0/go.mod h1:drNk2xRqLWW4/amk6Uh1S+sDAJTc7bcEEN1GfJzj418= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/receiver/otlpreceiver/internal/errors/errors.go b/receiver/otlpreceiver/internal/errors/errors.go new file mode 100644 index 00000000000..ee9d79e1c7c --- /dev/null +++ b/receiver/otlpreceiver/internal/errors/errors.go @@ -0,0 +1,26 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package errors // import "go.opentelemetry.io/collector/receiver/otlpreceiver/internal/errors" + +import ( + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "go.opentelemetry.io/collector/consumer/consumererror" +) + +func GetStatusFromError(err error) error { + s, ok := status.FromError(err) + if !ok { + // Default to a retryable error + // https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md#failures + code := codes.Unavailable + if consumererror.IsPermanent(err) { + // If an error is permanent but doesn't have an attached gRPC status, assume it is server-side. + code = codes.Internal + } + s = status.New(code, err.Error()) + } + return s.Err() +} diff --git a/receiver/otlpreceiver/internal/errors/errors_test.go b/receiver/otlpreceiver/internal/errors/errors_test.go new file mode 100644 index 00000000000..c75b5bf041f --- /dev/null +++ b/receiver/otlpreceiver/internal/errors/errors_test.go @@ -0,0 +1,45 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package errors // import "go.opentelemetry.io/collector/receiver/otlpreceiver/internal/util" + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "go.opentelemetry.io/collector/consumer/consumererror" +) + +func Test_GetStatusFromError(t *testing.T) { + tests := []struct { + name string + input error + expected *status.Status + }{ + { + name: "Status", + input: status.Error(codes.Aborted, "test"), + expected: status.New(codes.Aborted, "test"), + }, + { + name: "Permanent Error", + input: consumererror.NewPermanent(fmt.Errorf("test")), + expected: status.New(codes.Internal, "Permanent error: test"), + }, + { + name: "Non-Permanent Error", + input: fmt.Errorf("test"), + expected: status.New(codes.Unavailable, "test"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := GetStatusFromError(tt.input) + assert.Equal(t, tt.expected.Err(), result) + }) + } +} diff --git a/receiver/otlpreceiver/internal/logs/otlp.go b/receiver/otlpreceiver/internal/logs/otlp.go index faf92372d51..3088043267c 100644 --- a/receiver/otlpreceiver/internal/logs/otlp.go +++ b/receiver/otlpreceiver/internal/logs/otlp.go @@ -8,6 +8,7 @@ import ( "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/pdata/plog/plogotlp" + "go.opentelemetry.io/collector/receiver/otlpreceiver/internal/errors" "go.opentelemetry.io/collector/receiver/receiverhelper" ) @@ -40,5 +41,15 @@ func (r *Receiver) Export(ctx context.Context, req plogotlp.ExportRequest) (plog err := r.nextConsumer.ConsumeLogs(ctx, ld) r.obsreport.EndLogsOp(ctx, dataFormatProtobuf, numSpans, err) - return plogotlp.NewExportResponse(), err + // Use appropriate status codes for permanent/non-permanent errors + // If we return the error straightaway, then the grpc implementation will set status code to Unknown + // Refer: https://github.com/grpc/grpc-go/blob/v1.59.0/server.go#L1345 + // So, convert the error to appropriate grpc status and return the error + // NonPermanent errors will be converted to codes.Unavailable (equivalent to HTTP 503) + // Permanent errors will be converted to codes.InvalidArgument (equivalent to HTTP 400) + if err != nil { + return plogotlp.NewExportResponse(), errors.GetStatusFromError(err) + } + + return plogotlp.NewExportResponse(), nil } diff --git a/receiver/otlpreceiver/internal/logs/otlp_test.go b/receiver/otlpreceiver/internal/logs/otlp_test.go index beb64c159e1..b2d3178d011 100644 --- a/receiver/otlpreceiver/internal/logs/otlp_test.go +++ b/receiver/otlpreceiver/internal/logs/otlp_test.go @@ -12,10 +12,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" + "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/status" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/pdata/plog/plogotlp" @@ -47,13 +50,25 @@ func TestExport_EmptyRequest(t *testing.T) { assert.NotNil(t, resp, "The response is missing") } -func TestExport_ErrorConsumer(t *testing.T) { +func TestExport_NonPermanentErrorConsumer(t *testing.T) { ld := testdata.GenerateLogs(1) req := plogotlp.NewExportRequestFromLogs(ld) logClient := makeLogsServiceClient(t, consumertest.NewErr(errors.New("my error"))) resp, err := logClient.Export(context.Background(), req) - assert.EqualError(t, err, "rpc error: code = Unknown desc = my error") + assert.EqualError(t, err, "rpc error: code = Unavailable desc = my error") + assert.IsType(t, status.Error(codes.Unknown, ""), err) + assert.Equal(t, plogotlp.ExportResponse{}, resp) +} + +func TestExport_PermanentErrorConsumer(t *testing.T) { + ld := testdata.GenerateLogs(1) + req := plogotlp.NewExportRequestFromLogs(ld) + + logClient := makeLogsServiceClient(t, consumertest.NewErr(consumererror.NewPermanent(errors.New("my error")))) + resp, err := logClient.Export(context.Background(), req) + assert.EqualError(t, err, "rpc error: code = Internal desc = Permanent error: my error") + assert.IsType(t, status.Error(codes.Unknown, ""), err) assert.Equal(t, plogotlp.ExportResponse{}, resp) } @@ -77,7 +92,7 @@ func otlpReceiverOnGRPCServer(t *testing.T, lc consumer.Logs) net.Addr { }) set := receivertest.NewNopCreateSettings() - set.ID = component.NewIDWithName("otlp", "log") + set.ID = component.MustNewIDWithName("otlp", "log") obsreport, err := receiverhelper.NewObsReport(receiverhelper.ObsReportSettings{ ReceiverID: set.ID, Transport: "grpc", diff --git a/receiver/otlpreceiver/internal/logs/package_test.go b/receiver/otlpreceiver/internal/logs/package_test.go new file mode 100644 index 00000000000..1158f120b28 --- /dev/null +++ b/receiver/otlpreceiver/internal/logs/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package logs + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/receiver/otlpreceiver/internal/metadata/generated_status.go b/receiver/otlpreceiver/internal/metadata/generated_status.go new file mode 100644 index 00000000000..aa5483d7b5a --- /dev/null +++ b/receiver/otlpreceiver/internal/metadata/generated_status.go @@ -0,0 +1,29 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("otlp") + scopeName = "go.opentelemetry.io/collector/receiver/otlpreceiver" +) + +const ( + LogsStability = component.StabilityLevelBeta + TracesStability = component.StabilityLevelStable + MetricsStability = component.StabilityLevelStable +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter(scopeName) +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer(scopeName) +} diff --git a/receiver/otlpreceiver/internal/metrics/otlp.go b/receiver/otlpreceiver/internal/metrics/otlp.go index 59330dcc318..e06e2fd6d94 100644 --- a/receiver/otlpreceiver/internal/metrics/otlp.go +++ b/receiver/otlpreceiver/internal/metrics/otlp.go @@ -8,6 +8,7 @@ import ( "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/pdata/pmetric/pmetricotlp" + "go.opentelemetry.io/collector/receiver/otlpreceiver/internal/errors" "go.opentelemetry.io/collector/receiver/receiverhelper" ) @@ -40,5 +41,15 @@ func (r *Receiver) Export(ctx context.Context, req pmetricotlp.ExportRequest) (p err := r.nextConsumer.ConsumeMetrics(ctx, md) r.obsreport.EndMetricsOp(ctx, dataFormatProtobuf, dataPointCount, err) - return pmetricotlp.NewExportResponse(), err + // Use appropriate status codes for permanent/non-permanent errors + // If we return the error straightaway, then the grpc implementation will set status code to Unknown + // Refer: https://github.com/grpc/grpc-go/blob/v1.59.0/server.go#L1345 + // So, convert the error to appropriate grpc status and return the error + // NonPermanent errors will be converted to codes.Unavailable (equivalent to HTTP 503) + // Permanent errors will be converted to codes.InvalidArgument (equivalent to HTTP 400) + if err != nil { + return pmetricotlp.NewExportResponse(), errors.GetStatusFromError(err) + } + + return pmetricotlp.NewExportResponse(), nil } diff --git a/receiver/otlpreceiver/internal/metrics/otlp_test.go b/receiver/otlpreceiver/internal/metrics/otlp_test.go index d8691daaba1..babc366119f 100644 --- a/receiver/otlpreceiver/internal/metrics/otlp_test.go +++ b/receiver/otlpreceiver/internal/metrics/otlp_test.go @@ -12,10 +12,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" + "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/status" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/pdata/pmetric/pmetricotlp" @@ -47,13 +50,25 @@ func TestExport_EmptyRequest(t *testing.T) { require.NotNil(t, resp) } -func TestExport_ErrorConsumer(t *testing.T) { +func TestExport_NonPermanentErrorConsumer(t *testing.T) { md := testdata.GenerateMetrics(1) req := pmetricotlp.NewExportRequestFromMetrics(md) metricsClient := makeMetricsServiceClient(t, consumertest.NewErr(errors.New("my error"))) resp, err := metricsClient.Export(context.Background(), req) - assert.EqualError(t, err, "rpc error: code = Unknown desc = my error") + assert.EqualError(t, err, "rpc error: code = Unavailable desc = my error") + assert.IsType(t, status.Error(codes.Unknown, ""), err) + assert.Equal(t, pmetricotlp.ExportResponse{}, resp) +} + +func TestExport_PermanentErrorConsumer(t *testing.T) { + ld := testdata.GenerateMetrics(1) + req := pmetricotlp.NewExportRequestFromMetrics(ld) + + metricsClient := makeMetricsServiceClient(t, consumertest.NewErr(consumererror.NewPermanent(errors.New("my error")))) + resp, err := metricsClient.Export(context.Background(), req) + assert.EqualError(t, err, "rpc error: code = Internal desc = Permanent error: my error") + assert.IsType(t, status.Error(codes.Unknown, ""), err) assert.Equal(t, pmetricotlp.ExportResponse{}, resp) } @@ -78,7 +93,7 @@ func otlpReceiverOnGRPCServer(t *testing.T, mc consumer.Metrics) net.Addr { }) set := receivertest.NewNopCreateSettings() - set.ID = component.NewIDWithName("otlp", "metrics") + set.ID = component.MustNewIDWithName("otlp", "metrics") obsreport, err := receiverhelper.NewObsReport(receiverhelper.ObsReportSettings{ ReceiverID: set.ID, Transport: "grpc", diff --git a/receiver/otlpreceiver/internal/metrics/package_test.go b/receiver/otlpreceiver/internal/metrics/package_test.go new file mode 100644 index 00000000000..b8f16a8085e --- /dev/null +++ b/receiver/otlpreceiver/internal/metrics/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package metrics + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/receiver/otlpreceiver/internal/trace/otlp.go b/receiver/otlpreceiver/internal/trace/otlp.go index d14779e712b..615b597f05e 100644 --- a/receiver/otlpreceiver/internal/trace/otlp.go +++ b/receiver/otlpreceiver/internal/trace/otlp.go @@ -8,6 +8,7 @@ import ( "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp" + "go.opentelemetry.io/collector/receiver/otlpreceiver/internal/errors" "go.opentelemetry.io/collector/receiver/receiverhelper" ) @@ -41,5 +42,15 @@ func (r *Receiver) Export(ctx context.Context, req ptraceotlp.ExportRequest) (pt err := r.nextConsumer.ConsumeTraces(ctx, td) r.obsreport.EndTracesOp(ctx, dataFormatProtobuf, numSpans, err) - return ptraceotlp.NewExportResponse(), err + // Use appropriate status codes for permanent/non-permanent errors + // If we return the error straightaway, then the grpc implementation will set status code to Unknown + // Refer: https://github.com/grpc/grpc-go/blob/v1.59.0/server.go#L1345 + // So, convert the error to appropriate grpc status and return the error + // NonPermanent errors will be converted to codes.Unavailable (equivalent to HTTP 503) + // Permanent errors will be converted to codes.InvalidArgument (equivalent to HTTP 400) + if err != nil { + return ptraceotlp.NewExportResponse(), errors.GetStatusFromError(err) + } + + return ptraceotlp.NewExportResponse(), nil } diff --git a/receiver/otlpreceiver/internal/trace/otlp_test.go b/receiver/otlpreceiver/internal/trace/otlp_test.go index fcb7611c75f..58bfc61f4fc 100644 --- a/receiver/otlpreceiver/internal/trace/otlp_test.go +++ b/receiver/otlpreceiver/internal/trace/otlp_test.go @@ -12,10 +12,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" + "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/status" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp" @@ -45,13 +48,24 @@ func TestExport_EmptyRequest(t *testing.T) { assert.NotNil(t, resp, "The response is missing") } -func TestExport_ErrorConsumer(t *testing.T) { +func TestExport_NonPermanentErrorConsumer(t *testing.T) { td := testdata.GenerateTraces(1) req := ptraceotlp.NewExportRequestFromTraces(td) traceClient := makeTraceServiceClient(t, consumertest.NewErr(errors.New("my error"))) resp, err := traceClient.Export(context.Background(), req) - assert.EqualError(t, err, "rpc error: code = Unknown desc = my error") + assert.EqualError(t, err, "rpc error: code = Unavailable desc = my error") + assert.IsType(t, status.Error(codes.Unknown, ""), err) + assert.Equal(t, ptraceotlp.ExportResponse{}, resp) +} +func TestExport_PermanentErrorConsumer(t *testing.T) { + ld := testdata.GenerateTraces(1) + req := ptraceotlp.NewExportRequestFromTraces(ld) + + traceClient := makeTraceServiceClient(t, consumertest.NewErr(consumererror.NewPermanent(errors.New("my error")))) + resp, err := traceClient.Export(context.Background(), req) + assert.EqualError(t, err, "rpc error: code = Internal desc = Permanent error: my error") + assert.IsType(t, status.Error(codes.Unknown, ""), err) assert.Equal(t, ptraceotlp.ExportResponse{}, resp) } @@ -75,7 +89,7 @@ func otlpReceiverOnGRPCServer(t *testing.T, tc consumer.Traces) net.Addr { }) set := receivertest.NewNopCreateSettings() - set.ID = component.NewIDWithName("otlp", "trace") + set.ID = component.MustNewIDWithName("otlp", "trace") obsreport, err := receiverhelper.NewObsReport(receiverhelper.ObsReportSettings{ ReceiverID: set.ID, Transport: "grpc", diff --git a/receiver/otlpreceiver/internal/trace/package_test.go b/receiver/otlpreceiver/internal/trace/package_test.go new file mode 100644 index 00000000000..ac6d5ff970c --- /dev/null +++ b/receiver/otlpreceiver/internal/trace/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package trace + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/receiver/otlpreceiver/metadata.yaml b/receiver/otlpreceiver/metadata.yaml new file mode 100644 index 00000000000..c3036a3341d --- /dev/null +++ b/receiver/otlpreceiver/metadata.yaml @@ -0,0 +1,8 @@ +type: otlp + +status: + class: receiver + stability: + stable: [traces, metrics] + beta: [logs] + distributions: [core, contrib] diff --git a/receiver/otlpreceiver/otlp.go b/receiver/otlpreceiver/otlp.go index faf9a68fe04..91936bfb6a5 100644 --- a/receiver/otlpreceiver/otlp.go +++ b/receiver/otlpreceiver/otlp.go @@ -6,7 +6,6 @@ package otlpreceiver // import "go.opentelemetry.io/collector/receiver/otlprecei import ( "context" "errors" - "fmt" "net" "net/http" "sync" @@ -15,7 +14,6 @@ import ( "google.golang.org/grpc" "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/config/configgrpc" "go.opentelemetry.io/collector/config/confighttp" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/pdata/plog/plogotlp" @@ -32,37 +30,36 @@ import ( type otlpReceiver struct { cfg *Config serverGRPC *grpc.Server - httpMux *http.ServeMux serverHTTP *http.Server - tracesReceiver *trace.Receiver - metricsReceiver *metrics.Receiver - logsReceiver *logs.Receiver - shutdownWG sync.WaitGroup + nextTraces consumer.Traces + nextMetrics consumer.Metrics + nextLogs consumer.Logs + shutdownWG sync.WaitGroup obsrepGRPC *receiverhelper.ObsReport obsrepHTTP *receiverhelper.ObsReport - settings receiver.CreateSettings + settings *receiver.CreateSettings } // newOtlpReceiver just creates the OpenTelemetry receiver services. It is the caller's // responsibility to invoke the respective Start*Reception methods as well // as the various Stop*Reception methods to end it. -func newOtlpReceiver(cfg *Config, set receiver.CreateSettings) (*otlpReceiver, error) { +func newOtlpReceiver(cfg *Config, set *receiver.CreateSettings) (*otlpReceiver, error) { r := &otlpReceiver{ - cfg: cfg, - settings: set, - } - if cfg.HTTP != nil { - r.httpMux = http.NewServeMux() + cfg: cfg, + nextTraces: nil, + nextMetrics: nil, + nextLogs: nil, + settings: set, } var err error r.obsrepGRPC, err = receiverhelper.NewObsReport(receiverhelper.ObsReportSettings{ ReceiverID: set.ID, Transport: "grpc", - ReceiverCreateSettings: set, + ReceiverCreateSettings: *set, }) if err != nil { return nil, err @@ -70,7 +67,7 @@ func newOtlpReceiver(cfg *Config, set receiver.CreateSettings) (*otlpReceiver, e r.obsrepHTTP, err = receiverhelper.NewObsReport(receiverhelper.ObsReportSettings{ ReceiverID: set.ID, Transport: "http", - ReceiverCreateSettings: set, + ReceiverCreateSettings: *set, }) if err != nil { return nil, err @@ -79,91 +76,110 @@ func newOtlpReceiver(cfg *Config, set receiver.CreateSettings) (*otlpReceiver, e return r, nil } -func (r *otlpReceiver) startGRPCServer(cfg *configgrpc.GRPCServerSettings, host component.Host) error { - r.settings.Logger.Info("Starting GRPC server", zap.String("endpoint", cfg.NetAddr.Endpoint)) +func (r *otlpReceiver) startGRPCServer(host component.Host) error { + // If GRPC is not enabled, nothing to start. + if r.cfg.GRPC == nil { + return nil + } - gln, err := cfg.ToListener() - if err != nil { + var err error + if r.serverGRPC, err = r.cfg.GRPC.ToServerContext(context.Background(), host, r.settings.TelemetrySettings); err != nil { + return err + } + + if r.nextTraces != nil { + ptraceotlp.RegisterGRPCServer(r.serverGRPC, trace.New(r.nextTraces, r.obsrepGRPC)) + } + + if r.nextMetrics != nil { + pmetricotlp.RegisterGRPCServer(r.serverGRPC, metrics.New(r.nextMetrics, r.obsrepGRPC)) + } + + if r.nextLogs != nil { + plogotlp.RegisterGRPCServer(r.serverGRPC, logs.New(r.nextLogs, r.obsrepGRPC)) + } + + r.settings.Logger.Info("Starting GRPC server", zap.String("endpoint", r.cfg.GRPC.NetAddr.Endpoint)) + var gln net.Listener + if gln, err = r.cfg.GRPC.NetAddr.Listen(context.Background()); err != nil { return err } + r.shutdownWG.Add(1) go func() { defer r.shutdownWG.Done() if errGrpc := r.serverGRPC.Serve(gln); errGrpc != nil && !errors.Is(errGrpc, grpc.ErrServerStopped) { - host.ReportFatalError(errGrpc) + r.settings.ReportStatus(component.NewFatalErrorEvent(errGrpc)) } }() return nil } -func (r *otlpReceiver) startHTTPServer(cfg *confighttp.HTTPServerSettings, host component.Host) error { - r.settings.Logger.Info("Starting HTTP server", zap.String("endpoint", cfg.Endpoint)) +func (r *otlpReceiver) startHTTPServer(host component.Host) error { + // If HTTP is not enabled, nothing to start. + if r.cfg.HTTP == nil { + return nil + } + + httpMux := http.NewServeMux() + if r.nextTraces != nil { + httpTracesReceiver := trace.New(r.nextTraces, r.obsrepHTTP) + httpMux.HandleFunc(r.cfg.HTTP.TracesURLPath, func(resp http.ResponseWriter, req *http.Request) { + handleTraces(resp, req, httpTracesReceiver) + }) + } + + if r.nextMetrics != nil { + httpMetricsReceiver := metrics.New(r.nextMetrics, r.obsrepHTTP) + httpMux.HandleFunc(r.cfg.HTTP.MetricsURLPath, func(resp http.ResponseWriter, req *http.Request) { + handleMetrics(resp, req, httpMetricsReceiver) + }) + } + + if r.nextLogs != nil { + httpLogsReceiver := logs.New(r.nextLogs, r.obsrepHTTP) + httpMux.HandleFunc(r.cfg.HTTP.LogsURLPath, func(resp http.ResponseWriter, req *http.Request) { + handleLogs(resp, req, httpLogsReceiver) + }) + } + + var err error + if r.serverHTTP, err = r.cfg.HTTP.ToServer(host, r.settings.TelemetrySettings, httpMux, confighttp.WithErrorHandler(errorHandler)); err != nil { + return err + } + + r.settings.Logger.Info("Starting HTTP server", zap.String("endpoint", r.cfg.HTTP.ServerConfig.Endpoint)) var hln net.Listener - hln, err := cfg.ToListener() - if err != nil { + if hln, err = r.cfg.HTTP.ServerConfig.ToListener(); err != nil { return err } + r.shutdownWG.Add(1) go func() { defer r.shutdownWG.Done() if errHTTP := r.serverHTTP.Serve(hln); errHTTP != nil && !errors.Is(errHTTP, http.ErrServerClosed) { - host.ReportFatalError(errHTTP) + r.settings.ReportStatus(component.NewFatalErrorEvent(errHTTP)) } }() return nil } -func (r *otlpReceiver) startProtocolServers(host component.Host) error { - var err error - if r.cfg.GRPC != nil { - r.serverGRPC, err = r.cfg.GRPC.ToServer(host, r.settings.TelemetrySettings) - if err != nil { - return err - } - - if r.tracesReceiver != nil { - ptraceotlp.RegisterGRPCServer(r.serverGRPC, r.tracesReceiver) - } - - if r.metricsReceiver != nil { - pmetricotlp.RegisterGRPCServer(r.serverGRPC, r.metricsReceiver) - } - - if r.logsReceiver != nil { - plogotlp.RegisterGRPCServer(r.serverGRPC, r.logsReceiver) - } - - err = r.startGRPCServer(r.cfg.GRPC, host) - if err != nil { - return err - } +// Start runs the trace receiver on the gRPC server. Currently +// it also enables the metrics receiver too. +func (r *otlpReceiver) Start(ctx context.Context, host component.Host) error { + if err := r.startGRPCServer(host); err != nil { + return err } - if r.cfg.HTTP != nil { - r.serverHTTP, err = r.cfg.HTTP.ToServer( - host, - r.settings.TelemetrySettings, - r.httpMux, - confighttp.WithErrorHandler(errorHandler), - ) - if err != nil { - return err - } - - err = r.startHTTPServer(r.cfg.HTTP.HTTPServerSettings, host) - if err != nil { - return err - } + if err := r.startHTTPServer(host); err != nil { + // It's possible that a valid GRPC server configuration was specified, + // but an invalid HTTP configuration. If that's the case, the successfully + // started GRPC server must be shutdown to ensure no goroutines are leaked. + return errors.Join(err, r.Shutdown(ctx)) } - return err -} - -// Start runs the trace receiver on the gRPC server. Currently -// it also enables the metrics receiver too. -func (r *otlpReceiver) Start(_ context.Context, host component.Host) error { - return r.startProtocolServers(host) + return nil } // Shutdown is a method to turn off receiving. @@ -182,87 +198,14 @@ func (r *otlpReceiver) Shutdown(ctx context.Context) error { return err } -func (r *otlpReceiver) registerTraceConsumer(tc consumer.Traces) error { - if tc == nil { - return component.ErrNilNextConsumer - } - r.tracesReceiver = trace.New(tc, r.obsrepGRPC) - httpTracesReceiver := trace.New(tc, r.obsrepHTTP) - if r.httpMux != nil { - r.httpMux.HandleFunc(r.cfg.HTTP.TracesURLPath, func(resp http.ResponseWriter, req *http.Request) { - if req.Method != http.MethodPost { - handleUnmatchedMethod(resp) - return - } - switch getMimeTypeFromContentType(req.Header.Get("Content-Type")) { - case pbContentType: - handleTraces(resp, req, httpTracesReceiver, pbEncoder) - case jsonContentType: - handleTraces(resp, req, httpTracesReceiver, jsEncoder) - default: - handleUnmatchedContentType(resp) - } - }) - } - return nil -} - -func (r *otlpReceiver) registerMetricsConsumer(mc consumer.Metrics) error { - if mc == nil { - return component.ErrNilNextConsumer - } - r.metricsReceiver = metrics.New(mc, r.obsrepGRPC) - httpMetricsReceiver := metrics.New(mc, r.obsrepHTTP) - if r.httpMux != nil { - r.httpMux.HandleFunc(r.cfg.HTTP.MetricsURLPath, func(resp http.ResponseWriter, req *http.Request) { - if req.Method != http.MethodPost { - handleUnmatchedMethod(resp) - return - } - switch getMimeTypeFromContentType(req.Header.Get("Content-Type")) { - case pbContentType: - handleMetrics(resp, req, httpMetricsReceiver, pbEncoder) - case jsonContentType: - handleMetrics(resp, req, httpMetricsReceiver, jsEncoder) - default: - handleUnmatchedContentType(resp) - } - }) - } - return nil -} - -func (r *otlpReceiver) registerLogsConsumer(lc consumer.Logs) error { - if lc == nil { - return component.ErrNilNextConsumer - } - r.logsReceiver = logs.New(lc, r.obsrepGRPC) - httpLogsReceiver := logs.New(lc, r.obsrepHTTP) - if r.httpMux != nil { - r.httpMux.HandleFunc(r.cfg.HTTP.LogsURLPath, func(resp http.ResponseWriter, req *http.Request) { - if req.Method != http.MethodPost { - handleUnmatchedMethod(resp) - return - } - switch getMimeTypeFromContentType(req.Header.Get("Content-Type")) { - case pbContentType: - handleLogs(resp, req, httpLogsReceiver, pbEncoder) - case jsonContentType: - handleLogs(resp, req, httpLogsReceiver, jsEncoder) - default: - handleUnmatchedContentType(resp) - } - }) - } - return nil +func (r *otlpReceiver) registerTraceConsumer(tc consumer.Traces) { + r.nextTraces = tc } -func handleUnmatchedMethod(resp http.ResponseWriter) { - status := http.StatusMethodNotAllowed - writeResponse(resp, "text/plain", status, []byte(fmt.Sprintf("%v method not allowed, supported: [POST]", status))) +func (r *otlpReceiver) registerMetricsConsumer(mc consumer.Metrics) { + r.nextMetrics = mc } -func handleUnmatchedContentType(resp http.ResponseWriter) { - status := http.StatusUnsupportedMediaType - writeResponse(resp, "text/plain", status, []byte(fmt.Sprintf("%v unsupported media type, supported: [%s, %s]", status, jsonContentType, pbContentType))) +func (r *otlpReceiver) registerLogsConsumer(lc consumer.Logs) { + r.nextLogs = lc } diff --git a/receiver/otlpreceiver/otlp_test.go b/receiver/otlpreceiver/otlp_test.go index bc7cd3738b7..85b261cd6af 100644 --- a/receiver/otlpreceiver/otlp_test.go +++ b/receiver/otlpreceiver/otlp_test.go @@ -13,6 +13,7 @@ import ( "io" "net" "net/http" + "strings" "sync" "testing" "time" @@ -32,100 +33,22 @@ import ( "go.opentelemetry.io/collector/config/configgrpc" "go.opentelemetry.io/collector/config/confighttp" "go.opentelemetry.io/collector/config/confignet" - "go.opentelemetry.io/collector/config/configtelemetry" "go.opentelemetry.io/collector/config/configtls" "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/internal/testutil" - "go.opentelemetry.io/collector/obsreport/obsreporttest" + "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/ptrace" "go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp" - "go.opentelemetry.io/collector/receiver" "go.opentelemetry.io/collector/receiver/receivertest" - semconv "go.opentelemetry.io/collector/semconv/v1.5.0" ) const otlpReceiverName = "receiver_test" -var otlpReceiverID = component.NewIDWithName(typeStr, otlpReceiverName) - -var traceJSON = []byte(` - { - "resource_spans": [ - { - "resource": { - "attributes": [ - { - "key": "host.name", - "value": { "stringValue": "testHost" } - } - ] - }, - "scope_spans": [ - { - "spans": [ - { - "trace_id": "5B8EFFF798038103D269B633813FC60C", - "span_id": "EEE19B7EC3C1B174", - "parent_span_id": "EEE19B7EC3C1B173", - "name": "testSpan", - "start_time_unix_nano": 1544712660300000000, - "end_time_unix_nano": 1544712660600000000, - "kind": 2, - "attributes": [ - { - "key": "attr1", - "value": { "intValue": 55 } - } - ] - }, - { - "trace_id": "5B8EFFF798038103D269B633813FC60C", - "span_id": "EEE19B7EC3C1B173", - "name": "testSpan", - "start_time_unix_nano": 1544712660000000000, - "end_time_unix_nano": 1544712661000000000, - "kind": "SPAN_KIND_CLIENT", - "attributes": [ - { - "key": "attr1", - "value": { "intValue": 55 } - } - ] - } - ] - } - ] - } - ] - }`) - -var traceOtlp = func() ptrace.Traces { - td := ptrace.NewTraces() - rs := td.ResourceSpans().AppendEmpty() - rs.Resource().Attributes().PutStr(semconv.AttributeHostName, "testHost") - spans := rs.ScopeSpans().AppendEmpty().Spans() - span1 := spans.AppendEmpty() - span1.SetTraceID([16]byte{0x5B, 0x8E, 0xFF, 0xF7, 0x98, 0x3, 0x81, 0x3, 0xD2, 0x69, 0xB6, 0x33, 0x81, 0x3F, 0xC6, 0xC}) - span1.SetSpanID([8]byte{0xEE, 0xE1, 0x9B, 0x7E, 0xC3, 0xC1, 0xB1, 0x74}) - span1.SetParentSpanID([8]byte{0xEE, 0xE1, 0x9B, 0x7E, 0xC3, 0xC1, 0xB1, 0x73}) - span1.SetName("testSpan") - span1.SetStartTimestamp(1544712660300000000) - span1.SetEndTimestamp(1544712660600000000) - span1.SetKind(ptrace.SpanKindServer) - span1.Attributes().PutInt("attr1", 55) - span2 := spans.AppendEmpty() - span2.SetTraceID([16]byte{0x5B, 0x8E, 0xFF, 0xF7, 0x98, 0x3, 0x81, 0x3, 0xD2, 0x69, 0xB6, 0x33, 0x81, 0x3F, 0xC6, 0xC}) - span2.SetSpanID([8]byte{0xEE, 0xE1, 0x9B, 0x7E, 0xC3, 0xC1, 0xB1, 0x73}) - span2.SetName("testSpan") - span2.SetStartTimestamp(1544712660000000000) - span2.SetEndTimestamp(1544712661000000000) - span2.SetKind(ptrace.SpanKindClient) - span2.Attributes().PutInt("attr1", 55) - return td -}() +var otlpReceiverID = component.MustNewIDWithName("otlp", otlpReceiverName) func TestJsonHttp(t *testing.T) { tests := []struct { @@ -169,78 +92,49 @@ func TestJsonHttp(t *testing.T) { name: "GRPCError", encoding: "", contentType: "application/json", - err: status.New(codes.Internal, "").Err(), + err: status.New(codes.Unavailable, "").Err(), }, } addr := testutil.GetAvailableLocalAddress(t) - tracesURLPath := "/v1/traceingest" - metricsURLPath := "/v1/metricingest" - logsURLPath := "/v1/logingest" + sink := newErrOrSinkConsumer() + recv := newHTTPReceiver(t, componenttest.NewNopTelemetrySettings(), addr, sink) + require.NoError(t, recv.Start(context.Background(), componenttest.NewNopHost()), "Failed to start trace receiver") + t.Cleanup(func() { require.NoError(t, recv.Shutdown(context.Background())) }) - // Set the buffer count to 1 to make it flush the test span immediately. - sink := &errOrSinkConsumer{TracesSink: new(consumertest.TracesSink)} - ocr := newHTTPReceiver(t, addr, tracesURLPath, metricsURLPath, logsURLPath, sink, nil) - - require.NoError(t, ocr.Start(context.Background(), componenttest.NewNopHost()), "Failed to start trace receiver") - t.Cleanup(func() { require.NoError(t, ocr.Shutdown(context.Background())) }) - - // TODO(nilebox): make starting server deterministic - // Wait for the servers to start - <-time.After(10 * time.Millisecond) - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - url := fmt.Sprintf("http://%s%s", addr, tracesURLPath) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { sink.Reset() - testHTTPJSONRequest(t, url, sink, test.encoding, test.contentType, test.err) + sink.SetConsumeError(tt.err) + + for _, dr := range generateDataRequests(t) { + url := "http://" + addr + dr.path + respBytes := doHTTPRequest(t, url, tt.encoding, tt.contentType, dr.jsonBytes, tt.err != nil) + if tt.err == nil { + tr := ptraceotlp.NewExportResponse() + assert.NoError(t, tr.UnmarshalJSON(respBytes), "Unable to unmarshal response to Response") + sink.checkData(t, dr.data, 1) + } else { + errStatus := &spb.Status{} + assert.NoError(t, json.Unmarshal(respBytes, errStatus)) + if s, ok := status.FromError(tt.err); ok { + assert.True(t, proto.Equal(errStatus, s.Proto())) + } else { + fmt.Println(errStatus) + assert.True(t, proto.Equal(errStatus, &spb.Status{Code: int32(codes.Unavailable), Message: "my error"})) + } + sink.checkData(t, dr.data, 0) + } + } }) } } func TestHandleInvalidRequests(t *testing.T) { - endpoint := testutil.GetAvailableLocalAddress(t) - cfg := &Config{ - Protocols: Protocols{ - HTTP: &HTTPConfig{ - HTTPServerSettings: &confighttp.HTTPServerSettings{ - Endpoint: endpoint, - }, - TracesURLPath: defaultTracesURLPath, - MetricsURLPath: defaultMetricsURLPath, - LogsURLPath: defaultLogsURLPath, - }, - }, - } - - // Traces - tr, err := NewFactory().CreateTracesReceiver( - context.Background(), - receivertest.NewNopCreateSettings(), - cfg, - consumertest.NewNop()) - require.NoError(t, err) - assert.NotNil(t, tr) - require.NoError(t, tr.Start(context.Background(), componenttest.NewNopHost())) - - // Metrics - mr, err := NewFactory().CreateMetricsReceiver( - context.Background(), - receivertest.NewNopCreateSettings(), - cfg, - consumertest.NewNop()) - require.NoError(t, err) - assert.NotNil(t, tr) - require.NoError(t, mr.Start(context.Background(), componenttest.NewNopHost())) - - // Logs - lr, err := NewFactory().CreateLogsReceiver( - context.Background(), - receivertest.NewNopCreateSettings(), - cfg, - consumertest.NewNop()) - require.NoError(t, err) - assert.NotNil(t, tr) - require.NoError(t, lr.Start(context.Background(), componenttest.NewNopHost())) + addr := testutil.GetAvailableLocalAddress(t) + sink := newErrOrSinkConsumer() + recv := newHTTPReceiver(t, componenttest.NewNopTelemetrySettings(), addr, sink) + require.NoError(t, recv.Start(context.Background(), componenttest.NewNopHost()), "Failed to start trace receiver") + t.Cleanup(func() { require.NoError(t, recv.Shutdown(context.Background())) }) tests := []struct { name string @@ -252,8 +146,8 @@ func TestHandleInvalidRequests(t *testing.T) { expectedResponseBody string }{ { - name: "POST /v1/traces, no content type", - uri: "/v1/traces", + name: "no content type", + uri: defaultTracesURLPath, method: http.MethodPost, contentType: "", @@ -261,8 +155,8 @@ func TestHandleInvalidRequests(t *testing.T) { expectedResponseBody: "415 unsupported media type, supported: [application/json, application/x-protobuf]", }, { - name: "POST /v1/traces, invalid content type", - uri: "/v1/traces", + name: "invalid content type", + uri: defaultTracesURLPath, method: http.MethodPost, contentType: "invalid", @@ -270,8 +164,15 @@ func TestHandleInvalidRequests(t *testing.T) { expectedResponseBody: "415 unsupported media type, supported: [application/json, application/x-protobuf]", }, { - name: "PATCH /v1/traces", - uri: "/v1/traces", + name: "invalid request", + uri: defaultTracesURLPath, + method: http.MethodPost, + contentType: "application/json", + + expectedStatus: http.StatusBadRequest, + }, + { + uri: defaultTracesURLPath, method: http.MethodPatch, contentType: "application/json", @@ -279,8 +180,7 @@ func TestHandleInvalidRequests(t *testing.T) { expectedResponseBody: "405 method not allowed, supported: [POST]", }, { - name: "GET /v1/traces", - uri: "/v1/traces", + uri: defaultTracesURLPath, method: http.MethodGet, contentType: "application/json", @@ -288,8 +188,8 @@ func TestHandleInvalidRequests(t *testing.T) { expectedResponseBody: "405 method not allowed, supported: [POST]", }, { - name: "POST /v1/metrics, no content type", - uri: "/v1/metrics", + name: "no content type", + uri: defaultMetricsURLPath, method: http.MethodPost, contentType: "", @@ -297,8 +197,8 @@ func TestHandleInvalidRequests(t *testing.T) { expectedResponseBody: "415 unsupported media type, supported: [application/json, application/x-protobuf]", }, { - name: "POST /v1/metrics, no content type", - uri: "/v1/metrics", + name: "invalid content type", + uri: defaultMetricsURLPath, method: http.MethodPost, contentType: "invalid", @@ -306,8 +206,15 @@ func TestHandleInvalidRequests(t *testing.T) { expectedResponseBody: "415 unsupported media type, supported: [application/json, application/x-protobuf]", }, { - name: "PATCH /v1/metrics", - uri: "/v1/metrics", + name: "invalid request", + uri: defaultMetricsURLPath, + method: http.MethodPost, + contentType: "application/json", + + expectedStatus: http.StatusBadRequest, + }, + { + uri: defaultMetricsURLPath, method: http.MethodPatch, contentType: "application/json", @@ -315,8 +222,7 @@ func TestHandleInvalidRequests(t *testing.T) { expectedResponseBody: "405 method not allowed, supported: [POST]", }, { - name: "GET /v1/metrics", - uri: "/v1/metrics", + uri: defaultMetricsURLPath, method: http.MethodGet, contentType: "application/json", @@ -324,8 +230,8 @@ func TestHandleInvalidRequests(t *testing.T) { expectedResponseBody: "405 method not allowed, supported: [POST]", }, { - name: "POST /v1/logs, no content type", - uri: "/v1/logs", + name: "no content type", + uri: defaultLogsURLPath, method: http.MethodPost, contentType: "", @@ -333,8 +239,8 @@ func TestHandleInvalidRequests(t *testing.T) { expectedResponseBody: "415 unsupported media type, supported: [application/json, application/x-protobuf]", }, { - name: "POST /v1/logs, no content type", - uri: "/v1/logs", + name: "invalid content type", + uri: defaultLogsURLPath, method: http.MethodPost, contentType: "invalid", @@ -342,8 +248,15 @@ func TestHandleInvalidRequests(t *testing.T) { expectedResponseBody: "415 unsupported media type, supported: [application/json, application/x-protobuf]", }, { - name: "PATCH /v1/logs", - uri: "/v1/logs", + name: "invalid request", + uri: defaultLogsURLPath, + method: http.MethodPost, + contentType: "application/json", + + expectedStatus: http.StatusBadRequest, + }, + { + uri: defaultLogsURLPath, method: http.MethodPatch, contentType: "application/json", @@ -351,8 +264,7 @@ func TestHandleInvalidRequests(t *testing.T) { expectedResponseBody: "405 method not allowed, supported: [POST]", }, { - name: "GET /v1/logs", - uri: "/v1/logs", + uri: defaultLogsURLPath, method: http.MethodGet, contentType: "application/json", @@ -361,79 +273,31 @@ func TestHandleInvalidRequests(t *testing.T) { }, } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - url := fmt.Sprintf("http://%s%s", endpoint, test.uri) - req, err2 := http.NewRequest(test.method, url, bytes.NewReader([]byte(`{}`))) - require.NoError(t, err2) - req.Header.Set("Content-Type", test.contentType) + for _, tt := range tests { + t.Run(tt.method+" "+tt.uri+" "+tt.name, func(t *testing.T) { + url := "http://" + addr + tt.uri + req, err := http.NewRequest(tt.method, url, bytes.NewReader([]byte(`1234`))) + require.NoError(t, err) + req.Header.Set("Content-Type", tt.contentType) - client := &http.Client{} - resp, err2 := client.Do(req) - require.NoError(t, err2) + resp, err := http.DefaultClient.Do(req) + require.NoError(t, err) - body, err2 := io.ReadAll(resp.Body) - require.NoError(t, err2) + body, err := io.ReadAll(resp.Body) + require.NoError(t, err) - require.Equal(t, resp.Header.Get("Content-Type"), "text/plain") - require.Equal(t, resp.StatusCode, test.expectedStatus) - require.EqualValues(t, body, test.expectedResponseBody) + if tt.name == "invalid request" { + assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) + assert.Equal(t, tt.expectedStatus, resp.StatusCode) + return + } + assert.Equal(t, "text/plain", resp.Header.Get("Content-Type")) + assert.Equal(t, tt.expectedStatus, resp.StatusCode) + assert.Equal(t, tt.expectedResponseBody, string(body)) }) } - err = tr.Shutdown(context.Background()) - require.NoError(t, err) -} - -func testHTTPJSONRequest(t *testing.T, url string, sink *errOrSinkConsumer, encoding string, contentType string, expectedErr error) { - var buf *bytes.Buffer - var err error - switch encoding { - case "gzip": - buf, err = compressGzip(traceJSON) - require.NoError(t, err, "Error while gzip compressing trace: %v", err) - case "zstd": - buf, err = compressZstd(traceJSON) - require.NoError(t, err, "Error while zstd compressing trace: %v", err) - case "": - buf = bytes.NewBuffer(traceJSON) - default: - t.Fatalf("Unsupported compression type %v", encoding) - } - sink.SetConsumeError(expectedErr) - req, err := http.NewRequest(http.MethodPost, url, buf) - require.NoError(t, err, "Error creating trace POST request: %v", err) - req.Header.Set("Content-Type", contentType) - req.Header.Set("Content-Encoding", encoding) - - client := &http.Client{} - resp, err := client.Do(req) - require.NoError(t, err, "Error posting trace to http server: %v", err) - - respBytes, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.NoError(t, resp.Body.Close()) - - allTraces := sink.AllTraces() - if expectedErr == nil { - assert.Equal(t, 200, resp.StatusCode) - tr := ptraceotlp.NewExportResponse() - assert.NoError(t, tr.UnmarshalJSON(respBytes), "Unable to unmarshal response to Response") - - require.Len(t, allTraces, 1) - assert.EqualValues(t, allTraces[0], traceOtlp) - } else { - errStatus := &spb.Status{} - assert.NoError(t, json.Unmarshal(respBytes, errStatus)) - if s, ok := status.FromError(expectedErr); ok { - assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) - assert.True(t, proto.Equal(errStatus, s.Proto())) - } else { - assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) - assert.True(t, proto.Equal(errStatus, &spb.Status{Code: int32(codes.Unknown), Message: "my error"})) - } - require.Len(t, allTraces, 0) - } + require.NoError(t, recv.Shutdown(context.Background())) } func TestProtoHttp(t *testing.T) { @@ -462,110 +326,45 @@ func TestProtoHttp(t *testing.T) { { name: "GRPCError", encoding: "", - err: status.New(codes.Internal, "").Err(), + err: status.New(codes.Unavailable, "").Err(), }, } addr := testutil.GetAvailableLocalAddress(t) // Set the buffer count to 1 to make it flush the test span immediately. - tSink := &errOrSinkConsumer{TracesSink: new(consumertest.TracesSink)} - ocr := newHTTPReceiver(t, addr, defaultTracesURLPath, defaultMetricsURLPath, defaultLogsURLPath, tSink, consumertest.NewNop()) - - require.NoError(t, ocr.Start(context.Background(), componenttest.NewNopHost()), "Failed to start trace receiver") - t.Cleanup(func() { require.NoError(t, ocr.Shutdown(context.Background())) }) + sink := newErrOrSinkConsumer() + recv := newHTTPReceiver(t, componenttest.NewNopTelemetrySettings(), addr, sink) - // TODO(nilebox): make starting server deterministic - // Wait for the servers to start - <-time.After(10 * time.Millisecond) - - td := testdata.GenerateTraces(1) - marshaler := &ptrace.ProtoMarshaler{} - traceBytes, err := marshaler.MarshalTraces(td) - require.NoError(t, err) + require.NoError(t, recv.Start(context.Background(), componenttest.NewNopHost()), "Failed to start trace receiver") + t.Cleanup(func() { require.NoError(t, recv.Shutdown(context.Background())) }) - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - url := fmt.Sprintf("http://%s%s", addr, defaultTracesURLPath) - tSink.Reset() - testHTTPProtobufRequest(t, url, tSink, test.encoding, traceBytes, test.err, td) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + sink.Reset() + sink.SetConsumeError(tt.err) + + for _, dr := range generateDataRequests(t) { + url := "http://" + addr + dr.path + respBytes := doHTTPRequest(t, url, tt.encoding, "application/x-protobuf", dr.protoBytes, tt.err != nil) + if tt.err == nil { + tr := ptraceotlp.NewExportResponse() + assert.NoError(t, tr.UnmarshalProto(respBytes)) + sink.checkData(t, dr.data, 1) + } else { + errStatus := &spb.Status{} + assert.NoError(t, proto.Unmarshal(respBytes, errStatus)) + if s, ok := status.FromError(tt.err); ok { + assert.True(t, proto.Equal(errStatus, s.Proto())) + } else { + assert.True(t, proto.Equal(errStatus, &spb.Status{Code: int32(codes.Unavailable), Message: "my error"})) + } + sink.checkData(t, dr.data, 0) + } + } }) } } -func createHTTPProtobufRequest( - t *testing.T, - url string, - encoding string, - traceBytes []byte, -) *http.Request { - var buf *bytes.Buffer - var err error - switch encoding { - case "gzip": - buf, err = compressGzip(traceBytes) - require.NoError(t, err, "Error while gzip compressing trace: %v", err) - case "zstd": - buf, err = compressZstd(traceBytes) - require.NoError(t, err, "Error while zstd compressing trace: %v", err) - case "": - buf = bytes.NewBuffer(traceBytes) - default: - t.Fatalf("Unsupported compression type %v", encoding) - } - req, err := http.NewRequest(http.MethodPost, url, buf) - require.NoError(t, err, "Error creating trace POST request: %v", err) - req.Header.Set("Content-Type", "application/x-protobuf") - req.Header.Set("Content-Encoding", encoding) - return req -} - -func testHTTPProtobufRequest( - t *testing.T, - url string, - tSink *errOrSinkConsumer, - encoding string, - traceBytes []byte, - expectedErr error, - wantData ptrace.Traces, -) { - tSink.SetConsumeError(expectedErr) - - req := createHTTPProtobufRequest(t, url, encoding, traceBytes) - - client := &http.Client{} - resp, err := client.Do(req) - require.NoError(t, err, "Error posting trace to grpc-gateway server: %v", err) - - respBytes, err := io.ReadAll(resp.Body) - require.NoError(t, err, "Error reading response from trace grpc-gateway") - require.NoError(t, resp.Body.Close(), "Error closing response body") - - assert.Equal(t, "application/x-protobuf", resp.Header.Get("Content-Type"), "Unexpected response Content-Type") - - allTraces := tSink.AllTraces() - - if expectedErr == nil { - require.Equal(t, 200, resp.StatusCode, "Unexpected return status") - - tr := ptraceotlp.NewExportResponse() - assert.NoError(t, tr.UnmarshalProto(respBytes), "Unable to unmarshal response to Response") - - require.Len(t, allTraces, 1) - assert.EqualValues(t, allTraces[0], wantData) - } else { - errStatus := &spb.Status{} - assert.NoError(t, proto.Unmarshal(respBytes, errStatus)) - if s, ok := status.FromError(expectedErr); ok { - assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) - assert.True(t, proto.Equal(errStatus, s.Proto())) - } else { - assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) - assert.True(t, proto.Equal(errStatus, &spb.Status{Code: int32(codes.Unknown), Message: "my error"})) - } - require.Len(t, allTraces, 0) - } -} - func TestOTLPReceiverInvalidContentEncoding(t *testing.T) { tests := []struct { name string @@ -615,18 +414,13 @@ func TestOTLPReceiverInvalidContentEncoding(t *testing.T) { addr := testutil.GetAvailableLocalAddress(t) // Set the buffer count to 1 to make it flush the test span immediately. - tSink := new(consumertest.TracesSink) - mSink := new(consumertest.MetricsSink) - ocr := newHTTPReceiver(t, addr, defaultTracesURLPath, defaultMetricsURLPath, defaultLogsURLPath, tSink, mSink) + recv := newHTTPReceiver(t, componenttest.NewNopTelemetrySettings(), addr, consumertest.NewNop()) - require.NoError(t, ocr.Start(context.Background(), componenttest.NewNopHost()), "Failed to start trace receiver") - t.Cleanup(func() { require.NoError(t, ocr.Shutdown(context.Background())) }) + require.NoError(t, recv.Start(context.Background(), componenttest.NewNopHost()), "Failed to start trace receiver") + t.Cleanup(func() { require.NoError(t, recv.Shutdown(context.Background())) }) url := fmt.Sprintf("http://%s%s", addr, defaultTracesURLPath) - // Wait for the servers to start - <-time.After(10 * time.Millisecond) - for _, test := range tests { t.Run(test.name, func(t *testing.T) { body, err := test.reqBodyFunc() @@ -637,8 +431,7 @@ func TestOTLPReceiverInvalidContentEncoding(t *testing.T) { req.Header.Set("Content-Type", test.content) req.Header.Set("Content-Encoding", test.encoding) - client := &http.Client{} - resp, err := client.Do(req) + resp, err := http.DefaultClient.Do(req) require.NoError(t, err, "Error posting trace to grpc-gateway server: %v", err) respBytes, err := io.ReadAll(resp.Body) @@ -662,7 +455,7 @@ func TestGRPCNewPortAlreadyUsed(t *testing.T) { assert.NoError(t, ln.Close()) }) - r := newGRPCReceiver(t, addr, consumertest.NewNop(), consumertest.NewNop()) + r := newGRPCReceiver(t, componenttest.NewNopTelemetrySettings(), addr, consumertest.NewNop()) require.NotNil(t, r) require.Error(t, r.Start(context.Background(), componenttest.NewNopHost())) @@ -676,7 +469,7 @@ func TestHTTPNewPortAlreadyUsed(t *testing.T) { assert.NoError(t, ln.Close()) }) - r := newHTTPReceiver(t, addr, defaultTracesURLPath, defaultMetricsURLPath, defaultLogsURLPath, consumertest.NewNop(), consumertest.NewNop()) + r := newHTTPReceiver(t, componenttest.NewNopTelemetrySettings(), addr, consumertest.NewNop()) require.NotNil(t, r) require.Error(t, r.Start(context.Background(), componenttest.NewNopHost())) @@ -691,11 +484,12 @@ func TestHTTPNewPortAlreadyUsed(t *testing.T) { func TestOTLPReceiverGRPCTracesIngestTest(t *testing.T) { type ingestionStateTest struct { okToIngest bool + permanent bool expectedCode codes.Code } expectedReceivedBatches := 2 - expectedIngestionBlockedRPCs := 1 + expectedIngestionBlockedRPCs := 2 ingestionStates := []ingestionStateTest{ { okToIngest: true, @@ -703,7 +497,12 @@ func TestOTLPReceiverGRPCTracesIngestTest(t *testing.T) { }, { okToIngest: false, - expectedCode: codes.Unknown, + expectedCode: codes.Unavailable, + }, + { + okToIngest: false, + expectedCode: codes.Internal, + permanent: true, }, { okToIngest: true, @@ -714,16 +513,16 @@ func TestOTLPReceiverGRPCTracesIngestTest(t *testing.T) { addr := testutil.GetAvailableLocalAddress(t) td := testdata.GenerateTraces(1) - tt, err := obsreporttest.SetupTelemetry(otlpReceiverID) + tt, err := componenttest.SetupTelemetry(otlpReceiverID) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) sink := &errOrSinkConsumer{TracesSink: new(consumertest.TracesSink)} - ocr := newGRPCReceiver(t, addr, sink, nil) - require.NotNil(t, ocr) - require.NoError(t, ocr.Start(context.Background(), componenttest.NewNopHost())) - t.Cleanup(func() { require.NoError(t, ocr.Shutdown(context.Background())) }) + recv := newGRPCReceiver(t, tt.TelemetrySettings(), addr, sink) + require.NotNil(t, recv) + require.NoError(t, recv.Start(context.Background(), componenttest.NewNopHost())) + t.Cleanup(func() { require.NoError(t, recv.Shutdown(context.Background())) }) cc, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) require.NoError(t, err) @@ -735,7 +534,11 @@ func TestOTLPReceiverGRPCTracesIngestTest(t *testing.T) { if ingestionState.okToIngest { sink.SetConsumeError(nil) } else { - sink.SetConsumeError(errors.New("consumer error")) + if ingestionState.permanent { + sink.SetConsumeError(consumererror.NewPermanent(errors.New("consumer error"))) + } else { + sink.SetConsumeError(errors.New("consumer error")) + } } _, err = ptraceotlp.NewGRPCClient(cc).Export(context.Background(), ptraceotlp.NewExportRequestFromTraces(td)) @@ -770,7 +573,7 @@ func TestOTLPReceiverHTTPTracesIngestTest(t *testing.T) { }, { okToIngest: false, - expectedCode: codes.Unknown, + expectedCode: codes.Unavailable, }, { okToIngest: true, @@ -781,16 +584,16 @@ func TestOTLPReceiverHTTPTracesIngestTest(t *testing.T) { addr := testutil.GetAvailableLocalAddress(t) td := testdata.GenerateTraces(1) - tt, err := obsreporttest.SetupTelemetry(otlpReceiverID) + tt, err := componenttest.SetupTelemetry(otlpReceiverID) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) sink := &errOrSinkConsumer{TracesSink: new(consumertest.TracesSink)} - ocr := newHTTPReceiver(t, addr, defaultTracesURLPath, defaultMetricsURLPath, defaultLogsURLPath, sink, nil) - require.NotNil(t, ocr) - require.NoError(t, ocr.Start(context.Background(), componenttest.NewNopHost())) - t.Cleanup(func() { require.NoError(t, ocr.Shutdown(context.Background())) }) + recv := newHTTPReceiver(t, tt.TelemetrySettings(), addr, sink) + require.NotNil(t, recv) + require.NoError(t, recv.Start(context.Background(), componenttest.NewNopHost())) + t.Cleanup(func() { require.NoError(t, recv.Shutdown(context.Background())) }) for _, ingestionState := range ingestionStates { if ingestionState.okToIngest { @@ -830,13 +633,13 @@ func TestOTLPReceiverHTTPTracesIngestTest(t *testing.T) { func TestGRPCInvalidTLSCredentials(t *testing.T) { cfg := &Config{ Protocols: Protocols{ - GRPC: &configgrpc.GRPCServerSettings{ - NetAddr: confignet.NetAddr{ + GRPC: &configgrpc.ServerConfig{ + NetAddr: confignet.AddrConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), Transport: "tcp", }, - TLSSetting: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CertFile: "willfail", }, }, @@ -859,16 +662,13 @@ func TestGRPCInvalidTLSCredentials(t *testing.T) { func TestGRPCMaxRecvSize(t *testing.T) { addr := testutil.GetAvailableLocalAddress(t) - sink := new(consumertest.TracesSink) + sink := newErrOrSinkConsumer() - factory := NewFactory() - cfg := factory.CreateDefaultConfig().(*Config) + cfg := createDefaultConfig().(*Config) cfg.GRPC.NetAddr.Endpoint = addr cfg.HTTP = nil - ocr := newReceiver(t, factory, cfg, otlpReceiverID, sink, nil) - - require.NotNil(t, ocr) - require.NoError(t, ocr.Start(context.Background(), componenttest.NewNopHost())) + recv := newReceiver(t, componenttest.NewNopTelemetrySettings(), cfg, otlpReceiverID, sink) + require.NoError(t, recv.Start(context.Background(), componenttest.NewNopHost())) cc, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) require.NoError(t, err) @@ -876,14 +676,12 @@ func TestGRPCMaxRecvSize(t *testing.T) { td := testdata.GenerateTraces(50000) require.Error(t, exportTraces(cc, td)) assert.NoError(t, cc.Close()) - require.NoError(t, ocr.Shutdown(context.Background())) + require.NoError(t, recv.Shutdown(context.Background())) cfg.GRPC.MaxRecvMsgSizeMiB = 100 - ocr = newReceiver(t, factory, cfg, otlpReceiverID, sink, nil) - - require.NotNil(t, ocr) - require.NoError(t, ocr.Start(context.Background(), componenttest.NewNopHost())) - t.Cleanup(func() { require.NoError(t, ocr.Shutdown(context.Background())) }) + recv = newReceiver(t, componenttest.NewNopTelemetrySettings(), cfg, otlpReceiverID, sink) + require.NoError(t, recv.Start(context.Background(), componenttest.NewNopHost())) + t.Cleanup(func() { require.NoError(t, recv.Shutdown(context.Background())) }) cc, err = grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) require.NoError(t, err) @@ -901,10 +699,10 @@ func TestHTTPInvalidTLSCredentials(t *testing.T) { cfg := &Config{ Protocols: Protocols{ HTTP: &HTTPConfig{ - HTTPServerSettings: &confighttp.HTTPServerSettings{ + ServerConfig: &confighttp.ServerConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), - TLSSetting: &configtls.TLSServerSetting{ - TLSSetting: configtls.TLSSetting{ + TLSSetting: &configtls.ServerConfig{ + TLSSetting: configtls.Config{ CertFile: "willfail", }, }, @@ -928,14 +726,14 @@ func TestHTTPInvalidTLSCredentials(t *testing.T) { `failed to load TLS config: failed to load TLS cert and key: for auth via TLS, provide both certificate and key, or neither`) } -func testHTTPMaxRequestBodySizeJSON(t *testing.T, payload []byte, size int, expectedStatusCode int) { - endpoint := testutil.GetAvailableLocalAddress(t) - url := fmt.Sprintf("http://%s/v1/traces", endpoint) +func testHTTPMaxRequestBodySize(t *testing.T, path string, contentType string, payload []byte, size int, expectedStatusCode int) { + addr := testutil.GetAvailableLocalAddress(t) + url := "http://" + addr + path cfg := &Config{ Protocols: Protocols{ HTTP: &HTTPConfig{ - HTTPServerSettings: &confighttp.HTTPServerSettings{ - Endpoint: endpoint, + ServerConfig: &confighttp.ServerConfig{ + Endpoint: addr, MaxRequestBodySize: int64(size), }, TracesURLPath: defaultTracesURLPath, @@ -945,103 +743,193 @@ func testHTTPMaxRequestBodySizeJSON(t *testing.T, payload []byte, size int, expe }, } - r, err := NewFactory().CreateTracesReceiver( - context.Background(), - receivertest.NewNopCreateSettings(), - cfg, - consumertest.NewNop()) - require.NoError(t, err) - assert.NotNil(t, r) - require.NoError(t, r.Start(context.Background(), componenttest.NewNopHost())) + recv := newReceiver(t, componenttest.NewNopTelemetrySettings(), cfg, otlpReceiverID, consumertest.NewNop()) + require.NoError(t, recv.Start(context.Background(), componenttest.NewNopHost())) - req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(payload)) - require.NoError(t, err) - req.Header.Set("Content-Type", "application/json") - client := &http.Client{} - resp, err := client.Do(req) + req := createHTTPRequest(t, url, "", contentType, payload) + resp, err := http.DefaultClient.Do(req) require.NoError(t, err) _, err = io.ReadAll(resp.Body) require.NoError(t, err) require.Equal(t, expectedStatusCode, resp.StatusCode) - err = r.Shutdown(context.Background()) - require.NoError(t, err) + require.NoError(t, recv.Shutdown(context.Background())) } -func TestHTTPMaxRequestBodySize_OK(t *testing.T) { - testHTTPMaxRequestBodySizeJSON(t, traceJSON, len(traceJSON), 200) -} +func TestHTTPMaxRequestBodySize(t *testing.T) { + dataReqs := generateDataRequests(t) + + for _, dr := range dataReqs { + testHTTPMaxRequestBodySize(t, dr.path, "application/json", dr.jsonBytes, len(dr.jsonBytes), 200) + testHTTPMaxRequestBodySize(t, dr.path, "application/json", dr.jsonBytes, len(dr.jsonBytes)-1, 400) -func TestHTTPMaxRequestBodySize_TooLarge(t *testing.T) { - testHTTPMaxRequestBodySizeJSON(t, traceJSON, len(traceJSON)-1, 400) + testHTTPMaxRequestBodySize(t, dr.path, "application/x-protobuf", dr.protoBytes, len(dr.protoBytes), 200) + testHTTPMaxRequestBodySize(t, dr.path, "application/x-protobuf", dr.protoBytes, len(dr.protoBytes)-1, 400) + } } -func newGRPCReceiver(t *testing.T, endpoint string, tc consumer.Traces, mc consumer.Metrics) component.Component { - factory := NewFactory() - cfg := factory.CreateDefaultConfig().(*Config) +func newGRPCReceiver(t *testing.T, settings component.TelemetrySettings, endpoint string, c consumertest.Consumer) component.Component { + cfg := createDefaultConfig().(*Config) cfg.GRPC.NetAddr.Endpoint = endpoint cfg.HTTP = nil - return newReceiver(t, factory, cfg, otlpReceiverID, tc, mc) + return newReceiver(t, settings, cfg, otlpReceiverID, c) } -func newHTTPReceiver(t *testing.T, endpoint string, tracesURLPath string, metricsURLPath string, logsURLPath string, tc consumer.Traces, mc consumer.Metrics) component.Component { - factory := NewFactory() - cfg := factory.CreateDefaultConfig().(*Config) +func newHTTPReceiver(t *testing.T, settings component.TelemetrySettings, endpoint string, c consumertest.Consumer) component.Component { + cfg := createDefaultConfig().(*Config) cfg.HTTP.Endpoint = endpoint - cfg.HTTP.TracesURLPath = tracesURLPath - cfg.HTTP.MetricsURLPath = metricsURLPath - cfg.HTTP.LogsURLPath = logsURLPath cfg.GRPC = nil - return newReceiver(t, factory, cfg, otlpReceiverID, tc, mc) + return newReceiver(t, settings, cfg, otlpReceiverID, c) } -func newReceiver(t *testing.T, factory receiver.Factory, cfg *Config, id component.ID, tc consumer.Traces, mc consumer.Metrics) component.Component { +func newReceiver(t *testing.T, settings component.TelemetrySettings, cfg *Config, id component.ID, c consumertest.Consumer) component.Component { set := receivertest.NewNopCreateSettings() - set.TelemetrySettings.MetricsLevel = configtelemetry.LevelNormal + set.TelemetrySettings = settings set.ID = id - var r component.Component - var err error - if tc != nil { - r, err = factory.CreateTracesReceiver(context.Background(), set, cfg, tc) - require.NoError(t, err) + r, err := newOtlpReceiver(cfg, &set) + require.NoError(t, err) + r.registerTraceConsumer(c) + r.registerMetricsConsumer(c) + r.registerLogsConsumer(c) + return r +} + +type dataRequest struct { + data any + path string + jsonBytes []byte + protoBytes []byte +} + +func generateDataRequests(t *testing.T) []dataRequest { + return []dataRequest{generateTracesRequest(t), generateMetricsRequests(t), generateLogsRequest(t)} +} + +func generateTracesRequest(t *testing.T) dataRequest { + protoMarshaler := &ptrace.ProtoMarshaler{} + jsonMarshaler := &ptrace.JSONMarshaler{} + + td := testdata.GenerateTraces(2) + traceProto, err := protoMarshaler.MarshalTraces(td) + require.NoError(t, err) + + traceJSON, err := jsonMarshaler.MarshalTraces(td) + require.NoError(t, err) + + return dataRequest{data: td, path: defaultTracesURLPath, jsonBytes: traceJSON, protoBytes: traceProto} +} + +func generateMetricsRequests(t *testing.T) dataRequest { + protoMarshaler := &pmetric.ProtoMarshaler{} + jsonMarshaler := &pmetric.JSONMarshaler{} + + md := testdata.GenerateMetrics(2) + metricProto, err := protoMarshaler.MarshalMetrics(md) + require.NoError(t, err) + + metricJSON, err := jsonMarshaler.MarshalMetrics(md) + require.NoError(t, err) + + return dataRequest{data: md, path: defaultMetricsURLPath, jsonBytes: metricJSON, protoBytes: metricProto} +} + +func generateLogsRequest(t *testing.T) dataRequest { + protoMarshaler := &plog.ProtoMarshaler{} + jsonMarshaler := &plog.JSONMarshaler{} + + ld := testdata.GenerateLogs(2) + logProto, err := protoMarshaler.MarshalLogs(ld) + require.NoError(t, err) + + logJSON, err := jsonMarshaler.MarshalLogs(ld) + require.NoError(t, err) + + return dataRequest{data: ld, path: defaultLogsURLPath, jsonBytes: logJSON, protoBytes: logProto} +} + +func doHTTPRequest( + t *testing.T, + url string, + encoding string, + contentType string, + data []byte, + expectErr bool, +) []byte { + req := createHTTPRequest(t, url, encoding, contentType, data) + resp, err := http.DefaultClient.Do(req) + require.NoError(t, err) + + respBytes, err := io.ReadAll(resp.Body) + require.NoError(t, err) + + require.NoError(t, resp.Body.Close()) + // For cases like "application/json; charset=utf-8", the response will be only "application/json" + require.True(t, strings.HasPrefix(strings.ToLower(contentType), resp.Header.Get("Content-Type"))) + + if !expectErr { + require.Equal(t, http.StatusOK, resp.StatusCode) + } else { + require.Equal(t, http.StatusInternalServerError, resp.StatusCode) } - if mc != nil { - r, err = factory.CreateMetricsReceiver(context.Background(), set, cfg, mc) - require.NoError(t, err) + + return respBytes +} + +func createHTTPRequest( + t *testing.T, + url string, + encoding string, + contentType string, + data []byte, +) *http.Request { + var buf *bytes.Buffer + switch encoding { + case "gzip": + buf = compressGzip(t, data) + case "zstd": + buf = compressZstd(t, data) + case "": + buf = bytes.NewBuffer(data) + default: + t.Fatalf("Unsupported compression type %v", encoding) } - return r + + req, err := http.NewRequest(http.MethodPost, url, buf) + require.NoError(t, err) + req.Header.Set("Content-Type", contentType) + req.Header.Set("Content-Encoding", encoding) + + return req } -func compressGzip(body []byte) (*bytes.Buffer, error) { +func compressGzip(t *testing.T, body []byte) *bytes.Buffer { var buf bytes.Buffer gw := gzip.NewWriter(&buf) - defer gw.Close() + defer func() { + require.NoError(t, gw.Close()) + }() _, err := gw.Write(body) - if err != nil { - return nil, err - } + require.NoError(t, err) - return &buf, nil + return &buf } -func compressZstd(body []byte) (*bytes.Buffer, error) { +func compressZstd(t *testing.T, body []byte) *bytes.Buffer { var buf bytes.Buffer zw, err := zstd.NewWriter(&buf) - if err != nil { - return nil, err - } + require.NoError(t, err) - defer zw.Close() + defer func() { + require.NoError(t, zw.Close()) + }() _, err = zw.Write(body) - if err != nil { - return nil, err - } + require.NoError(t, err) - return &buf, nil + return &buf } type senderFunc func(td ptrace.Traces) @@ -1070,7 +958,9 @@ func TestShutdown(t *testing.T) { conn, err := grpc.Dial(endpointGrpc, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) require.NoError(t, err) - defer conn.Close() + t.Cleanup(func() { + require.NoError(t, conn.Close()) + }) doneSignalGrpc := make(chan bool) doneSignalHTTP := make(chan bool) @@ -1084,12 +974,10 @@ func TestShutdown(t *testing.T) { marshaler := &ptrace.ProtoMarshaler{} traceBytes, err2 := marshaler.MarshalTraces(td) require.NoError(t, err2) - url := fmt.Sprintf("http://%s/v1/traces", endpointHTTP) - req := createHTTPProtobufRequest(t, url, "", traceBytes) - client := &http.Client{} - resp, err2 := client.Do(req) - if err2 == nil { - resp.Body.Close() + url := "http://" + endpointHTTP + defaultTracesURLPath + req := createHTTPRequest(t, url, "", "application/x-protobuf", traceBytes) + if resp, errResp := http.DefaultClient.Do(req); errResp == nil { + require.NoError(t, resp.Body.Close()) } } @@ -1106,8 +994,7 @@ func TestShutdown(t *testing.T) { // Now shutdown the receiver, while continuing sending traces to it. ctx, cancelFn := context.WithTimeout(context.Background(), 10*time.Second) defer cancelFn() - err = r.Shutdown(ctx) - assert.NoError(t, err) + assert.NoError(t, r.Shutdown(ctx)) // Remember how many spans the sink received. This number should not change after this // point because after Shutdown() returns the component is not allowed to produce @@ -1125,7 +1012,7 @@ func TestShutdown(t *testing.T) { // The last, additional trace should not be received by sink, so the number of spans in // the sink should not change. - assert.EqualValues(t, sinkSpanCountAfterShutdown, nextSink.SpanCount()) + assert.Equal(t, sinkSpanCountAfterShutdown, nextSink.SpanCount()) } func generateTraces(senderFn senderFunc, doneSignal chan bool) { @@ -1157,12 +1044,22 @@ func exportTraces(cc *grpc.ClientConn, td ptrace.Traces) error { } type errOrSinkConsumer struct { + consumertest.Consumer *consumertest.TracesSink *consumertest.MetricsSink + *consumertest.LogsSink mu sync.Mutex consumeError error // to be returned by ConsumeTraces, if set } +func newErrOrSinkConsumer() *errOrSinkConsumer { + return &errOrSinkConsumer{ + TracesSink: new(consumertest.TracesSink), + MetricsSink: new(consumertest.MetricsSink), + LogsSink: new(consumertest.LogsSink), + } +} + // SetConsumeError sets an error that will be returned by the Consume function. func (esc *errOrSinkConsumer) SetConsumeError(err error) { esc.mu.Lock() @@ -1198,16 +1095,49 @@ func (esc *errOrSinkConsumer) ConsumeMetrics(ctx context.Context, md pmetric.Met return esc.MetricsSink.ConsumeMetrics(ctx, md) } +// ConsumeMetrics stores metrics to this sink. +func (esc *errOrSinkConsumer) ConsumeLogs(ctx context.Context, ld plog.Logs) error { + esc.mu.Lock() + defer esc.mu.Unlock() + + if esc.consumeError != nil { + return esc.consumeError + } + + return esc.LogsSink.ConsumeLogs(ctx, ld) +} + // Reset deletes any stored in the sinks, resets error to nil. func (esc *errOrSinkConsumer) Reset() { esc.mu.Lock() defer esc.mu.Unlock() esc.consumeError = nil - if esc.TracesSink != nil { - esc.TracesSink.Reset() - } - if esc.MetricsSink != nil { - esc.MetricsSink.Reset() + esc.TracesSink.Reset() + esc.MetricsSink.Reset() + esc.LogsSink.Reset() +} + +// Reset deletes any stored in the sinks, resets error to nil. +func (esc *errOrSinkConsumer) checkData(t *testing.T, data any, len int) { + switch data.(type) { + case ptrace.Traces: + allTraces := esc.TracesSink.AllTraces() + require.Len(t, allTraces, len) + if len > 0 { + require.Equal(t, allTraces[0], data) + } + case pmetric.Metrics: + allMetrics := esc.MetricsSink.AllMetrics() + require.Len(t, allMetrics, len) + if len > 0 { + require.Equal(t, allMetrics[0], data) + } + case plog.Logs: + allLogs := esc.LogsSink.AllLogs() + require.Len(t, allLogs, len) + if len > 0 { + require.Equal(t, allLogs[0], data) + } } } diff --git a/receiver/otlpreceiver/otlphttp.go b/receiver/otlpreceiver/otlphttp.go index 641335a482c..dca42737052 100644 --- a/receiver/otlpreceiver/otlphttp.go +++ b/receiver/otlpreceiver/otlphttp.go @@ -4,6 +4,7 @@ package otlpreceiver // import "go.opentelemetry.io/collector/receiver/otlpreceiver" import ( + "fmt" "io" "mime" "net/http" @@ -22,92 +23,124 @@ var fallbackMsg = []byte(`{"code": 13, "message": "failed to marshal error messa const fallbackContentType = "application/json" -func handleTraces(resp http.ResponseWriter, req *http.Request, tracesReceiver *trace.Receiver, encoder encoder) { - body, ok := readAndCloseBody(resp, req, encoder) +func handleTraces(resp http.ResponseWriter, req *http.Request, tracesReceiver *trace.Receiver) { + enc, ok := readContentType(resp, req) if !ok { return } - otlpReq, err := encoder.unmarshalTracesRequest(body) + body, ok := readAndCloseBody(resp, req, enc) + if !ok { + return + } + + otlpReq, err := enc.unmarshalTracesRequest(body) if err != nil { - writeError(resp, encoder, err, http.StatusBadRequest) + writeError(resp, enc, err, http.StatusBadRequest) return } otlpResp, err := tracesReceiver.Export(req.Context(), otlpReq) if err != nil { - writeError(resp, encoder, err, http.StatusInternalServerError) + writeError(resp, enc, err, http.StatusInternalServerError) return } - msg, err := encoder.marshalTracesResponse(otlpResp) + msg, err := enc.marshalTracesResponse(otlpResp) if err != nil { - writeError(resp, encoder, err, http.StatusInternalServerError) + writeError(resp, enc, err, http.StatusInternalServerError) return } - writeResponse(resp, encoder.contentType(), http.StatusOK, msg) + writeResponse(resp, enc.contentType(), http.StatusOK, msg) } -func handleMetrics(resp http.ResponseWriter, req *http.Request, metricsReceiver *metrics.Receiver, encoder encoder) { - body, ok := readAndCloseBody(resp, req, encoder) +func handleMetrics(resp http.ResponseWriter, req *http.Request, metricsReceiver *metrics.Receiver) { + enc, ok := readContentType(resp, req) if !ok { return } - otlpReq, err := encoder.unmarshalMetricsRequest(body) + body, ok := readAndCloseBody(resp, req, enc) + if !ok { + return + } + + otlpReq, err := enc.unmarshalMetricsRequest(body) if err != nil { - writeError(resp, encoder, err, http.StatusBadRequest) + writeError(resp, enc, err, http.StatusBadRequest) return } otlpResp, err := metricsReceiver.Export(req.Context(), otlpReq) if err != nil { - writeError(resp, encoder, err, http.StatusInternalServerError) + writeError(resp, enc, err, http.StatusInternalServerError) return } - msg, err := encoder.marshalMetricsResponse(otlpResp) + msg, err := enc.marshalMetricsResponse(otlpResp) if err != nil { - writeError(resp, encoder, err, http.StatusInternalServerError) + writeError(resp, enc, err, http.StatusInternalServerError) return } - writeResponse(resp, encoder.contentType(), http.StatusOK, msg) + writeResponse(resp, enc.contentType(), http.StatusOK, msg) } -func handleLogs(resp http.ResponseWriter, req *http.Request, logsReceiver *logs.Receiver, encoder encoder) { - body, ok := readAndCloseBody(resp, req, encoder) +func handleLogs(resp http.ResponseWriter, req *http.Request, logsReceiver *logs.Receiver) { + enc, ok := readContentType(resp, req) + if !ok { + return + } + + body, ok := readAndCloseBody(resp, req, enc) if !ok { return } - otlpReq, err := encoder.unmarshalLogsRequest(body) + otlpReq, err := enc.unmarshalLogsRequest(body) if err != nil { - writeError(resp, encoder, err, http.StatusBadRequest) + writeError(resp, enc, err, http.StatusBadRequest) return } otlpResp, err := logsReceiver.Export(req.Context(), otlpReq) if err != nil { - writeError(resp, encoder, err, http.StatusInternalServerError) + writeError(resp, enc, err, http.StatusInternalServerError) return } - msg, err := encoder.marshalLogsResponse(otlpResp) + msg, err := enc.marshalLogsResponse(otlpResp) if err != nil { - writeError(resp, encoder, err, http.StatusInternalServerError) + writeError(resp, enc, err, http.StatusInternalServerError) return } - writeResponse(resp, encoder.contentType(), http.StatusOK, msg) + writeResponse(resp, enc.contentType(), http.StatusOK, msg) } -func readAndCloseBody(resp http.ResponseWriter, req *http.Request, encoder encoder) ([]byte, bool) { +func readContentType(resp http.ResponseWriter, req *http.Request) (encoder, bool) { + if req.Method != http.MethodPost { + handleUnmatchedMethod(resp) + return nil, false + } + + switch getMimeTypeFromContentType(req.Header.Get("Content-Type")) { + case pbContentType: + return pbEncoder, true + case jsonContentType: + return jsEncoder, true + default: + handleUnmatchedContentType(resp) + return nil, false + } +} + +func readAndCloseBody(resp http.ResponseWriter, req *http.Request, enc encoder) ([]byte, bool) { body, err := io.ReadAll(req.Body) if err != nil { - writeError(resp, encoder, err, http.StatusBadRequest) + writeError(resp, enc, err, http.StatusBadRequest) return nil, false } if err = req.Body.Close(); err != nil { - writeError(resp, encoder, err, http.StatusBadRequest) + writeError(resp, enc, err, http.StatusBadRequest) return nil, false } return body, true @@ -137,14 +170,14 @@ func errorHandler(w http.ResponseWriter, r *http.Request, errMsg string, statusC writeResponse(w, fallbackContentType, http.StatusInternalServerError, fallbackMsg) } -func writeStatusResponse(w http.ResponseWriter, encoder encoder, statusCode int, rsp *spb.Status) { - msg, err := encoder.marshalStatus(rsp) +func writeStatusResponse(w http.ResponseWriter, enc encoder, statusCode int, rsp *spb.Status) { + msg, err := enc.marshalStatus(rsp) if err != nil { writeResponse(w, fallbackContentType, http.StatusInternalServerError, fallbackMsg) return } - writeResponse(w, encoder.contentType(), statusCode, msg) + writeResponse(w, enc.contentType(), statusCode, msg) } func writeResponse(w http.ResponseWriter, contentType string, statusCode int, msg []byte) { @@ -168,3 +201,13 @@ func getMimeTypeFromContentType(contentType string) string { } return mediatype } + +func handleUnmatchedMethod(resp http.ResponseWriter) { + status := http.StatusMethodNotAllowed + writeResponse(resp, "text/plain", status, []byte(fmt.Sprintf("%v method not allowed, supported: [POST]", status))) +} + +func handleUnmatchedContentType(resp http.ResponseWriter) { + status := http.StatusUnsupportedMediaType + writeResponse(resp, "text/plain", status, []byte(fmt.Sprintf("%v unsupported media type, supported: [%s, %s]", status, jsonContentType, pbContentType))) +} diff --git a/receiver/otlpreceiver/package_test.go b/receiver/otlpreceiver/package_test.go new file mode 100644 index 00000000000..9d49b5c8f7b --- /dev/null +++ b/receiver/otlpreceiver/package_test.go @@ -0,0 +1,17 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package otlpreceiver + +import ( + "testing" + + "go.uber.org/goleak" +) + +// The IgnoreTopFunction call prevents catching the leak generated by opencensus +// defaultWorker.Start which at this time is part of the package's init call. +// See https://github.com/open-telemetry/opentelemetry-collector/issues/9165#issuecomment-1874836336 for more context. +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m, goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start")) +} diff --git a/receiver/package_test.go b/receiver/package_test.go new file mode 100644 index 00000000000..09e3e768e60 --- /dev/null +++ b/receiver/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package receiver + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/receiver/receiver.go b/receiver/receiver.go index bb525a1e03c..3b0f0ac8371 100644 --- a/receiver/receiver.go +++ b/receiver/receiver.go @@ -5,6 +5,7 @@ package receiver // import "go.opentelemetry.io/collector/receiver" import ( "context" + "errors" "fmt" "go.uber.org/zap" @@ -13,6 +14,10 @@ import ( "go.opentelemetry.io/collector/consumer" ) +var ( + errNilNextConsumer = errors.New("nil next Consumer") +) + // Traces receiver receives traces. // Its purpose is to translate data from any format to the collector's internal trace format. // TracesReceiver feeds a consumer.Traces with data. @@ -60,7 +65,7 @@ type Factory interface { // CreateTracesReceiver creates a TracesReceiver based on this config. // If the receiver type does not support tracing or if the config is not valid - // an error will be returned instead. + // an error will be returned instead. `nextConsumer` is never nil. CreateTracesReceiver(ctx context.Context, set CreateSettings, cfg component.Config, nextConsumer consumer.Traces) (Traces, error) // TracesReceiverStability gets the stability level of the TracesReceiver. @@ -68,7 +73,7 @@ type Factory interface { // CreateMetricsReceiver creates a MetricsReceiver based on this config. // If the receiver type does not support metrics or if the config is not valid - // an error will be returned instead. + // an error will be returned instead. `nextConsumer` is never nil. CreateMetricsReceiver(ctx context.Context, set CreateSettings, cfg component.Config, nextConsumer consumer.Metrics) (Metrics, error) // MetricsReceiverStability gets the stability level of the MetricsReceiver. @@ -76,7 +81,7 @@ type Factory interface { // CreateLogsReceiver creates a LogsReceiver based on this config. // If the receiver type does not support the data type or if the config is not valid - // an error will be returned instead. + // an error will be returned instead. `nextConsumer` is never nil. CreateLogsReceiver(ctx context.Context, set CreateSettings, cfg component.Config, nextConsumer consumer.Logs) (Logs, error) // LogsReceiverStability gets the stability level of the LogsReceiver. @@ -236,6 +241,9 @@ func NewBuilder(cfgs map[component.ID]component.Config, factories map[component. // CreateTraces creates a Traces receiver based on the settings and config. func (b *Builder) CreateTraces(ctx context.Context, set CreateSettings, next consumer.Traces) (Traces, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("receiver %q is not configured", set.ID) @@ -252,6 +260,9 @@ func (b *Builder) CreateTraces(ctx context.Context, set CreateSettings, next con // CreateMetrics creates a Metrics receiver based on the settings and config. func (b *Builder) CreateMetrics(ctx context.Context, set CreateSettings, next consumer.Metrics) (Metrics, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("receiver %q is not configured", set.ID) @@ -268,6 +279,9 @@ func (b *Builder) CreateMetrics(ctx context.Context, set CreateSettings, next co // CreateLogs creates a Logs receiver based on the settings and config. func (b *Builder) CreateLogs(ctx context.Context, set CreateSettings, next consumer.Logs) (Logs, error) { + if next == nil { + return nil, errNilNextConsumer + } cfg, existsCfg := b.cfgs[set.ID] if !existsCfg { return nil, fmt.Errorf("receiver %q is not configured", set.ID) diff --git a/receiver/receiver_test.go b/receiver/receiver_test.go index d04dd88247d..00b93dba549 100644 --- a/receiver/receiver_test.go +++ b/receiver/receiver_test.go @@ -17,31 +17,31 @@ import ( ) func TestNewFactory(t *testing.T) { - const typeStr = "test" + var testType = component.MustNewType("test") defaultCfg := struct{}{} factory := NewFactory( - typeStr, + testType, func() component.Config { return &defaultCfg }) - assert.EqualValues(t, typeStr, factory.Type()) + assert.EqualValues(t, testType, factory.Type()) assert.EqualValues(t, &defaultCfg, factory.CreateDefaultConfig()) - _, err := factory.CreateTracesReceiver(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err := factory.CreateTracesReceiver(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.Error(t, err) - _, err = factory.CreateMetricsReceiver(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err = factory.CreateMetricsReceiver(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.Error(t, err) - _, err = factory.CreateLogsReceiver(context.Background(), CreateSettings{}, &defaultCfg, nil) + _, err = factory.CreateLogsReceiver(context.Background(), CreateSettings{}, &defaultCfg, consumertest.NewNop()) assert.Error(t, err) } func TestNewFactoryWithOptions(t *testing.T) { - const typeStr = "test" + var testType = component.MustNewType("test") defaultCfg := struct{}{} factory := NewFactory( - typeStr, + testType, func() component.Config { return &defaultCfg }, WithTraces(createTraces, component.StabilityLevelDeprecated), WithMetrics(createMetrics, component.StabilityLevelAlpha), WithLogs(createLogs, component.StabilityLevelStable)) - assert.EqualValues(t, typeStr, factory.Type()) + assert.EqualValues(t, testType, factory.Type()) assert.EqualValues(t, &defaultCfg, factory.CreateDefaultConfig()) assert.Equal(t, component.StabilityLevelDeprecated, factory.TracesReceiverStability()) @@ -64,8 +64,8 @@ func TestMakeFactoryMap(t *testing.T) { out map[component.Type]Factory } - p1 := NewFactory("p1", nil) - p2 := NewFactory("p2", nil) + p1 := NewFactory(component.MustNewType("p1"), nil) + p2 := NewFactory(component.MustNewType("p2"), nil) testCases := []testCase{ { name: "different names", @@ -77,7 +77,7 @@ func TestMakeFactoryMap(t *testing.T) { }, { name: "same name", - in: []Factory{p1, p2, NewFactory("p1", nil)}, + in: []Factory{p1, p2, NewFactory(component.MustNewType("p1"), nil)}, }, } @@ -98,9 +98,9 @@ func TestMakeFactoryMap(t *testing.T) { func TestBuilder(t *testing.T) { defaultCfg := struct{}{} factories, err := MakeFactoryMap([]Factory{ - NewFactory("err", nil), + NewFactory(component.MustNewType("err"), nil), NewFactory( - "all", + component.MustNewType("all"), func() component.Config { return &defaultCfg }, WithTraces(createTraces, component.StabilityLevelDevelopment), WithMetrics(createMetrics, component.StabilityLevelAlpha), @@ -110,27 +110,50 @@ func TestBuilder(t *testing.T) { require.NoError(t, err) testCases := []struct { - name string - id component.ID - err string + name string + id component.ID + err string + nextTraces consumer.Traces + nextLogs consumer.Logs + nextMetrics consumer.Metrics }{ { - name: "unknown", - id: component.NewID("unknown"), - err: "receiver factory not available for: \"unknown\"", + name: "unknown", + id: component.MustNewID("unknown"), + err: "receiver factory not available for: \"unknown\"", + nextTraces: consumertest.NewNop(), + nextLogs: consumertest.NewNop(), + nextMetrics: consumertest.NewNop(), + }, + { + name: "err", + id: component.MustNewID("err"), + err: "telemetry type is not supported", + nextTraces: consumertest.NewNop(), + nextLogs: consumertest.NewNop(), + nextMetrics: consumertest.NewNop(), }, { - name: "err", - id: component.NewID("err"), - err: "telemetry type is not supported", + name: "all", + id: component.MustNewID("all"), + nextTraces: consumertest.NewNop(), + nextLogs: consumertest.NewNop(), + nextMetrics: consumertest.NewNop(), }, { - name: "all", - id: component.NewID("all"), + name: "all/named", + id: component.MustNewIDWithName("all", "named"), + nextTraces: consumertest.NewNop(), + nextLogs: consumertest.NewNop(), + nextMetrics: consumertest.NewNop(), }, { - name: "all/named", - id: component.NewIDWithName("all", "named"), + name: "no next consumer", + id: component.MustNewID("unknown"), + err: "nil next Consumer", + nextTraces: nil, + nextLogs: nil, + nextMetrics: nil, }, } @@ -139,7 +162,7 @@ func TestBuilder(t *testing.T) { cfgs := map[component.ID]component.Config{tt.id: defaultCfg} b := NewBuilder(cfgs, factories) - te, err := b.CreateTraces(context.Background(), createSettings(tt.id), nil) + te, err := b.CreateTraces(context.Background(), createSettings(tt.id), tt.nextTraces) if tt.err != "" { assert.EqualError(t, err, tt.err) assert.Nil(t, te) @@ -148,7 +171,7 @@ func TestBuilder(t *testing.T) { assert.Equal(t, nopInstance, te) } - me, err := b.CreateMetrics(context.Background(), createSettings(tt.id), nil) + me, err := b.CreateMetrics(context.Background(), createSettings(tt.id), tt.nextMetrics) if tt.err != "" { assert.EqualError(t, err, tt.err) assert.Nil(t, me) @@ -157,7 +180,7 @@ func TestBuilder(t *testing.T) { assert.Equal(t, nopInstance, me) } - le, err := b.CreateLogs(context.Background(), createSettings(tt.id), nil) + le, err := b.CreateLogs(context.Background(), createSettings(tt.id), tt.nextLogs) if tt.err != "" { assert.EqualError(t, err, tt.err) assert.Nil(t, le) @@ -173,7 +196,7 @@ func TestBuilderMissingConfig(t *testing.T) { defaultCfg := struct{}{} factories, err := MakeFactoryMap([]Factory{ NewFactory( - "all", + component.MustNewType("all"), func() component.Config { return &defaultCfg }, WithTraces(createTraces, component.StabilityLevelDevelopment), WithMetrics(createMetrics, component.StabilityLevelAlpha), @@ -184,30 +207,30 @@ func TestBuilderMissingConfig(t *testing.T) { require.NoError(t, err) bErr := NewBuilder(map[component.ID]component.Config{}, factories) - missingID := component.NewIDWithName("all", "missing") + missingID := component.MustNewIDWithName("all", "missing") - te, err := bErr.CreateTraces(context.Background(), createSettings(missingID), nil) + te, err := bErr.CreateTraces(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "receiver \"all/missing\" is not configured") assert.Nil(t, te) - me, err := bErr.CreateMetrics(context.Background(), createSettings(missingID), nil) + me, err := bErr.CreateMetrics(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "receiver \"all/missing\" is not configured") assert.Nil(t, me) - le, err := bErr.CreateLogs(context.Background(), createSettings(missingID), nil) + le, err := bErr.CreateLogs(context.Background(), createSettings(missingID), consumertest.NewNop()) assert.EqualError(t, err, "receiver \"all/missing\" is not configured") assert.Nil(t, le) } func TestBuilderFactory(t *testing.T) { - factories, err := MakeFactoryMap([]Factory{NewFactory("foo", nil)}...) + factories, err := MakeFactoryMap([]Factory{NewFactory(component.MustNewType("foo"), nil)}...) require.NoError(t, err) - cfgs := map[component.ID]component.Config{component.NewID("foo"): struct{}{}} + cfgs := map[component.ID]component.Config{component.MustNewID("foo"): struct{}{}} b := NewBuilder(cfgs, factories) - assert.NotNil(t, b.Factory(component.NewID("foo").Type())) - assert.Nil(t, b.Factory(component.NewID("bar").Type())) + assert.NotNil(t, b.Factory(component.MustNewID("foo").Type())) + assert.Nil(t, b.Factory(component.MustNewID("bar").Type())) } var nopInstance = &nopReceiver{ diff --git a/receiver/receiverhelper/obsreport.go b/receiver/receiverhelper/obsreport.go index edea46ebcfe..d70f6789157 100644 --- a/receiver/receiverhelper/obsreport.go +++ b/receiver/receiverhelper/obsreport.go @@ -5,21 +5,16 @@ package receiverhelper // import "go.opentelemetry.io/collector/receiver/receive import ( "context" - "errors" - "go.opencensus.io/stats" - "go.opencensus.io/tag" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/metric" - sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/trace" "go.uber.org/multierr" "go.uber.org/zap" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configtelemetry" - "go.opentelemetry.io/collector/internal/obsreportconfig" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" "go.opentelemetry.io/collector/receiver" ) @@ -34,13 +29,11 @@ type ObsReport struct { spanNamePrefix string transport string longLivedCtx bool - mutators []tag.Mutator tracer trace.Tracer meter metric.Meter logger *zap.Logger - useOtelForMetrics bool - otelAttrs []attribute.KeyValue + otelAttrs []attribute.KeyValue acceptedSpansCounter metric.Int64Counter refusedSpansCounter metric.Int64Counter @@ -65,35 +58,26 @@ type ObsReportSettings struct { // NewObsReport creates a new ObsReport. func NewObsReport(cfg ObsReportSettings) (*ObsReport, error) { - return newReceiver(cfg, obsreportconfig.UseOtelForInternalMetricsfeatureGate.IsEnabled()) + return newReceiver(cfg) } -func newReceiver(cfg ObsReportSettings, useOtel bool) (*ObsReport, error) { +func newReceiver(cfg ObsReportSettings) (*ObsReport, error) { rec := &ObsReport{ level: cfg.ReceiverCreateSettings.TelemetrySettings.MetricsLevel, spanNamePrefix: obsmetrics.ReceiverPrefix + cfg.ReceiverID.String(), transport: cfg.Transport, longLivedCtx: cfg.LongLivedCtx, - mutators: []tag.Mutator{ - tag.Upsert(obsmetrics.TagKeyReceiver, cfg.ReceiverID.String(), tag.WithTTL(tag.TTLNoPropagation)), - tag.Upsert(obsmetrics.TagKeyTransport, cfg.Transport, tag.WithTTL(tag.TTLNoPropagation)), - }, - tracer: cfg.ReceiverCreateSettings.TracerProvider.Tracer(cfg.ReceiverID.String()), - meter: cfg.ReceiverCreateSettings.MeterProvider.Meter(receiverScope), - logger: cfg.ReceiverCreateSettings.Logger, + tracer: cfg.ReceiverCreateSettings.TracerProvider.Tracer(cfg.ReceiverID.String()), + meter: cfg.ReceiverCreateSettings.MeterProvider.Meter(receiverScope), + logger: cfg.ReceiverCreateSettings.Logger, - useOtelForMetrics: useOtel, otelAttrs: []attribute.KeyValue{ attribute.String(obsmetrics.ReceiverKey, cfg.ReceiverID.String()), attribute.String(obsmetrics.TransportKey, cfg.Transport), }, } - // ignore instrument name error as per workaround in https://github.com/open-telemetry/opentelemetry-collector/issues/8346 - // if err := rec.createOtelMetrics(); err != nil { - // return nil, err - // } - if err := rec.createOtelMetrics(); err != nil && !errors.Is(err, sdkmetric.ErrInstrumentName) { + if err := rec.createOtelMetrics(); err != nil { return nil, err } @@ -101,10 +85,6 @@ func newReceiver(cfg ObsReportSettings, useOtel bool) (*ObsReport, error) { } func (rec *ObsReport) createOtelMetrics() error { - if !rec.useOtelForMetrics { - return nil - } - var errors, err error rec.acceptedSpansCounter, err = rec.meter.Int64Counter( @@ -209,11 +189,11 @@ func (rec *ObsReport) EndMetricsOp( // startOp creates the span used to trace the operation. Returning // the updated context with the created span. func (rec *ObsReport) startOp(receiverCtx context.Context, operationSuffix string) context.Context { - ctx, _ := tag.New(receiverCtx, rec.mutators...) + var ctx context.Context var span trace.Span spanName := rec.spanNamePrefix + operationSuffix if !rec.longLivedCtx { - ctx, span = rec.tracer.Start(ctx, spanName) + ctx, span = rec.tracer.Start(receiverCtx, spanName) } else { // Since the receiverCtx is long lived do not use it to start the span. // This way this trace ends when the EndTracesOp is called. @@ -222,7 +202,7 @@ func (rec *ObsReport) startOp(receiverCtx context.Context, operationSuffix strin SpanContext: trace.SpanContextFromContext(receiverCtx), })) - ctx = trace.ContextWithSpan(ctx, span) + ctx = trace.ContextWithSpan(receiverCtx, span) } if rec.transport != "" { @@ -280,14 +260,6 @@ func (rec *ObsReport) endOp( } func (rec *ObsReport) recordMetrics(receiverCtx context.Context, dataType component.DataType, numAccepted, numRefused int) { - if rec.useOtelForMetrics { - rec.recordWithOtel(receiverCtx, dataType, numAccepted, numRefused) - } else { - rec.recordWithOC(receiverCtx, dataType, numAccepted, numRefused) - } -} - -func (rec *ObsReport) recordWithOtel(receiverCtx context.Context, dataType component.DataType, numAccepted, numRefused int) { var acceptedMeasure, refusedMeasure metric.Int64Counter switch dataType { case component.DataTypeTraces: @@ -304,23 +276,3 @@ func (rec *ObsReport) recordWithOtel(receiverCtx context.Context, dataType compo acceptedMeasure.Add(receiverCtx, int64(numAccepted), metric.WithAttributes(rec.otelAttrs...)) refusedMeasure.Add(receiverCtx, int64(numRefused), metric.WithAttributes(rec.otelAttrs...)) } - -func (rec *ObsReport) recordWithOC(receiverCtx context.Context, dataType component.DataType, numAccepted, numRefused int) { - var acceptedMeasure, refusedMeasure *stats.Int64Measure - switch dataType { - case component.DataTypeTraces: - acceptedMeasure = obsmetrics.ReceiverAcceptedSpans - refusedMeasure = obsmetrics.ReceiverRefusedSpans - case component.DataTypeMetrics: - acceptedMeasure = obsmetrics.ReceiverAcceptedMetricPoints - refusedMeasure = obsmetrics.ReceiverRefusedMetricPoints - case component.DataTypeLogs: - acceptedMeasure = obsmetrics.ReceiverAcceptedLogRecords - refusedMeasure = obsmetrics.ReceiverRefusedLogRecords - } - - stats.Record( - receiverCtx, - acceptedMeasure.M(int64(numAccepted)), - refusedMeasure.M(int64(numRefused))) -} diff --git a/receiver/receiverhelper/obsreport_test.go b/receiver/receiverhelper/obsreport_test.go index 941d66ee621..3a417e176aa 100644 --- a/receiver/receiverhelper/obsreport_test.go +++ b/receiver/receiverhelper/obsreport_test.go @@ -14,9 +14,9 @@ import ( "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" - "go.opentelemetry.io/collector/obsreport/obsreporttest" - "go.opentelemetry.io/collector/receiver/receivertest" + "go.opentelemetry.io/collector/receiver" ) const ( @@ -25,7 +25,7 @@ const ( ) var ( - receiverID = component.NewID("fakeReceiver") + receiverID = component.MustNewID("fakeReceiver") errFake = errors.New("errFake") ) @@ -36,8 +36,8 @@ type testParams struct { } func TestReceiveTraceDataOp(t *testing.T) { - testTelemetry(t, receiverID, func(t *testing.T, tt obsreporttest.TestTelemetry, useOtel bool) { - parentCtx, parentSpan := tt.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) + testTelemetry(t, receiverID, func(t *testing.T, tt componenttest.TestTelemetry) { + parentCtx, parentSpan := tt.TelemetrySettings().TracerProvider.Tracer("test").Start(context.Background(), t.Name()) defer parentSpan.End() params := []testParams{ @@ -48,8 +48,8 @@ func TestReceiveTraceDataOp(t *testing.T) { rec, err := newReceiver(ObsReportSettings{ ReceiverID: receiverID, Transport: transport, - ReceiverCreateSettings: receivertest.NewCreateSettings(receiverID, tt.TelemetrySettings), - }, useOtel) + ReceiverCreateSettings: receiver.CreateSettings{ID: receiverID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) require.NoError(t, err) ctx := rec.StartTracesOp(parentCtx) assert.NotNil(t, ctx) @@ -83,8 +83,8 @@ func TestReceiveTraceDataOp(t *testing.T) { } func TestReceiveLogsOp(t *testing.T) { - testTelemetry(t, receiverID, func(t *testing.T, tt obsreporttest.TestTelemetry, useOtel bool) { - parentCtx, parentSpan := tt.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) + testTelemetry(t, receiverID, func(t *testing.T, tt componenttest.TestTelemetry) { + parentCtx, parentSpan := tt.TelemetrySettings().TracerProvider.Tracer("test").Start(context.Background(), t.Name()) defer parentSpan.End() params := []testParams{ @@ -95,8 +95,8 @@ func TestReceiveLogsOp(t *testing.T) { rec, err := newReceiver(ObsReportSettings{ ReceiverID: receiverID, Transport: transport, - ReceiverCreateSettings: receivertest.NewCreateSettings(receiverID, tt.TelemetrySettings), - }, useOtel) + ReceiverCreateSettings: receiver.CreateSettings{ID: receiverID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) require.NoError(t, err) ctx := rec.StartLogsOp(parentCtx) @@ -131,8 +131,8 @@ func TestReceiveLogsOp(t *testing.T) { } func TestReceiveMetricsOp(t *testing.T) { - testTelemetry(t, receiverID, func(t *testing.T, tt obsreporttest.TestTelemetry, useOtel bool) { - parentCtx, parentSpan := tt.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) + testTelemetry(t, receiverID, func(t *testing.T, tt componenttest.TestTelemetry) { + parentCtx, parentSpan := tt.TelemetrySettings().TracerProvider.Tracer("test").Start(context.Background(), t.Name()) defer parentSpan.End() params := []testParams{ @@ -143,8 +143,8 @@ func TestReceiveMetricsOp(t *testing.T) { rec, err := newReceiver(ObsReportSettings{ ReceiverID: receiverID, Transport: transport, - ReceiverCreateSettings: receivertest.NewCreateSettings(receiverID, tt.TelemetrySettings), - }, useOtel) + ReceiverCreateSettings: receiver.CreateSettings{ID: receiverID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) require.NoError(t, err) ctx := rec.StartMetricsOp(parentCtx) @@ -180,11 +180,11 @@ func TestReceiveMetricsOp(t *testing.T) { } func TestReceiveWithLongLivedCtx(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(receiverID) + tt, err := componenttest.SetupTelemetry(receiverID) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - longLivedCtx, parentSpan := tt.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) + longLivedCtx, parentSpan := tt.TelemetrySettings().TracerProvider.Tracer("test").Start(context.Background(), t.Name()) defer parentSpan.End() params := []testParams{ @@ -198,7 +198,7 @@ func TestReceiveWithLongLivedCtx(t *testing.T) { ReceiverID: receiverID, Transport: transport, LongLivedCtx: true, - ReceiverCreateSettings: receivertest.NewCreateSettings(receiverID, tt.TelemetrySettings), + ReceiverCreateSettings: receiver.CreateSettings{ID: receiverID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, }) require.NoError(t, rerr) ctx := rec.StartTracesOp(longLivedCtx) @@ -233,20 +233,75 @@ func TestReceiveWithLongLivedCtx(t *testing.T) { } } -func testTelemetry(t *testing.T, id component.ID, testFunc func(t *testing.T, tt obsreporttest.TestTelemetry, useOtel bool)) { - t.Run("WithOC", func(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(id) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) +func TestCheckReceiverTracesViews(t *testing.T) { + tt, err := componenttest.SetupTelemetry(receiverID) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + rec, err := NewObsReport(ObsReportSettings{ + ReceiverID: receiverID, + Transport: transport, + ReceiverCreateSettings: receiver.CreateSettings{ID: receiverID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) + require.NoError(t, err) + ctx := rec.StartTracesOp(context.Background()) + require.NotNil(t, ctx) + rec.EndTracesOp(ctx, format, 7, nil) + + assert.NoError(t, tt.CheckReceiverTraces(transport, 7, 0)) + assert.Error(t, tt.CheckReceiverTraces(transport, 7, 7)) + assert.Error(t, tt.CheckReceiverTraces(transport, 0, 0)) + assert.Error(t, tt.CheckReceiverTraces(transport, 0, 7)) +} + +func TestCheckReceiverMetricsViews(t *testing.T) { + tt, err := componenttest.SetupTelemetry(receiverID) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + rec, err := NewObsReport(ObsReportSettings{ + ReceiverID: receiverID, + Transport: transport, + ReceiverCreateSettings: receiver.CreateSettings{ID: receiverID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) + require.NoError(t, err) + ctx := rec.StartMetricsOp(context.Background()) + require.NotNil(t, ctx) + rec.EndMetricsOp(ctx, format, 7, nil) + + assert.NoError(t, tt.CheckReceiverMetrics(transport, 7, 0)) + assert.Error(t, tt.CheckReceiverMetrics(transport, 7, 7)) + assert.Error(t, tt.CheckReceiverMetrics(transport, 0, 0)) + assert.Error(t, tt.CheckReceiverMetrics(transport, 0, 7)) +} - testFunc(t, tt, false) +func TestCheckReceiverLogsViews(t *testing.T) { + tt, err := componenttest.SetupTelemetry(receiverID) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) + + rec, err := NewObsReport(ObsReportSettings{ + ReceiverID: receiverID, + Transport: transport, + ReceiverCreateSettings: receiver.CreateSettings{ID: receiverID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, }) + require.NoError(t, err) + ctx := rec.StartLogsOp(context.Background()) + require.NotNil(t, ctx) + rec.EndLogsOp(ctx, format, 7, nil) + + assert.NoError(t, tt.CheckReceiverLogs(transport, 7, 0)) + assert.Error(t, tt.CheckReceiverLogs(transport, 7, 7)) + assert.Error(t, tt.CheckReceiverLogs(transport, 0, 0)) + assert.Error(t, tt.CheckReceiverLogs(transport, 0, 7)) +} +func testTelemetry(t *testing.T, id component.ID, testFunc func(t *testing.T, tt componenttest.TestTelemetry)) { t.Run("WithOTel", func(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(id) + tt, err := componenttest.SetupTelemetry(id) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - testFunc(t, tt, true) + testFunc(t, tt) }) } diff --git a/receiver/receiverhelper/package_test.go b/receiver/receiverhelper/package_test.go new file mode 100644 index 00000000000..7b9bf829fc9 --- /dev/null +++ b/receiver/receiverhelper/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package receiverhelper + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/receiver/receivertest/contract_checker.go b/receiver/receivertest/contract_checker.go index 7bd71d4c3a9..37dd68b7f80 100644 --- a/receiver/receivertest/contract_checker.go +++ b/receiver/receivertest/contract_checker.go @@ -22,6 +22,7 @@ import ( "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/ptrace" "go.opentelemetry.io/collector/receiver" ) @@ -78,7 +79,7 @@ func CheckConsumeContract(params CheckConsumeContractParams) { { name: "always_succeed", // Always succeed. We expect all data to be delivered as is. - decisionFunc: func(ids idSet) error { return nil }, + decisionFunc: func(idSet) error { return nil }, }, { name: "random_non_permanent_error", @@ -96,7 +97,7 @@ func CheckConsumeContract(params CheckConsumeContractParams) { for _, scenario := range scenarios { params.T.Run( - scenario.name, func(t *testing.T) { + scenario.name, func(*testing.T) { checkConsumeContractScenario(params, scenario.decisionFunc) }, ) @@ -104,7 +105,7 @@ func CheckConsumeContract(params CheckConsumeContractParams) { } func checkConsumeContractScenario(params CheckConsumeContractParams, decisionFunc func(ids idSet) error) { - consumer := &mockConsumer{t: params.T, consumeDecisionFunc: decisionFunc} + consumer := &mockConsumer{t: params.T, consumeDecisionFunc: decisionFunc, acceptedIDs: make(idSet), droppedIDs: make(idSet)} ctx := context.Background() // Create and start the receiver. @@ -116,8 +117,7 @@ func checkConsumeContractScenario(params CheckConsumeContractParams, decisionFun case component.DataTypeTraces: receiver, err = params.Factory.CreateTracesReceiver(ctx, NewNopCreateSettings(), params.Config, consumer) case component.DataTypeMetrics: - // TODO: add metrics support to mockConsumer so that this case can be also implemented. - require.FailNow(params.T, "DataTypeMetrics is not implemented") + receiver, err = params.Factory.CreateMetricsReceiver(ctx, NewNopCreateSettings(), params.Config, consumer) default: require.FailNow(params.T, "must specify a valid DataType to test for") } @@ -129,7 +129,7 @@ func checkConsumeContractScenario(params CheckConsumeContractParams, decisionFun // Begin generating data to the receiver. - var generatedIds idSet + generatedIDs := make(idSet) var generatedIndex int64 var mux sync.Mutex var wg sync.WaitGroup @@ -151,7 +151,7 @@ func checkConsumeContractScenario(params CheckConsumeContractParams, decisionFun require.Greater(params.T, len(ids), 0) mux.Lock() - duplicates := generatedIds.mergeSlice(ids) + duplicates := generatedIDs.mergeSlice(ids) mux.Unlock() // Check that the generator works correctly. There may not be any duplicates in the @@ -172,7 +172,7 @@ func checkConsumeContractScenario(params CheckConsumeContractParams, decisionFun assert.Failf(params.T, "found duplicate elements in received and dropped data", "keys=%v", duplicates) } // Compare accepted+dropped with generated. Once they are equal it means all data is seen by the consumer. - missingInOther, onlyInOther := generatedIds.compare(acceptedAndDropped) + missingInOther, onlyInOther := generatedIDs.compare(acceptedAndDropped) return len(missingInOther) == 0 && len(onlyInOther) == 0 }, 5*time.Second, 10*time.Millisecond) @@ -184,7 +184,7 @@ func checkConsumeContractScenario(params CheckConsumeContractParams, decisionFun // Make sure generated and accepted+dropped are exactly the same. - missingInOther, onlyInOther := generatedIds.compare(acceptedAndDropped) + missingInOther, onlyInOther := generatedIDs.compare(acceptedAndDropped) if len(missingInOther) != 0 { assert.Failf(params.T, "found elements sent that were not delivered", "keys=%v", missingInOther) } @@ -198,9 +198,9 @@ func checkConsumeContractScenario(params CheckConsumeContractParams, decisionFun // Print some stats to help debug test failures. fmt.Printf( "Sent %d, accepted=%d, expected dropped=%d, non-permanent errors retried=%d\n", - len(generatedIds), - len(consumer.acceptedIds), - len(consumer.droppedIds), + len(generatedIDs), + len(consumer.acceptedIDs), + len(consumer.droppedIDs), consumer.nonPermanentFailures, ) } @@ -224,30 +224,24 @@ func (ds idSet) compare(other idSet) (missingInOther, onlyInOther []UniqueIDAttr } // merge another set into this one and return a list of duplicate ids. -func (ds *idSet) merge(other idSet) (duplicates []UniqueIDAttrVal) { - if *ds == nil { - *ds = map[UniqueIDAttrVal]bool{} - } +func (ds idSet) merge(other idSet) (duplicates []UniqueIDAttrVal) { for k, v := range other { - if _, ok := (*ds)[k]; ok { + if _, ok := ds[k]; ok { duplicates = append(duplicates, k) } else { - (*ds)[k] = v + ds[k] = v } } return } -// merge another set into this one and return a list of duplicate ids. -func (ds *idSet) mergeSlice(other []UniqueIDAttrVal) (duplicates []UniqueIDAttrVal) { - if *ds == nil { - *ds = map[UniqueIDAttrVal]bool{} - } +// mergeSlice merges another set into this one and return a list of duplicate ids. +func (ds idSet) mergeSlice(other []UniqueIDAttrVal) (duplicates []UniqueIDAttrVal) { for _, id := range other { - if _, ok := (*ds)[id]; ok { + if _, ok := ds[id]; ok { duplicates = append(duplicates, id) } else { - (*ds)[id] = true + ds[id] = true } } return @@ -255,9 +249,9 @@ func (ds *idSet) mergeSlice(other []UniqueIDAttrVal) (duplicates []UniqueIDAttrV // union computes the union of this and another sets. A new set if created to return the result. // Also returns a list of any duplicate ids found. -func (ds *idSet) union(other idSet) (union idSet, duplicates []UniqueIDAttrVal) { +func (ds idSet) union(other idSet) (union idSet, duplicates []UniqueIDAttrVal) { union = map[UniqueIDAttrVal]bool{} - for k, v := range *ds { + for k, v := range ds { union[k] = v } for k, v := range other { @@ -282,7 +276,7 @@ var errPermanent = errors.New("permanent error") // randomNonPermanentErrorConsumeDecision is a decision function that succeeds approximately // half of the time and fails with a non-permanent error the rest of the time. -func randomNonPermanentErrorConsumeDecision(_ idSet) error { +func randomNonPermanentErrorConsumeDecision(idSet) error { if rand.Float32() < 0.5 { return errNonPermanent } @@ -291,7 +285,7 @@ func randomNonPermanentErrorConsumeDecision(_ idSet) error { // randomPermanentErrorConsumeDecision is a decision function that succeeds approximately // half of the time and fails with a permanent error the rest of the time. -func randomPermanentErrorConsumeDecision(_ idSet) error { +func randomPermanentErrorConsumeDecision(idSet) error { if rand.Float32() < 0.5 { return consumererror.NewPermanent(errPermanent) } @@ -301,7 +295,7 @@ func randomPermanentErrorConsumeDecision(_ idSet) error { // randomErrorsConsumeDecision is a decision function that succeeds approximately // a third of the time, fails with a permanent error the third of the time and fails with // a non-permanent error the rest of the time. -func randomErrorsConsumeDecision(_ idSet) error { +func randomErrorsConsumeDecision(idSet) error { r := rand.Float64() third := 1.0 / 3.0 if r < third { @@ -321,8 +315,8 @@ type mockConsumer struct { t *testing.T consumeDecisionFunc consumeDecisionFunc mux sync.Mutex - acceptedIds idSet - droppedIds idSet + acceptedIDs idSet + droppedIDs idSet nonPermanentFailures int } @@ -390,7 +384,76 @@ func idSetFromLogs(data plog.Logs) (idSet, error) { return ds, nil } -// TODO: Implement mockConsumer.ConsumeMetrics() +func (m *mockConsumer) ConsumeMetrics(_ context.Context, data pmetric.Metrics) error { + ids, err := idSetFromMetrics(data) + require.NoError(m.t, err) + return m.consume(ids) +} + +// idSetFromLogs computes an idSet from given pmetric.Metrics. The idSet will contain ids of all metric data points. +func idSetFromMetrics(data pmetric.Metrics) (idSet, error) { + ds := map[UniqueIDAttrVal]bool{} + rss := data.ResourceMetrics() + for i := 0; i < rss.Len(); i++ { + ils := rss.At(i).ScopeMetrics() + for j := 0; j < ils.Len(); j++ { + ss := ils.At(j).Metrics() + for k := 0; k < ss.Len(); k++ { + elem := ss.At(k) + switch elem.Type() { + case pmetric.MetricTypeGauge: + for l := 0; l < elem.Gauge().DataPoints().Len(); l++ { + dp := elem.Gauge().DataPoints().At(l) + if err := idSetFromDataPoint(ds, dp.Attributes()); err != nil { + return ds, err + } + } + case pmetric.MetricTypeSum: + for l := 0; l < elem.Sum().DataPoints().Len(); l++ { + dp := elem.Sum().DataPoints().At(l) + if err := idSetFromDataPoint(ds, dp.Attributes()); err != nil { + return ds, err + } + } + case pmetric.MetricTypeSummary: + for l := 0; l < elem.Summary().DataPoints().Len(); l++ { + dp := elem.Summary().DataPoints().At(l) + if err := idSetFromDataPoint(ds, dp.Attributes()); err != nil { + return ds, err + } + } + case pmetric.MetricTypeHistogram: + for l := 0; l < elem.Histogram().DataPoints().Len(); l++ { + dp := elem.Histogram().DataPoints().At(l) + if err := idSetFromDataPoint(ds, dp.Attributes()); err != nil { + return ds, err + } + } + case pmetric.MetricTypeExponentialHistogram: + for l := 0; l < elem.ExponentialHistogram().DataPoints().Len(); l++ { + dp := elem.ExponentialHistogram().DataPoints().At(l) + if err := idSetFromDataPoint(ds, dp.Attributes()); err != nil { + return ds, err + } + } + } + } + } + } + return ds, nil +} + +func idSetFromDataPoint(ds map[UniqueIDAttrVal]bool, attributes pcommon.Map) error { + key, exists := attributes.Get(UniqueIDAttrName) + if !exists { + return fmt.Errorf("invalid data element, attribute %q is missing", UniqueIDAttrName) + } + if key.Type() != pcommon.ValueTypeStr { + return fmt.Errorf("invalid data element, attribute %q is wrong type %v", UniqueIDAttrName, key.Type()) + } + ds[UniqueIDAttrVal(key.Str())] = true + return nil +} // consume the elements with the specified ids, regardless of the element data type. func (m *mockConsumer) consume(ids idSet) error { @@ -404,7 +467,7 @@ func (m *mockConsumer) consume(ids idSet) error { if consumererror.IsPermanent(err) { // It is a permanent error, which means we need to drop the data. // Remember the ids of dropped elements. - duplicates := m.droppedIds.merge(ids) + duplicates := m.droppedIDs.merge(ids) require.Empty(m.t, duplicates, "elements that were dropped previously were sent again") } else { // It is a non-permanent error. Don't add it to the drop list. Remember the number of @@ -416,7 +479,7 @@ func (m *mockConsumer) consume(ids idSet) error { } // The decision is a success. Remember the ids of the data in the accepted list. - duplicates := m.acceptedIds.merge(ids) + duplicates := m.acceptedIDs.merge(ids) require.Empty(m.t, duplicates, "elements that were accepted previously were sent again") return nil } @@ -426,7 +489,7 @@ func (m *mockConsumer) consume(ids idSet) error { func (m *mockConsumer) acceptedAndDropped() (acceptedAndDropped idSet, duplicates []UniqueIDAttrVal) { m.mux.Lock() defer m.mux.Unlock() - return m.acceptedIds.union(m.droppedIds) + return m.acceptedIDs.union(m.droppedIDs) } func CreateOneLogWithID(id UniqueIDAttrVal) plog.Logs { @@ -437,3 +500,62 @@ func CreateOneLogWithID(id UniqueIDAttrVal) plog.Logs { ) return data } + +func CreateGaugeMetricWithID(id UniqueIDAttrVal) pmetric.Metrics { + data := pmetric.NewMetrics() + gauge := data.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics() + gauge.AppendEmpty().SetEmptyGauge().DataPoints().AppendEmpty().Attributes().PutStr( + UniqueIDAttrName, + string(id), + ) + return data +} + +func CreateSumMetricWithID(id UniqueIDAttrVal) pmetric.Metrics { + data := pmetric.NewMetrics() + sum := data.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics() + sum.AppendEmpty().SetEmptySum().DataPoints().AppendEmpty().Attributes().PutStr( + UniqueIDAttrName, + string(id), + ) + return data +} + +func CreateSummaryMetricWithID(id UniqueIDAttrVal) pmetric.Metrics { + data := pmetric.NewMetrics() + summary := data.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics() + summary.AppendEmpty().SetEmptySummary().DataPoints().AppendEmpty().Attributes().PutStr( + UniqueIDAttrName, + string(id), + ) + return data +} + +func CreateHistogramMetricWithID(id UniqueIDAttrVal) pmetric.Metrics { + data := pmetric.NewMetrics() + histogram := data.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics() + histogram.AppendEmpty().SetEmptyHistogram().DataPoints().AppendEmpty().Attributes().PutStr( + UniqueIDAttrName, + string(id), + ) + return data +} + +func CreateExponentialHistogramMetricWithID(id UniqueIDAttrVal) pmetric.Metrics { + data := pmetric.NewMetrics() + exponentialHistogram := data.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics() + exponentialHistogram.AppendEmpty().SetEmptyExponentialHistogram().DataPoints().AppendEmpty().Attributes().PutStr( + UniqueIDAttrName, + string(id), + ) + return data +} + +func CreateOneSpanWithID(id UniqueIDAttrVal) ptrace.Traces { + data := ptrace.NewTraces() + data.ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty().Attributes().PutStr( + UniqueIDAttrName, + string(id), + ) + return data +} diff --git a/receiver/receivertest/contract_checker_test.go b/receiver/receivertest/contract_checker_test.go index 2212d0b6196..57906308400 100644 --- a/receiver/receivertest/contract_checker_test.go +++ b/receiver/receivertest/contract_checker_test.go @@ -9,10 +9,15 @@ import ( "sync/atomic" "testing" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumererror" + "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" "go.opentelemetry.io/collector/receiver" ) @@ -20,21 +25,61 @@ import ( // We declare a trivial example receiver, a data generator and then use them in TestConsumeContract(). type exampleReceiver struct { - nextConsumer consumer.Logs + nextLogsConsumer consumer.Logs + nextTracesConsumer consumer.Traces + nextMetricsConsumer consumer.Metrics } -func (s *exampleReceiver) Start(_ context.Context, _ component.Host) error { +func (s *exampleReceiver) Start(context.Context, component.Host) error { return nil } -func (s *exampleReceiver) Shutdown(_ context.Context) error { +func (s *exampleReceiver) Shutdown(context.Context) error { return nil } -func (s *exampleReceiver) Receive(data plog.Logs) { +func (s *exampleReceiver) ReceiveLogs(data plog.Logs) { + // This very simple implementation demonstrates how a single items receiving should happen. + for { + err := s.nextLogsConsumer.ConsumeLogs(context.Background(), data) + if err != nil { + // The next consumer returned an error. + if !consumererror.IsPermanent(err) { + // It is not a permanent error, so we must retry sending it again. In network-based + // receivers instead we can ask our sender to re-retry the same data again later. + // We may also pause here a bit if we don't want to hammer the next consumer. + continue + } + } + // If we are hear either the ConsumeLogs returned success or it returned a permanent error. + // In either case we don't need to retry the same data, we are done. + return + } +} + +func (s *exampleReceiver) ReceiveMetrics(data pmetric.Metrics) { + // This very simple implementation demonstrates how a single items receiving should happen. + for { + err := s.nextMetricsConsumer.ConsumeMetrics(context.Background(), data) + if err != nil { + // The next consumer returned an error. + if !consumererror.IsPermanent(err) { + // It is not a permanent error, so we must retry sending it again. In network-based + // receivers instead we can ask our sender to re-retry the same data again later. + // We may also pause here a bit if we don't want to hammer the next consumer. + continue + } + } + // If we are hear either the ConsumeLogs returned success or it returned a permanent error. + // In either case we don't need to retry the same data, we are done. + return + } +} + +func (s *exampleReceiver) ReceiveTraces(data ptrace.Traces) { // This very simple implementation demonstrates how a single items receiving should happen. for { - err := s.nextConsumer.ConsumeLogs(context.Background(), data) + err := s.nextTracesConsumer.ConsumeTraces(context.Background(), data) if err != nil { // The next consumer returned an error. if !consumererror.IsPermanent(err) { @@ -52,30 +97,95 @@ func (s *exampleReceiver) Receive(data plog.Logs) { // A config for exampleReceiver. type exampleReceiverConfig struct { - generator *exampleGenerator + generator Generator } // A generator that can send data to exampleReceiver. -type exampleGenerator struct { +type exampleLogGenerator struct { t *testing.T receiver *exampleReceiver sequenceNum int64 } -func (g *exampleGenerator) Start() { +func (g *exampleLogGenerator) Start() { g.sequenceNum = 0 } -func (g *exampleGenerator) Stop() {} +func (g *exampleLogGenerator) Stop() {} -func (g *exampleGenerator) Generate() []UniqueIDAttrVal { +func (g *exampleLogGenerator) Generate() []UniqueIDAttrVal { // Make sure the id is atomically incremented. Generate() may be called concurrently. id := UniqueIDAttrVal(strconv.FormatInt(atomic.AddInt64(&g.sequenceNum, 1), 10)) data := CreateOneLogWithID(id) // Send the generated data to the receiver. - g.receiver.Receive(data) + g.receiver.ReceiveLogs(data) + + // And return the ids for bookkeeping by the test. + return []UniqueIDAttrVal{id} +} + +// A generator that can send data to exampleReceiver. +type exampleTraceGenerator struct { + t *testing.T + receiver *exampleReceiver + sequenceNum int64 +} + +func (g *exampleTraceGenerator) Start() { + g.sequenceNum = 0 +} + +func (g *exampleTraceGenerator) Stop() {} + +func (g *exampleTraceGenerator) Generate() []UniqueIDAttrVal { + // Make sure the id is atomically incremented. Generate() may be called concurrently. + id := UniqueIDAttrVal(strconv.FormatInt(atomic.AddInt64(&g.sequenceNum, 1), 10)) + + data := CreateOneSpanWithID(id) + + // Send the generated data to the receiver. + g.receiver.ReceiveTraces(data) + + // And return the ids for bookkeeping by the test. + return []UniqueIDAttrVal{id} +} + +// A generator that can send data to exampleReceiver. +type exampleMetricGenerator struct { + t *testing.T + receiver *exampleReceiver + sequenceNum int64 +} + +func (g *exampleMetricGenerator) Start() { + g.sequenceNum = 0 +} + +func (g *exampleMetricGenerator) Stop() {} + +func (g *exampleMetricGenerator) Generate() []UniqueIDAttrVal { + // Make sure the id is atomically incremented. Generate() may be called concurrently. + next := atomic.AddInt64(&g.sequenceNum, 1) + id := UniqueIDAttrVal(strconv.FormatInt(next, 10)) + + var data pmetric.Metrics + switch next % 5 { + case 0: + data = CreateGaugeMetricWithID(id) + case 1: + data = CreateSumMetricWithID(id) + case 2: + data = CreateSummaryMetricWithID(id) + case 3: + data = CreateHistogramMetricWithID(id) + case 4: + data = CreateExponentialHistogramMetricWithID(id) + } + + // Send the generated data to the receiver. + g.receiver.ReceiveMetrics(data) // And return the ids for bookkeeping by the test. return []UniqueIDAttrVal{id} @@ -83,22 +193,36 @@ func (g *exampleGenerator) Generate() []UniqueIDAttrVal { func newExampleFactory() receiver.Factory { return receiver.NewFactory( - "example_receiver", + component.MustNewType("example_receiver"), func() component.Config { return &exampleReceiverConfig{} }, receiver.WithLogs(createLog, component.StabilityLevelBeta), + receiver.WithMetrics(createMetric, component.StabilityLevelBeta), + receiver.WithTraces(createTrace, component.StabilityLevelBeta), ) } +func createTrace(_ context.Context, _ receiver.CreateSettings, cfg component.Config, consumer consumer.Traces) (receiver.Traces, error) { + rcv := &exampleReceiver{nextTracesConsumer: consumer} + cfg.(*exampleReceiverConfig).generator.(*exampleTraceGenerator).receiver = rcv + return rcv, nil +} + +func createMetric(_ context.Context, _ receiver.CreateSettings, cfg component.Config, consumer consumer.Metrics) (receiver.Metrics, error) { + rcv := &exampleReceiver{nextMetricsConsumer: consumer} + cfg.(*exampleReceiverConfig).generator.(*exampleMetricGenerator).receiver = rcv + return rcv, nil +} + func createLog( _ context.Context, _ receiver.CreateSettings, cfg component.Config, consumer consumer.Logs, ) (receiver.Logs, error) { - rcv := &exampleReceiver{nextConsumer: consumer} - cfg.(*exampleReceiverConfig).generator.receiver = rcv + rcv := &exampleReceiver{nextLogsConsumer: consumer} + cfg.(*exampleReceiverConfig).generator.(*exampleLogGenerator).receiver = rcv return rcv, nil } @@ -109,7 +233,7 @@ func TestConsumeContract(t *testing.T) { // Number of log records to send per scenario. const logsPerTest = 100 - generator := &exampleGenerator{t: t} + generator := &exampleLogGenerator{t: t} cfg := &exampleReceiverConfig{generator: generator} params := CheckConsumeContractParams{ @@ -124,3 +248,115 @@ func TestConsumeContract(t *testing.T) { // Run the contract checker. This will trigger test failures if any problems are found. CheckConsumeContract(params) } + +// TestConsumeMetricsContract is an example of testing of the receiver for the contract between the +// receiver and next consumer. +func TestConsumeMetricsContract(t *testing.T) { + + // Number of metric data points to send per scenario. + const metricsPerTest = 100 + + generator := &exampleMetricGenerator{t: t} + cfg := &exampleReceiverConfig{generator: generator} + + params := CheckConsumeContractParams{ + T: t, + Factory: newExampleFactory(), + DataType: component.DataTypeMetrics, + Config: cfg, + Generator: generator, + GenerateCount: metricsPerTest, + } + + // Run the contract checker. This will trigger test failures if any problems are found. + CheckConsumeContract(params) +} + +// TestConsumeTracesContract is an example of testing of the receiver for the contract between the +// receiver and next consumer. +func TestConsumeTracesContract(t *testing.T) { + + // Number of trace spans to send per scenario. + const spansPerTest = 100 + + generator := &exampleTraceGenerator{t: t} + cfg := &exampleReceiverConfig{generator: generator} + + params := CheckConsumeContractParams{ + T: t, + Factory: newExampleFactory(), + DataType: component.DataTypeTraces, + Config: cfg, + Generator: generator, + GenerateCount: spansPerTest, + } + + // Run the contract checker. This will trigger test failures if any problems are found. + CheckConsumeContract(params) +} + +func TestIDSetFromDataPoint(t *testing.T) { + require.Error(t, idSetFromDataPoint(map[UniqueIDAttrVal]bool{}, pcommon.NewMap())) + m := pcommon.NewMap() + m.PutStr("foo", "bar") + require.Error(t, idSetFromDataPoint(map[UniqueIDAttrVal]bool{}, m)) + m.PutInt(UniqueIDAttrName, 64) + require.Error(t, idSetFromDataPoint(map[UniqueIDAttrVal]bool{}, m)) + m.PutStr(UniqueIDAttrName, "myid") + result := map[UniqueIDAttrVal]bool{} + require.NoError(t, idSetFromDataPoint(result, m)) + require.True(t, result["myid"]) +} + +func TestBadMetricPoint(t *testing.T) { + for _, test := range []struct { + name string + metrics pmetric.Metrics + }{ + { + name: "gauge", + metrics: func() pmetric.Metrics { + m := pmetric.NewMetrics() + m.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptyGauge().DataPoints().AppendEmpty() + return m + }(), + }, + { + name: "sum", + metrics: func() pmetric.Metrics { + m := pmetric.NewMetrics() + m.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptySum().DataPoints().AppendEmpty() + return m + }(), + }, + { + name: "summary", + metrics: func() pmetric.Metrics { + m := pmetric.NewMetrics() + m.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptySummary().DataPoints().AppendEmpty() + return m + }(), + }, + { + name: "histogram", + metrics: func() pmetric.Metrics { + m := pmetric.NewMetrics() + m.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptyHistogram().DataPoints().AppendEmpty() + return m + }(), + }, + { + name: "exponential histogram", + metrics: func() pmetric.Metrics { + m := pmetric.NewMetrics() + m.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptyExponentialHistogram().DataPoints().AppendEmpty() + return m + }(), + }, + } { + t.Run(test.name, func(t *testing.T) { + _, err := idSetFromMetrics(test.metrics) + require.Error(t, err) + }) + } +} diff --git a/receiver/receivertest/nop_receiver.go b/receiver/receivertest/nop_receiver.go index e2216f5c4a3..0c7cee87cf3 100644 --- a/receiver/receivertest/nop_receiver.go +++ b/receiver/receivertest/nop_receiver.go @@ -12,11 +12,12 @@ import ( "go.opentelemetry.io/collector/receiver" ) -const typeStr = "nop" +var componentType = component.MustNewType("nop") -// NewNopCreateSettings returns a new nop settings for Create* functions. +// NewNopCreateSettings returns a new nop settings for Create*Receiver functions. func NewNopCreateSettings() receiver.CreateSettings { return receiver.CreateSettings{ + ID: component.NewID(componentType), TelemetrySettings: componenttest.NewNopTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo(), } @@ -25,7 +26,7 @@ func NewNopCreateSettings() receiver.CreateSettings { // NewNopFactory returns a receiver.Factory that constructs nop receivers. func NewNopFactory() receiver.Factory { return receiver.NewFactory( - "nop", + componentType, func() component.Config { return &nopConfig{} }, receiver.WithTraces(createTraces, component.StabilityLevelStable), receiver.WithMetrics(createMetrics, component.StabilityLevelStable), @@ -48,7 +49,7 @@ type nopConfig struct{} var nopInstance = &nopReceiver{} -// nopReceiver stores consumed traces and metrics for testing purposes. +// nopReceiver acts as a receiver for testing purposes. type nopReceiver struct { component.StartFunc component.ShutdownFunc @@ -58,14 +59,6 @@ type nopReceiver struct { func NewNopBuilder() *receiver.Builder { nopFactory := NewNopFactory() return receiver.NewBuilder( - map[component.ID]component.Config{component.NewID(typeStr): nopFactory.CreateDefaultConfig()}, - map[component.Type]receiver.Factory{typeStr: nopFactory}) -} - -func NewCreateSettings(id component.ID, set component.TelemetrySettings) receiver.CreateSettings { - return receiver.CreateSettings{ - ID: id, - TelemetrySettings: set, - BuildInfo: component.NewDefaultBuildInfo(), - } + map[component.ID]component.Config{component.NewID(componentType): nopFactory.CreateDefaultConfig()}, + map[component.Type]receiver.Factory{componentType: nopFactory}) } diff --git a/receiver/receivertest/nop_receiver_test.go b/receiver/receivertest/nop_receiver_test.go index f2f74d3f17e..d384e6b1fb7 100644 --- a/receiver/receivertest/nop_receiver_test.go +++ b/receiver/receivertest/nop_receiver_test.go @@ -15,10 +15,12 @@ import ( "go.opentelemetry.io/collector/consumer/consumertest" ) +var nopType = component.MustNewType("nop") + func TestNewNopFactory(t *testing.T) { factory := NewNopFactory() require.NotNil(t, factory) - assert.Equal(t, component.Type("nop"), factory.Type()) + assert.Equal(t, nopType, factory.Type()) cfg := factory.CreateDefaultConfig() assert.Equal(t, &nopConfig{}, cfg) @@ -45,7 +47,7 @@ func TestNewNopBuilder(t *testing.T) { factory := NewNopFactory() cfg := factory.CreateDefaultConfig() set := NewNopCreateSettings() - set.ID = component.NewID(typeStr) + set.ID = component.NewID(nopType) traces, err := factory.CreateTracesReceiver(context.Background(), set, cfg, consumertest.NewNop()) require.NoError(t, err) diff --git a/receiver/receivertest/package_test.go b/receiver/receivertest/package_test.go new file mode 100644 index 00000000000..c4702240490 --- /dev/null +++ b/receiver/receivertest/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package receivertest + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/receiver/scrapererror/package_test.go b/receiver/scrapererror/package_test.go new file mode 100644 index 00000000000..b414afd1d34 --- /dev/null +++ b/receiver/scrapererror/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package scrapererror + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/receiver/scrapererror/partialscrapeerror.go b/receiver/scrapererror/partialscrapeerror.go index e1a67fa52b0..cb4c03bab80 100644 --- a/receiver/scrapererror/partialscrapeerror.go +++ b/receiver/scrapererror/partialscrapeerror.go @@ -23,10 +23,6 @@ func NewPartialScrapeError(err error, failed int) PartialScrapeError { // IsPartialScrapeError checks if an error was wrapped with PartialScrapeError. func IsPartialScrapeError(err error) bool { - if err == nil { - return false - } - var partialScrapeErr PartialScrapeError return errors.As(err, &partialScrapeErr) } diff --git a/receiver/scraperhelper/settings.go b/receiver/scraperhelper/config.go similarity index 64% rename from receiver/scraperhelper/settings.go rename to receiver/scraperhelper/config.go index c59ea932583..68f0a56297d 100644 --- a/receiver/scraperhelper/settings.go +++ b/receiver/scraperhelper/config.go @@ -20,8 +20,14 @@ var ( // ScraperControllerSettings defines common settings for a scraper controller // configuration. Scraper controller receivers can embed this struct, instead // of receiver.Settings, and extend it with more fields if needed. -type ScraperControllerSettings struct { - // CollectionInterval sets the how frequently the scraper +// Deprecated: [v0.95.0] Use ControllerConfig instead +type ScraperControllerSettings = ControllerConfig + +// ControllerConfig defines common settings for a scraper controller +// configuration. Scraper controller receivers can embed this struct, instead +// of receiver.Settings, and extend it with more fields if needed. +type ControllerConfig struct { + // CollectionInterval sets how frequently the scraper // should be called and used as the context timeout // to ensure that scrapers don't exceed the interval. CollectionInterval time.Duration `mapstructure:"collection_interval"` @@ -34,15 +40,22 @@ type ScraperControllerSettings struct { // NewDefaultScraperControllerSettings returns default scraper controller // settings with a collection interval of one minute. -func NewDefaultScraperControllerSettings(component.Type) ScraperControllerSettings { - return ScraperControllerSettings{ +// Deprecated: [v0.95.0] Use NewDefaultControllerConfig instead +func NewDefaultScraperControllerSettings(component.Type) ControllerConfig { + return NewDefaultControllerConfig() +} + +// NewDefaultControllerConfig returns default scraper controller +// settings with a collection interval of one minute. +func NewDefaultControllerConfig() ControllerConfig { + return ControllerConfig{ CollectionInterval: time.Minute, InitialDelay: time.Second, Timeout: 0, } } -func (set *ScraperControllerSettings) Validate() (errs error) { +func (set *ControllerConfig) Validate() (errs error) { if set.CollectionInterval <= 0 { errs = multierr.Append(errs, fmt.Errorf(`"collection_interval": %w`, errNonPositiveInterval)) } diff --git a/receiver/scraperhelper/settings_test.go b/receiver/scraperhelper/config_test.go similarity index 84% rename from receiver/scraperhelper/settings_test.go rename to receiver/scraperhelper/config_test.go index 0fa0d57f915..1da08e78006 100644 --- a/receiver/scraperhelper/settings_test.go +++ b/receiver/scraperhelper/config_test.go @@ -15,22 +15,22 @@ func TestScrapeControllerSettings(t *testing.T) { for _, tc := range []struct { name string - set ScraperControllerSettings + set ControllerConfig errVal string }{ { name: "default configuration", - set: NewDefaultScraperControllerSettings(""), + set: NewDefaultControllerConfig(), errVal: "", }, { name: "zero value configuration", - set: ScraperControllerSettings{}, + set: ControllerConfig{}, errVal: `"collection_interval": requires positive value`, }, { name: "invalid timeout", - set: ScraperControllerSettings{ + set: ControllerConfig{ CollectionInterval: time.Minute, Timeout: -1 * time.Minute, }, diff --git a/receiver/scraperhelper/obsreport.go b/receiver/scraperhelper/obsreport.go index 415e090195e..a8ba76b66e7 100644 --- a/receiver/scraperhelper/obsreport.go +++ b/receiver/scraperhelper/obsreport.go @@ -7,19 +7,15 @@ import ( "context" "errors" - "go.opencensus.io/stats" - "go.opencensus.io/tag" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/metric" - sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/trace" "go.uber.org/multierr" "go.uber.org/zap" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configtelemetry" - "go.opentelemetry.io/collector/internal/obsreportconfig" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" "go.opentelemetry.io/collector/receiver" "go.opentelemetry.io/collector/receiver/scrapererror" @@ -34,12 +30,10 @@ type ObsReport struct { level configtelemetry.Level receiverID component.ID scraper component.ID - mutators []tag.Mutator tracer trace.Tracer logger *zap.Logger - useOtelForMetrics bool otelAttrs []attribute.KeyValue scrapedMetricsPoints metric.Int64Counter erroredMetricsPoints metric.Int64Counter @@ -54,32 +48,24 @@ type ObsReportSettings struct { // NewObsReport creates a new ObsReport. func NewObsReport(cfg ObsReportSettings) (*ObsReport, error) { - return newScraper(cfg, obsreportconfig.UseOtelForInternalMetricsfeatureGate.IsEnabled()) + return newScraper(cfg) } -func newScraper(cfg ObsReportSettings, useOtel bool) (*ObsReport, error) { +func newScraper(cfg ObsReportSettings) (*ObsReport, error) { scraper := &ObsReport{ level: cfg.ReceiverCreateSettings.TelemetrySettings.MetricsLevel, receiverID: cfg.ReceiverID, scraper: cfg.Scraper, - mutators: []tag.Mutator{ - tag.Upsert(obsmetrics.TagKeyReceiver, cfg.ReceiverID.String(), tag.WithTTL(tag.TTLNoPropagation)), - tag.Upsert(obsmetrics.TagKeyScraper, cfg.Scraper.String(), tag.WithTTL(tag.TTLNoPropagation))}, - tracer: cfg.ReceiverCreateSettings.TracerProvider.Tracer(cfg.Scraper.String()), + tracer: cfg.ReceiverCreateSettings.TracerProvider.Tracer(cfg.Scraper.String()), - logger: cfg.ReceiverCreateSettings.Logger, - useOtelForMetrics: useOtel, + logger: cfg.ReceiverCreateSettings.Logger, otelAttrs: []attribute.KeyValue{ attribute.String(obsmetrics.ReceiverKey, cfg.ReceiverID.String()), attribute.String(obsmetrics.ScraperKey, cfg.Scraper.String()), }, } - // ignore instrument name error as per workaround in https://github.com/open-telemetry/opentelemetry-collector/issues/8346 - // if err := scraper.createOtelMetrics(cfg); err != nil { - // return nil, err - // } - if err := scraper.createOtelMetrics(cfg); err != nil && !errors.Is(err, sdkmetric.ErrInstrumentName) { + if err := scraper.createOtelMetrics(cfg); err != nil { return nil, err } @@ -87,9 +73,6 @@ func newScraper(cfg ObsReportSettings, useOtel bool) (*ObsReport, error) { } func (s *ObsReport) createOtelMetrics(cfg ObsReportSettings) error { - if !s.useOtelForMetrics { - return nil - } meter := cfg.ReceiverCreateSettings.MeterProvider.Meter(scraperScope) var errors, err error @@ -115,8 +98,6 @@ func (s *ObsReport) createOtelMetrics(cfg ObsReportSettings) error { // returned context should be used in other calls to the obsreport functions // dealing with the same scrape operation. func (s *ObsReport) StartMetricsOp(ctx context.Context) context.Context { - ctx, _ = tag.New(ctx, s.mutators...) - spanName := obsmetrics.ScraperPrefix + s.receiverID.String() + obsmetrics.NameSep + s.scraper.String() + obsmetrics.ScraperMetricsOperationSuffix ctx, _ = s.tracer.Start(ctx, spanName) return ctx @@ -149,7 +130,7 @@ func (s *ObsReport) EndMetricsOp( // end span according to errors if span.IsRecording() { span.SetAttributes( - attribute.String(obsmetrics.FormatKey, string(component.DataTypeMetrics)), + attribute.String(obsmetrics.FormatKey, component.DataTypeMetrics.String()), attribute.Int64(obsmetrics.ScrapedMetricPointsKey, int64(numScrapedMetrics)), attribute.Int64(obsmetrics.ErroredMetricPointsKey, int64(numErroredMetrics)), ) @@ -163,13 +144,6 @@ func (s *ObsReport) EndMetricsOp( } func (s *ObsReport) recordMetrics(scraperCtx context.Context, numScrapedMetrics, numErroredMetrics int) { - if s.useOtelForMetrics { - s.scrapedMetricsPoints.Add(scraperCtx, int64(numScrapedMetrics), metric.WithAttributes(s.otelAttrs...)) - s.erroredMetricsPoints.Add(scraperCtx, int64(numErroredMetrics), metric.WithAttributes(s.otelAttrs...)) - } else { // OC for metrics - stats.Record( - scraperCtx, - obsmetrics.ScraperScrapedMetricPoints.M(int64(numScrapedMetrics)), - obsmetrics.ScraperErroredMetricPoints.M(int64(numErroredMetrics))) - } + s.scrapedMetricsPoints.Add(scraperCtx, int64(numScrapedMetrics), metric.WithAttributes(s.otelAttrs...)) + s.erroredMetricsPoints.Add(scraperCtx, int64(numErroredMetrics), metric.WithAttributes(s.otelAttrs...)) } diff --git a/receiver/scraperhelper/obsreport_test.go b/receiver/scraperhelper/obsreport_test.go index 0ca828c77cb..6ccbc8041cd 100644 --- a/receiver/scraperhelper/obsreport_test.go +++ b/receiver/scraperhelper/obsreport_test.go @@ -14,15 +14,15 @@ import ( "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" - "go.opentelemetry.io/collector/obsreport/obsreporttest" - "go.opentelemetry.io/collector/receiver/receivertest" + "go.opentelemetry.io/collector/receiver" "go.opentelemetry.io/collector/receiver/scrapererror" ) var ( - receiverID = component.NewID("fakeReceiver") - scraperID = component.NewID("fakeScraper") + receiverID = component.MustNewID("fakeReceiver") + scraperID = component.MustNewID("fakeScraper") errFake = errors.New("errFake") partialErrFake = scrapererror.NewPartialScrapeError(errFake, 1) @@ -34,8 +34,8 @@ type testParams struct { } func TestScrapeMetricsDataOp(t *testing.T) { - testTelemetry(t, receiverID, func(t *testing.T, tt obsreporttest.TestTelemetry, useOtel bool) { - parentCtx, parentSpan := tt.TracerProvider.Tracer("test").Start(context.Background(), t.Name()) + testTelemetry(t, receiverID, func(t *testing.T, tt componenttest.TestTelemetry) { + parentCtx, parentSpan := tt.TelemetrySettings().TracerProvider.Tracer("test").Start(context.Background(), t.Name()) defer parentSpan.End() params := []testParams{ @@ -47,8 +47,8 @@ func TestScrapeMetricsDataOp(t *testing.T) { scrp, err := newScraper(ObsReportSettings{ ReceiverID: receiverID, Scraper: scraperID, - ReceiverCreateSettings: receivertest.NewCreateSettings(receiverID, tt.TelemetrySettings), - }, useOtel) + ReceiverCreateSettings: receiver.CreateSettings{ID: receiverID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, + }) require.NoError(t, err) ctx := scrp.StartMetricsOp(parentCtx) assert.NotNil(t, ctx) @@ -86,24 +86,37 @@ func TestScrapeMetricsDataOp(t *testing.T) { } } - require.NoError(t, obsreporttest.CheckScraperMetrics(tt, receiverID, scraperID, int64(scrapedMetricPoints), int64(erroredMetricPoints))) + require.NoError(t, tt.CheckScraperMetrics(receiverID, scraperID, int64(scrapedMetricPoints), int64(erroredMetricPoints))) }) } -func testTelemetry(t *testing.T, id component.ID, testFunc func(t *testing.T, tt obsreporttest.TestTelemetry, useOtel bool)) { - t.Run("WithOC", func(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(id) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) +func TestCheckScraperMetricsViews(t *testing.T) { + tt, err := componenttest.SetupTelemetry(receiverID) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - testFunc(t, tt, false) + s, err := NewObsReport(ObsReportSettings{ + ReceiverID: receiverID, + Scraper: scraperID, + ReceiverCreateSettings: receiver.CreateSettings{ID: receiverID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, }) + require.NoError(t, err) + ctx := s.StartMetricsOp(context.Background()) + require.NotNil(t, ctx) + s.EndMetricsOp(ctx, 7, nil) + + assert.NoError(t, tt.CheckScraperMetrics(receiverID, scraperID, 7, 0)) + assert.Error(t, tt.CheckScraperMetrics(receiverID, scraperID, 7, 7)) + assert.Error(t, tt.CheckScraperMetrics(receiverID, scraperID, 0, 0)) + assert.Error(t, tt.CheckScraperMetrics(receiverID, scraperID, 0, 7)) +} +func testTelemetry(t *testing.T, id component.ID, testFunc func(t *testing.T, tt componenttest.TestTelemetry)) { t.Run("WithOTel", func(t *testing.T) { - tt, err := obsreporttest.SetupTelemetry(id) + tt, err := componenttest.SetupTelemetry(id) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - testFunc(t, tt, true) + testFunc(t, tt) }) } diff --git a/receiver/scraperhelper/package_test.go b/receiver/scraperhelper/package_test.go new file mode 100644 index 00000000000..a9a536a78d9 --- /dev/null +++ b/receiver/scraperhelper/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package scraperhelper + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/receiver/scraperhelper/scraper.go b/receiver/scraperhelper/scraper.go index 70bfe099d3a..f97eb65a403 100644 --- a/receiver/scraperhelper/scraper.go +++ b/receiver/scraperhelper/scraper.go @@ -67,7 +67,7 @@ func NewScraper(name string, scrape ScrapeFunc, options ...ScraperOption) (Scrap } bs := &baseScraper{ ScrapeFunc: scrape, - id: component.NewID(component.Type(name)), + id: component.NewID(component.MustNewType(name)), } for _, op := range options { op(bs) diff --git a/receiver/scraperhelper/scrapercontroller.go b/receiver/scraperhelper/scrapercontroller.go index fb6da0a3ddf..2f2896f6903 100644 --- a/receiver/scraperhelper/scrapercontroller.go +++ b/receiver/scraperhelper/scrapercontroller.go @@ -65,14 +65,11 @@ type controller struct { // NewScraperControllerReceiver creates a Receiver with the configured options, that can control multiple scrapers. func NewScraperControllerReceiver( - cfg *ScraperControllerSettings, + cfg *ControllerConfig, set receiver.CreateSettings, nextConsumer consumer.Metrics, options ...ScraperControllerOption, ) (component.Component, error) { - if nextConsumer == nil { - return nil, component.ErrNilNextConsumer - } if cfg.CollectionInterval <= 0 { return nil, errors.New("collection_interval must be a positive duration") diff --git a/receiver/scraperhelper/scrapercontroller_test.go b/receiver/scraperhelper/scrapercontroller_test.go index 1340af2bba7..1c41258ff18 100644 --- a/receiver/scraperhelper/scrapercontroller_test.go +++ b/receiver/scraperhelper/scrapercontroller_test.go @@ -17,10 +17,9 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" - "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" - "go.opentelemetry.io/collector/obsreport/obsreporttest" "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/receiver" "go.opentelemetry.io/collector/receiver/receivertest" "go.opentelemetry.io/collector/receiver/scrapererror" ) @@ -51,7 +50,7 @@ type testScrapeMetrics struct { err error } -func (ts *testScrapeMetrics) scrape(_ context.Context) (pmetric.Metrics, error) { +func (ts *testScrapeMetrics) scrape(context.Context) (pmetric.Metrics, error) { ts.timesScrapeCalled++ ts.ch <- ts.timesScrapeCalled @@ -64,8 +63,8 @@ func (ts *testScrapeMetrics) scrape(_ context.Context) (pmetric.Metrics, error) return md, nil } -func newTestNoDelaySettings() *ScraperControllerSettings { - return &ScraperControllerSettings{ +func newTestNoDelaySettings() *ControllerConfig { + return &ControllerConfig{ CollectionInterval: time.Second, InitialDelay: 0, } @@ -75,8 +74,7 @@ type metricsTestCase struct { name string scrapers int - scraperControllerSettings *ScraperControllerSettings - nilNextConsumer bool + scraperControllerSettings *ControllerConfig scrapeErr error expectedNewErr string expectScraped bool @@ -97,16 +95,10 @@ func TestScrapeController(t *testing.T) { scrapers: 2, expectScraped: true, }, - { - name: "AddMetricsScrapers_NilNextConsumerError", - scrapers: 2, - nilNextConsumer: true, - expectedNewErr: "nil next Consumer", - }, { name: "AddMetricsScrapersWithCollectionInterval_InvalidCollectionIntervalError", scrapers: 2, - scraperControllerSettings: &ScraperControllerSettings{CollectionInterval: -time.Millisecond}, + scraperControllerSettings: &ControllerConfig{CollectionInterval: -time.Millisecond}, expectedNewErr: "collection_interval must be a positive duration", }, { @@ -134,8 +126,8 @@ func TestScrapeController(t *testing.T) { for _, test := range testCases { test := test t.Run(test.name, func(t *testing.T) { - receiverID := component.NewID("receiver") - tt, err := obsreporttest.SetupTelemetry(receiverID) + receiverID := component.MustNewID("receiver") + tt, err := componenttest.SetupTelemetry(receiverID) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) @@ -147,17 +139,13 @@ func TestScrapeController(t *testing.T) { tickerCh := make(chan time.Time) options = append(options, WithTickerChannel(tickerCh)) - var nextConsumer consumer.Metrics sink := new(consumertest.MetricsSink) - if !test.nilNextConsumer { - nextConsumer = sink - } cfg := newTestNoDelaySettings() if test.scraperControllerSettings != nil { cfg = test.scraperControllerSettings } - mr, err := NewScraperControllerReceiver(cfg, receivertest.NewCreateSettings(receiverID, tt.TelemetrySettings), nextConsumer, options...) + mr, err := NewScraperControllerReceiver(cfg, receiver.CreateSettings{ID: receiverID, TelemetrySettings: tt.TelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo()}, sink, options...) if test.expectedNewErr != "" { assert.EqualError(t, err, test.expectedNewErr) return @@ -285,7 +273,7 @@ func assertReceiverSpan(t *testing.T, spans []sdktrace.ReadOnlySpan) { assert.True(t, receiverSpan) } -func assertReceiverViews(t *testing.T, tt obsreporttest.TestTelemetry, sink *consumertest.MetricsSink) { +func assertReceiverViews(t *testing.T, tt componenttest.TestTelemetry, sink *consumertest.MetricsSink) { dataPointCount := 0 for _, md := range sink.AllMetrics() { dataPointCount += md.DataPointCount() @@ -313,7 +301,7 @@ func assertScraperSpan(t *testing.T, expectedErr error, spans []sdktrace.ReadOnl assert.True(t, scraperSpan) } -func assertScraperViews(t *testing.T, tt obsreporttest.TestTelemetry, expectedErr error, sink *consumertest.MetricsSink) { +func assertScraperViews(t *testing.T, tt componenttest.TestTelemetry, expectedErr error, sink *consumertest.MetricsSink) { expectedScraped := int64(sink.DataPointCount()) expectedErrored := int64(0) if expectedErr != nil { @@ -326,7 +314,7 @@ func assertScraperViews(t *testing.T, tt obsreporttest.TestTelemetry, expectedEr } } - require.NoError(t, obsreporttest.CheckScraperMetrics(tt, component.NewID("receiver"), component.NewID("scraper"), expectedScraped, expectedErrored)) + require.NoError(t, tt.CheckScraperMetrics(component.MustNewID("receiver"), component.MustNewID("scraper"), expectedScraped, expectedErrored)) } func TestSingleScrapePerInterval(t *testing.T) { @@ -337,7 +325,7 @@ func TestSingleScrapePerInterval(t *testing.T) { tickerCh := make(chan time.Time) - scp, err := NewScraper("", tsm.scrape) + scp, err := NewScraper("scaper", tsm.scrape) assert.NoError(t, err) receiver, err := NewScraperControllerReceiver( @@ -350,6 +338,7 @@ func TestSingleScrapePerInterval(t *testing.T) { require.NoError(t, err) require.NoError(t, receiver.Start(context.Background(), componenttest.NewNopHost())) + defer func() { require.NoError(t, receiver.Shutdown(context.Background())) }() tickerCh <- time.Now() @@ -378,11 +367,11 @@ func TestScrapeControllerStartsOnInit(t *testing.T) { ch: make(chan int, 1), } - scp, err := NewScraper("", tsm.scrape) + scp, err := NewScraper("scraper", tsm.scrape) require.NoError(t, err, "Must not error when creating scraper") r, err := NewScraperControllerReceiver( - &ScraperControllerSettings{ + &ControllerConfig{ CollectionInterval: time.Hour, InitialDelay: 0, }, @@ -408,13 +397,13 @@ func TestScrapeControllerInitialDelay(t *testing.T) { var ( elapsed = make(chan time.Time, 1) - cfg = ScraperControllerSettings{ + cfg = ControllerConfig{ CollectionInterval: time.Second, InitialDelay: 300 * time.Millisecond, } ) - scp, err := NewScraper("timed", func(ctx context.Context) (pmetric.Metrics, error) { + scp, err := NewScraper("timed", func(context.Context) (pmetric.Metrics, error) { elapsed <- time.Now() return pmetric.NewMetrics(), nil }) diff --git a/renovate.json b/renovate.json index df04fb36693..9f645452830 100644 --- a/renovate.json +++ b/renovate.json @@ -1,13 +1,26 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "labels": [ + "renovatebot", "dependencies" ], - "extends": [ - "config:base" - ], + "constraints": { + "go": "1.21" + }, + "extends": ["config:recommended"], "schedule": ["every tuesday"], "packageRules": [ + { + "matchManagers": ["gomod"], + "matchUpdateTypes": ["pin", "pinDigest", "digest", "lockFileMaintenance", "rollback", "bump", "replacement"], + "enabled": false + }, + { + "matchManagers": ["gomod"], + "matchUpdateTypes": ["major"], + "prBodyNotes": [":warning: MAJOR VERSION UPDATE :warning: - please manually update this package"], + "labels": ["dependency-major-update"] + }, { "matchManagers": ["dockerfile"], "groupName": "dockerfile deps" @@ -22,10 +35,28 @@ }, { "matchManagers": ["gomod"], - "matchUpdateTypes": ["minor", "major"] + "matchSourceUrlPrefixes": ["https://go.opentelemetry.io/contrib"], + "groupName": "All go.opentelemetry.io/contrib packages" + }, + { + "matchManagers": ["gomod"], + "matchSourceUrlPrefixes": ["https://go.opentelemetry.io/otel"], + "groupName": "All go.opentelemetry.io/contrib packages" + }, + { + "matchManagers": ["gomod"], + "matchSourceUrlPrefixes": ["https://google.golang.org"], + "groupName": "All google.golang.org packages" + }, + { + "matchManagers": ["gomod"], + "matchSourceUrlPrefixes": ["https://golang.org"], + "groupName": "All golang.org packages" } ], "ignoreDeps": [ "github.com/mattn/go-ieproxy" - ] + ], + "prConcurrentLimit": 200, + "suppressNotifications": ["prEditedNotification"] } diff --git a/semconv/README.md b/semconv/README.md index dcbcc71c797..a453bbafd27 100644 --- a/semconv/README.md +++ b/semconv/README.md @@ -6,17 +6,13 @@ from definitions in the specification. ## Generation To generate the constants you can use the `gensemconv` make target. You must provide the path to the root of a clone of -the `opentelemetry-specification` repository in the `SPECPATH` variable and the version of the conventions to generate +the `semantic-conventions` repository in the `SPECPATH` variable and the version of the conventions to generate in the `SPECTAG` variable. ```console -$ make gensemconv SPECPATH=~/dev/opentelemetry-specification SPECTAG=v1.5.0 -Generating semantic convention constants from specification version v1.5.0 at ~/dev/opentelemetry-specification -semconvgen -o semconv/v1.5.0 -t semconv/template.j2 -s v1.5.0 -i ~/dev/opentelemetry-specification/semantic_conventions/resource -p conventionType=resource -semconvgen -o semconv/v1.5.0 -t semconv/template.j2 -s v1.5.0 -i ~/dev/opentelemetry-specification/semantic_conventions/trace -p conventionType=trace +$ make gensemconv SPECPATH=/tmp/semantic-conventions SPECTAG=v1.22.0 +Generating semantic convention constants from specification version v1.22.0 at /tmp/semantic-conventions +.tools/semconvgen -o semconv/v1.22.0 -t semconv/template.j2 -s v1.22.0 -i /tmp/semantic-conventions/model/. --only=resource -p conventionType=resource -f generated_resource.go +.tools/semconvgen -o semconv/v1.22.0 -t semconv/template.j2 -s v1.22.0 -i /tmp/semantic-conventions/model/. --only=event -p conventionType=event -f generated_event.go +.tools/semconvgen -o semconv/v1.22.0 -t semconv/template.j2 -s v1.22.0 -i /tmp/semantic-conventions/model/. --only=span -p conventionType=trace -f generated_trace.go ``` - -When generating the constants for a new version ot the specification it is important to note that only -`generated_trace.go` and `generated_resource.go` are generated automatically. The `schema.go` and `nonstandard.go` -files should be copied from a prior version's package and updated as appropriate. Most important will be to update -the `SchemaURL` constant in `schema.go`. diff --git a/semconv/go.mod b/semconv/go.mod index d5dd356474c..6f758cc6751 100644 --- a/semconv/go.mod +++ b/semconv/go.mod @@ -1,10 +1,11 @@ module go.opentelemetry.io/collector/semconv -go 1.20 +go 1.21 require ( github.com/hashicorp/go-version v1.6.0 github.com/stretchr/testify v1.8.4 + go.uber.org/goleak v1.3.0 ) require ( diff --git a/semconv/go.sum b/semconv/go.sum index 58b69a26f3e..8ca3cb9177c 100644 --- a/semconv/go.sum +++ b/semconv/go.sum @@ -18,6 +18,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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/semconv/package_test.go b/semconv/package_test.go new file mode 100644 index 00000000000..ca832817aef --- /dev/null +++ b/semconv/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package semconv + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/semconv/template.j2 b/semconv/template.j2 index 4d614187849..a91e8a554c4 100644 --- a/semconv/template.j2 +++ b/semconv/template.j2 @@ -36,6 +36,9 @@ Examples: {{ attr.examples | pprint | trim("[]") }} Note: {{ attr.note | render_markdown(paragraph="{0}", code="{0}", link="{1}", emphasis="{0}", strong="{0}") }} {%- endif %} {%- endmacro -%} +{%- macro sentence_case(text) -%} + {{ text[0]|upper}}{{text[1:] }} +{%- endmacro -%} // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 @@ -45,7 +48,7 @@ package semconv {% for semconv in semconvs -%} {%- if semconvs[semconv].attributes | rejectattr("ref") | selectattr("is_local") | sort(attribute=fqn) | length > 0 -%} -// {{ semconvs[semconv].brief }} +// {{ sentence_case(semconvs[semconv].brief | replace("This document defines ", "")) | wordwrap(76, break_long_words=false, break_on_hyphens=false, wrapstring="\n// ") }} const ( {% for attr in semconvs[semconv].attributes if attr.is_local and not attr.ref -%} // {{ godoc(attr) | wordwrap | indent(3) | replace(" ", "\t// ") | replace("// //", "//") }} diff --git a/semconv/v1.21.0/doc.go b/semconv/v1.21.0/doc.go new file mode 100644 index 00000000000..a189e79efbc --- /dev/null +++ b/semconv/v1.21.0/doc.go @@ -0,0 +1,9 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package semconv implements OpenTelemetry semantic conventions. +// +// OpenTelemetry semantic conventions are agreed standardized naming +// patterns for OpenTelemetry things. This package represents the v1.21.0 +// version of the OpenTelemetry semantic conventions. +package semconv // import "go.opentelemetry.io/collector/semconv/v1.21.0" diff --git a/semconv/v1.21.0/generated_event.go b/semconv/v1.21.0/generated_event.go new file mode 100644 index 00000000000..ec6c733ecd4 --- /dev/null +++ b/semconv/v1.21.0/generated_event.go @@ -0,0 +1,119 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Code generated from semantic convention specification. DO NOT EDIT. + +package semconv + +// This semantic convention defines the attributes used to represent a feature +// flag evaluation as an event. +const ( + // The unique identifier of the feature flag. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'logo-color' + AttributeFeatureFlagKey = "feature_flag.key" + // The name of the service provider that performs the flag evaluation. + // + // Type: string + // Requirement Level: Recommended + // Stability: experimental + // Examples: 'Flag Manager' + AttributeFeatureFlagProviderName = "feature_flag.provider_name" + // SHOULD be a semantic identifier for a value. If one is unavailable, a + // stringified version of the value can be used. + // + // Type: string + // Requirement Level: Recommended + // Stability: experimental + // Examples: 'red', 'true', 'on' + // Note: A semantic identifier, commonly referred to as a variant, provides a + // means + // for referring to a value without including the value itself. This can + // provide additional context for understanding the meaning behind a value. + // For example, the variant red maybe be used for the value #c05543.A stringified + // version of the value can be used in situations where a + // semantic identifier is unavailable. String representation of the value + // should be determined by the implementer. + AttributeFeatureFlagVariant = "feature_flag.variant" +) + +// RPC received/sent message. +const ( + // Compressed size of the message in bytes. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + AttributeMessageCompressedSize = "message.compressed_size" + // MUST be calculated as two different counters starting from 1 one for sent + // messages and one for received message. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Note: This way we guarantee that the values will be consistent between + // different implementations. + AttributeMessageID = "message.id" + // Whether this is a received or sent message. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeMessageType = "message.type" + // Uncompressed size of the message in bytes. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + AttributeMessageUncompressedSize = "message.uncompressed_size" +) + +const ( + // sent + AttributeMessageTypeSent = "SENT" + // received + AttributeMessageTypeReceived = "RECEIVED" +) + +// The attributes used to report a single exception associated with a span. +const ( + // SHOULD be set to true if the exception event is recorded at a point where it is + // known that the exception is escaping the scope of the span. + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + // Note: An exception is considered to have escaped (or left) the scope of a span, + // if that span is ended while the exception is still logically "in + // flight". + // This may be actually "in flight" in some languages (e.g. if the + // exception + // is passed to a Context manager's __exit__ method in Python) but will + // usually be caught at the point of recording the exception in most languages.It + // is usually not possible to determine at the point where an exception is thrown + // whether it will escape the scope of a span. + // However, it is trivial to know that an exception + // will escape, if one checks for an active exception just before ending the span, + // as done in the example above.It follows that an exception may still escape the + // scope of the span + // even if the exception.escaped attribute was not set or set to false, + // since the event might have been recorded at a time where it was not + // clear whether the exception will escape. + AttributeExceptionEscaped = "exception.escaped" +) + +func GetEventSemanticConventionAttributeNames() []string { + return []string{ + AttributeFeatureFlagKey, + AttributeFeatureFlagProviderName, + AttributeFeatureFlagVariant, + AttributeMessageCompressedSize, + AttributeMessageID, + AttributeMessageType, + AttributeMessageUncompressedSize, + AttributeExceptionEscaped, + } +} diff --git a/semconv/v1.21.0/generated_resource.go b/semconv/v1.21.0/generated_resource.go new file mode 100644 index 00000000000..b1a66142afe --- /dev/null +++ b/semconv/v1.21.0/generated_resource.go @@ -0,0 +1,1342 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Code generated from semantic convention specification. DO NOT EDIT. + +package semconv + +// The web browser in which the application represented by the resource is +// running. The `browser.*` attributes MUST be used only for resources that +// represent applications running in a web browser (regardless of whether +// running on a mobile or desktop device). +const ( + // Array of brand name and version separated by a space + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: ' Not A;Brand 99', 'Chromium 99', 'Chrome 99' + // Note: This value is intended to be taken from the UA client hints API + // (navigator.userAgentData.brands). + AttributeBrowserBrands = "browser.brands" + // Preferred language of the user using the browser + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'en', 'en-US', 'fr', 'fr-FR' + // Note: This value is intended to be taken from the Navigator API + // navigator.language. + AttributeBrowserLanguage = "browser.language" + // A boolean that is true if the browser is running on a mobile device + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + // Note: This value is intended to be taken from the UA client hints API + // (navigator.userAgentData.mobile). If unavailable, this attribute SHOULD be left + // unset. + AttributeBrowserMobile = "browser.mobile" + // The platform on which the browser is running + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Windows', 'macOS', 'Android' + // Note: This value is intended to be taken from the UA client hints API + // (navigator.userAgentData.platform). If unavailable, the legacy + // navigator.platform API SHOULD NOT be used instead and this attribute SHOULD be + // left unset in order for the values to be consistent. + // The list of possible values is defined in the W3C User-Agent Client Hints + // specification. Note that some (but not all) of these values can overlap with + // values in the os.type and os.name attributes. However, for consistency, the + // values in the browser.platform attribute should capture the exact value that + // the user agent provides. + AttributeBrowserPlatform = "browser.platform" +) + +// A cloud environment (e.g. GCP, Azure, AWS) +const ( + // The cloud account ID the resource is assigned to. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '111111111111', 'opentelemetry' + AttributeCloudAccountID = "cloud.account.id" + // Cloud regions often have multiple, isolated locations known as zones to + // increase availability. Availability zone represents the zone where the resource + // is running. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'us-east-1c' + // Note: Availability zones are called "zones" on Alibaba Cloud and + // Google Cloud. + AttributeCloudAvailabilityZone = "cloud.availability_zone" + // The cloud platform in use. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Note: The prefix of the service SHOULD match the one specified in + // cloud.provider. + AttributeCloudPlatform = "cloud.platform" + // Name of the cloud provider. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeCloudProvider = "cloud.provider" + // The geographical region the resource is running. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'us-central1', 'us-east-1' + // Note: Refer to your provider's docs to see the available regions, for example + // Alibaba Cloud regions, AWS regions, Azure regions, Google Cloud regions, or + // Tencent Cloud regions. + AttributeCloudRegion = "cloud.region" + // Cloud provider-specific native identifier of the monitored cloud resource (e.g. + // an ARN on AWS, a fully qualified resource ID on Azure, a full resource name on + // GCP) + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:lambda:REGION:ACCOUNT_ID:function:my-function', '//run.googl + // eapis.com/projects/PROJECT_ID/locations/LOCATION_ID/services/SERVICE_ID', '/sub + // scriptions//resourceGroups//providers/Microsoft.Web/sites + // //functions/' + // Note: On some cloud providers, it may not be possible to determine the full ID + // at startup, + // so it may be necessary to set cloud.resource_id as a span attribute instead.The + // exact value to use for cloud.resource_id depends on the cloud provider. + // The following well-known definitions MUST be used if you set this attribute and + // they apply:
    + //
  • AWS Lambda: The function ARN. + // Take care not to use the "invoked ARN" directly but replace any + // alias suffix + // with the resolved function version, as the same runtime instance may be + // invokable with + // multiple different aliases.
  • + //
  • GCP: The URI of the resource
  • + //
  • Azure: The Fully Qualified Resource ID of the invoked function, + // not the function app, having the form + // /subscriptions//resourceGroups//providers/Microsoft.Web/s + // ites//functions/. + // This means that a span attribute MUST be used, as an Azure function app can + // host multiple functions that would usually share + // a TracerProvider.
  • + //
+ AttributeCloudResourceID = "cloud.resource_id" +) + +const ( + // Alibaba Cloud Elastic Compute Service + AttributeCloudPlatformAlibabaCloudECS = "alibaba_cloud_ecs" + // Alibaba Cloud Function Compute + AttributeCloudPlatformAlibabaCloudFc = "alibaba_cloud_fc" + // Red Hat OpenShift on Alibaba Cloud + AttributeCloudPlatformAlibabaCloudOpenshift = "alibaba_cloud_openshift" + // AWS Elastic Compute Cloud + AttributeCloudPlatformAWSEC2 = "aws_ec2" + // AWS Elastic Container Service + AttributeCloudPlatformAWSECS = "aws_ecs" + // AWS Elastic Kubernetes Service + AttributeCloudPlatformAWSEKS = "aws_eks" + // AWS Lambda + AttributeCloudPlatformAWSLambda = "aws_lambda" + // AWS Elastic Beanstalk + AttributeCloudPlatformAWSElasticBeanstalk = "aws_elastic_beanstalk" + // AWS App Runner + AttributeCloudPlatformAWSAppRunner = "aws_app_runner" + // Red Hat OpenShift on AWS (ROSA) + AttributeCloudPlatformAWSOpenshift = "aws_openshift" + // Azure Virtual Machines + AttributeCloudPlatformAzureVM = "azure_vm" + // Azure Container Instances + AttributeCloudPlatformAzureContainerInstances = "azure_container_instances" + // Azure Kubernetes Service + AttributeCloudPlatformAzureAKS = "azure_aks" + // Azure Functions + AttributeCloudPlatformAzureFunctions = "azure_functions" + // Azure App Service + AttributeCloudPlatformAzureAppService = "azure_app_service" + // Azure Red Hat OpenShift + AttributeCloudPlatformAzureOpenshift = "azure_openshift" + // Google Bare Metal Solution (BMS) + AttributeCloudPlatformGCPBareMetalSolution = "gcp_bare_metal_solution" + // Google Cloud Compute Engine (GCE) + AttributeCloudPlatformGCPComputeEngine = "gcp_compute_engine" + // Google Cloud Run + AttributeCloudPlatformGCPCloudRun = "gcp_cloud_run" + // Google Cloud Kubernetes Engine (GKE) + AttributeCloudPlatformGCPKubernetesEngine = "gcp_kubernetes_engine" + // Google Cloud Functions (GCF) + AttributeCloudPlatformGCPCloudFunctions = "gcp_cloud_functions" + // Google Cloud App Engine (GAE) + AttributeCloudPlatformGCPAppEngine = "gcp_app_engine" + // Red Hat OpenShift on Google Cloud + AttributeCloudPlatformGCPOpenshift = "gcp_openshift" + // Red Hat OpenShift on IBM Cloud + AttributeCloudPlatformIbmCloudOpenshift = "ibm_cloud_openshift" + // Tencent Cloud Cloud Virtual Machine (CVM) + AttributeCloudPlatformTencentCloudCvm = "tencent_cloud_cvm" + // Tencent Cloud Elastic Kubernetes Service (EKS) + AttributeCloudPlatformTencentCloudEKS = "tencent_cloud_eks" + // Tencent Cloud Serverless Cloud Function (SCF) + AttributeCloudPlatformTencentCloudScf = "tencent_cloud_scf" +) + +const ( + // Alibaba Cloud + AttributeCloudProviderAlibabaCloud = "alibaba_cloud" + // Amazon Web Services + AttributeCloudProviderAWS = "aws" + // Microsoft Azure + AttributeCloudProviderAzure = "azure" + // Google Cloud Platform + AttributeCloudProviderGCP = "gcp" + // Heroku Platform as a Service + AttributeCloudProviderHeroku = "heroku" + // IBM Cloud + AttributeCloudProviderIbmCloud = "ibm_cloud" + // Tencent Cloud + AttributeCloudProviderTencentCloud = "tencent_cloud" +) + +// Resources used by AWS Elastic Container Service (ECS). +const ( + // The ARN of an ECS cluster. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster' + AttributeAWSECSClusterARN = "aws.ecs.cluster.arn" + // The Amazon Resource Name (ARN) of an ECS container instance. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:ecs:us- + // west-1:123456789123:container/32624152-9086-4f0e-acae-1a75b14fe4d9' + AttributeAWSECSContainerARN = "aws.ecs.container.arn" + // The launch type for an ECS task. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeAWSECSLaunchtype = "aws.ecs.launchtype" + // The ARN of an ECS task definition. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:ecs:us- + // west-1:123456789123:task/10838bed-421f-43ef-870a-f43feacbbb5b' + AttributeAWSECSTaskARN = "aws.ecs.task.arn" + // The task definition family this task definition is a member of. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry-family' + AttributeAWSECSTaskFamily = "aws.ecs.task.family" + // The revision for this task definition. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '8', '26' + AttributeAWSECSTaskRevision = "aws.ecs.task.revision" +) + +const ( + // ec2 + AttributeAWSECSLaunchtypeEC2 = "ec2" + // fargate + AttributeAWSECSLaunchtypeFargate = "fargate" +) + +// Resources used by AWS Elastic Kubernetes Service (EKS). +const ( + // The ARN of an EKS cluster. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster' + AttributeAWSEKSClusterARN = "aws.eks.cluster.arn" +) + +// Resources specific to Amazon Web Services. +const ( + // The Amazon Resource Name(s) (ARN) of the AWS log group(s). + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:*' + // Note: See the log group ARN format documentation. + AttributeAWSLogGroupARNs = "aws.log.group.arns" + // The name(s) of the AWS log group(s) an application is writing to. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: '/aws/lambda/my-function', 'opentelemetry-service' + // Note: Multiple log groups must be supported for cases like multi-container + // applications, where a single application has sidecar containers, and each write + // to their own log group. + AttributeAWSLogGroupNames = "aws.log.group.names" + // The ARN(s) of the AWS log stream(s). + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:log- + // stream:logs/main/10838bed-421f-43ef-870a-f43feacbbb5b' + // Note: See the log stream ARN format documentation. One log group can contain + // several log streams, so these ARNs necessarily identify both a log group and a + // log stream. + AttributeAWSLogStreamARNs = "aws.log.stream.arns" + // The name(s) of the AWS log stream(s) an application is writing to. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'logs/main/10838bed-421f-43ef-870a-f43feacbbb5b' + AttributeAWSLogStreamNames = "aws.log.stream.names" +) + +// Resource used by Google Cloud Run. +const ( + // The name of the Cloud Run execution being run for the Job, as set by the + // CLOUD_RUN_EXECUTION environment variable. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'job-name-xxxx', 'sample-job-mdw84' + AttributeGCPCloudRunJobExecution = "gcp.cloud_run.job.execution" + // The index for a task within an execution as provided by the + // CLOUD_RUN_TASK_INDEX environment variable. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 0, 1 + AttributeGCPCloudRunJobTaskIndex = "gcp.cloud_run.job.task_index" +) + +// Resources used by Google Compute Engine (GCE). +const ( + // The hostname of a GCE instance. This is the full value of the default or custom + // hostname. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'my-host1234.example.com', 'sample-vm.us-west1-b.c.my- + // project.internal' + AttributeGCPGceInstanceHostname = "gcp.gce.instance.hostname" + // The instance name of a GCE instance. This is the value provided by host.name, + // the visible name of the instance in the Cloud Console UI, and the prefix for + // the default hostname of the instance as defined by the default internal DNS + // name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'instance-1', 'my-vm-name' + AttributeGCPGceInstanceName = "gcp.gce.instance.name" +) + +// Heroku dyno metadata +const ( + // Unique identifier for the application + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2daa2797-e42b-4624-9322-ec3f968df4da' + AttributeHerokuAppID = "heroku.app.id" + // Commit hash for the current release + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'e6134959463efd8966b20e75b913cafe3f5ec' + AttributeHerokuReleaseCommit = "heroku.release.commit" + // Time and date the release was created + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2022-10-23T18:00:42Z' + AttributeHerokuReleaseCreationTimestamp = "heroku.release.creation_timestamp" +) + +// A container instance. +const ( + // The command used to run the container (i.e. the command name). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'otelcontribcol' + // Note: If using embedded credentials or sensitive data, it is recommended to + // remove them to prevent potential leakage. + AttributeContainerCommand = "container.command" + // All the command arguments (including the command/executable itself) run by the + // container. [2] + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'otelcontribcol, --config, config.yaml' + AttributeContainerCommandArgs = "container.command_args" + // The full command run by the container as a single string representing the full + // command. [2] + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'otelcontribcol --config config.yaml' + AttributeContainerCommandLine = "container.command_line" + // Container ID. Usually a UUID, as for example used to identify Docker + // containers. The UUID might be abbreviated. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'a3bf90e006b2' + AttributeContainerID = "container.id" + // Runtime specific image identifier. Usually a hash algorithm followed by a UUID. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: + // 'sha256:19c92d0a00d1b66d897bceaa7319bee0dd38a10a851c60bcec9474aa3f01e50f' + // Note: Docker defines a sha256 of the image id; container.image.id corresponds + // to the Image field from the Docker container inspect API endpoint. + // K8S defines a link to the container registry repository with digest "imageID": + // "registry.azurecr.io /namespace/service/dockerfile@sha256:bdeabd40c3a8a492eaf9e + // 8e44d0ebbb84bac7ee25ac0cf8a7159d25f62555625". + // OCI defines a digest of manifest. + AttributeContainerImageID = "container.image.id" + // Name of the image the container was built on. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'gcr.io/opentelemetry/operator' + AttributeContainerImageName = "container.image.name" + // Container image tag. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '0.1' + AttributeContainerImageTag = "container.image.tag" + // Container name used by container runtime. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry-autoconf' + AttributeContainerName = "container.name" + // The container runtime managing this container. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'docker', 'containerd', 'rkt' + AttributeContainerRuntime = "container.runtime" +) + +// The software deployment. +const ( + // Name of the deployment environment (aka deployment tier). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'staging', 'production' + AttributeDeploymentEnvironment = "deployment.environment" +) + +// The device on which the process represented by this resource is running. +const ( + // A unique identifier representing the device + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2ab2916d-a51f-4ac8-80ee-45ac31a28092' + // Note: The device identifier MUST only be defined using the values outlined + // below. This value is not an advertising identifier and MUST NOT be used as + // such. On iOS (Swift or Objective-C), this value MUST be equal to the vendor + // identifier. On Android (Java or Kotlin), this value MUST be equal to the + // Firebase Installation ID or a globally unique UUID which is persisted across + // sessions in your application. More information can be found here on best + // practices and exact implementation details. Caution should be taken when + // storing personal data or anything which can identify a user. GDPR and data + // protection laws may apply, ensure you do your own due diligence. + AttributeDeviceID = "device.id" + // The name of the device manufacturer + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Apple', 'Samsung' + // Note: The Android OS provides this field via Build. iOS apps SHOULD hardcode + // the value Apple. + AttributeDeviceManufacturer = "device.manufacturer" + // The model identifier for the device + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'iPhone3,4', 'SM-G920F' + // Note: It's recommended this value represents a machine readable version of the + // model identifier rather than the market or consumer-friendly name of the + // device. + AttributeDeviceModelIdentifier = "device.model.identifier" + // The marketing name for the device model + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'iPhone 6s Plus', 'Samsung Galaxy S6' + // Note: It's recommended this value represents a human readable version of the + // device model rather than a machine readable alternative. + AttributeDeviceModelName = "device.model.name" +) + +// A serverless instance. +const ( + // The execution environment ID as a string, that will be potentially reused for + // other invocations to the same function/function version. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2021/06/28/[$LATEST]2f399eb14537447da05ab2a2e39309de' + // Note:
    + //
  • AWS Lambda: Use the (full) log stream name.
  • + //
+ AttributeFaaSInstance = "faas.instance" + // The amount of memory available to the serverless function converted to Bytes. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 134217728 + // Note: It's recommended to set this attribute since e.g. too little memory can + // easily stop a Java AWS Lambda function from working correctly. On AWS Lambda, + // the environment variable AWS_LAMBDA_FUNCTION_MEMORY_SIZE provides this + // information (which must be multiplied by 1,048,576). + AttributeFaaSMaxMemory = "faas.max_memory" + // The name of the single function that this runtime instance executes. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'my-function', 'myazurefunctionapp/some-function-name' + // Note: This is the name of the function as configured/deployed on the FaaS + // platform and is usually different from the name of the callback + // function (which may be stored in the + // code.namespace/code.function + // span attributes).For some cloud providers, the above definition is ambiguous. + // The following + // definition of function name MUST be used for this attribute + // (and consequently the span name) for the listed cloud providers/products:
    + //
  • Azure: The full name /, i.e., function app name + // followed by a forward slash followed by the function name (this form + // can also be seen in the resource JSON for the function). + // This means that a span attribute MUST be used, as an Azure function + // app can host multiple functions that would usually share + // a TracerProvider (see also the cloud.resource_id attribute).
  • + //
+ AttributeFaaSName = "faas.name" + // The immutable version of the function being executed. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '26', 'pinkfroid-00002' + // Note: Depending on the cloud provider and platform, use:
    + //
  • AWS Lambda: The function version + // (an integer represented as a decimal string).
  • + //
  • Google Cloud Run (Services): The revision + // (i.e., the function name plus the revision suffix).
  • + //
  • Google Cloud Functions: The value of the + // K_REVISION environment variable.
  • + //
  • Azure Functions: Not applicable. Do not set this attribute.
  • + //
+ AttributeFaaSVersion = "faas.version" +) + +// A host is defined as a computing instance. For example, physical servers, +// virtual machines, switches or disk array. +const ( + // The CPU architecture the host system is running on. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeHostArch = "host.arch" + // Unique host ID. For Cloud, this must be the instance_id assigned by the cloud + // provider. For non-containerized systems, this should be the machine-id. See the + // table below for the sources to use to determine the machine-id based on + // operating system. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'fdbf79e8af94cb7f9e8df36789187052' + AttributeHostID = "host.id" + // VM image ID or host OS image ID. For Cloud, this value is from the provider. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'ami-07b06b442921831e5' + AttributeHostImageID = "host.image.id" + // Name of the VM image or OS install the host was instantiated from. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'infra-ami-eks-worker-node-7d4ec78312', 'CentOS-8-x86_64-1905' + AttributeHostImageName = "host.image.name" + // The version string of the VM image or host OS as defined in Version Attributes. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '0.1' + AttributeHostImageVersion = "host.image.version" + // Name of the host. On Unix systems, it may contain what the hostname command + // returns, or the fully qualified hostname, or another name specified by the + // user. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry-test' + AttributeHostName = "host.name" + // Type of host. For Cloud, this must be the machine type. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'n1-standard-1' + AttributeHostType = "host.type" +) + +const ( + // AMD64 + AttributeHostArchAMD64 = "amd64" + // ARM32 + AttributeHostArchARM32 = "arm32" + // ARM64 + AttributeHostArchARM64 = "arm64" + // Itanium + AttributeHostArchIA64 = "ia64" + // 32-bit PowerPC + AttributeHostArchPPC32 = "ppc32" + // 64-bit PowerPC + AttributeHostArchPPC64 = "ppc64" + // IBM z/Architecture + AttributeHostArchS390x = "s390x" + // 32-bit x86 + AttributeHostArchX86 = "x86" +) + +// A Kubernetes Cluster. +const ( + // The name of the cluster. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry-cluster' + AttributeK8SClusterName = "k8s.cluster.name" + // A pseudo-ID for the cluster, set to the UID of the kube-system namespace. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '218fc5a9-a5f1-4b54-aa05-46717d0ab26d' + // Note: K8S does not have support for obtaining a cluster ID. If this is ever + // added, we will recommend collecting the k8s.cluster.uid through the + // official APIs. In the meantime, we are able to use the uid of the + // kube-system namespace as a proxy for cluster ID. Read on for the + // rationale.Every object created in a K8S cluster is assigned a distinct UID. The + // kube-system namespace is used by Kubernetes itself and will exist + // for the lifetime of the cluster. Using the uid of the kube-system + // namespace is a reasonable proxy for the K8S ClusterID as it will only + // change if the cluster is rebuilt. Furthermore, Kubernetes UIDs are + // UUIDs as standardized by + // ISO/IEC 9834-8 and ITU-T X.667. + // Which states:
+ // If generated according to one of the mechanisms defined in Rec.
+ // ITU-T X.667 | ISO/IEC 9834-8, a UUID is either guaranteed to be + // different from all other UUIDs generated before 3603 A.D., or is + // extremely likely to be different (depending on the mechanism + // chosen).Therefore, UIDs between clusters should be extremely unlikely to + // conflict. + AttributeK8SClusterUID = "k8s.cluster.uid" +) + +// A Kubernetes Node object. +const ( + // The name of the Node. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'node-1' + AttributeK8SNodeName = "k8s.node.name" + // The UID of the Node. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '1eb3a0c6-0477-4080-a9cb-0cb7db65c6a2' + AttributeK8SNodeUID = "k8s.node.uid" +) + +// A Kubernetes Namespace. +const ( + // The name of the namespace that the pod is running in. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'default' + AttributeK8SNamespaceName = "k8s.namespace.name" +) + +// A Kubernetes Pod object. +const ( + // The name of the Pod. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry-pod-autoconf' + AttributeK8SPodName = "k8s.pod.name" + // The UID of the Pod. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + AttributeK8SPodUID = "k8s.pod.uid" +) + +// A container in a +// [PodTemplate](https://kubernetes.io/docs/concepts/workloads/pods/#pod-templates). +const ( + // The name of the Container from Pod specification, must be unique within a Pod. + // Container runtime usually uses different globally unique name (container.name). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'redis' + AttributeK8SContainerName = "k8s.container.name" + // Number of times the container was restarted. This attribute can be used to + // identify a particular container (running or stopped) within a container spec. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 0, 2 + AttributeK8SContainerRestartCount = "k8s.container.restart_count" +) + +// A Kubernetes ReplicaSet object. +const ( + // The name of the ReplicaSet. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry' + AttributeK8SReplicaSetName = "k8s.replicaset.name" + // The UID of the ReplicaSet. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + AttributeK8SReplicaSetUID = "k8s.replicaset.uid" +) + +// A Kubernetes Deployment object. +const ( + // The name of the Deployment. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry' + AttributeK8SDeploymentName = "k8s.deployment.name" + // The UID of the Deployment. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + AttributeK8SDeploymentUID = "k8s.deployment.uid" +) + +// A Kubernetes StatefulSet object. +const ( + // The name of the StatefulSet. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry' + AttributeK8SStatefulSetName = "k8s.statefulset.name" + // The UID of the StatefulSet. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + AttributeK8SStatefulSetUID = "k8s.statefulset.uid" +) + +// A Kubernetes DaemonSet object. +const ( + // The name of the DaemonSet. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry' + AttributeK8SDaemonSetName = "k8s.daemonset.name" + // The UID of the DaemonSet. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + AttributeK8SDaemonSetUID = "k8s.daemonset.uid" +) + +// A Kubernetes Job object. +const ( + // The name of the Job. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry' + AttributeK8SJobName = "k8s.job.name" + // The UID of the Job. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + AttributeK8SJobUID = "k8s.job.uid" +) + +// A Kubernetes CronJob object. +const ( + // The name of the CronJob. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry' + AttributeK8SCronJobName = "k8s.cronjob.name" + // The UID of the CronJob. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + AttributeK8SCronJobUID = "k8s.cronjob.uid" +) + +// The operating system (OS) on which the process represented by this resource +// is running. +const ( + // Human readable (not intended to be parsed) OS version information, like e.g. + // reported by ver or lsb_release -a commands. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Microsoft Windows [Version 10.0.18363.778]', 'Ubuntu 18.04.1 LTS' + AttributeOSDescription = "os.description" + // Human readable operating system name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'iOS', 'Android', 'Ubuntu' + AttributeOSName = "os.name" + // The operating system type. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + AttributeOSType = "os.type" + // The version string of the operating system as defined in Version Attributes. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '14.2.1', '18.04.1' + AttributeOSVersion = "os.version" +) + +const ( + // Microsoft Windows + AttributeOSTypeWindows = "windows" + // Linux + AttributeOSTypeLinux = "linux" + // Apple Darwin + AttributeOSTypeDarwin = "darwin" + // FreeBSD + AttributeOSTypeFreeBSD = "freebsd" + // NetBSD + AttributeOSTypeNetBSD = "netbsd" + // OpenBSD + AttributeOSTypeOpenBSD = "openbsd" + // DragonFly BSD + AttributeOSTypeDragonflyBSD = "dragonflybsd" + // HP-UX (Hewlett Packard Unix) + AttributeOSTypeHPUX = "hpux" + // AIX (Advanced Interactive eXecutive) + AttributeOSTypeAIX = "aix" + // SunOS, Oracle Solaris + AttributeOSTypeSolaris = "solaris" + // IBM z/OS + AttributeOSTypeZOS = "z_os" +) + +// An operating system process. +const ( + // The command used to launch the process (i.e. the command name). On Linux based + // systems, can be set to the zeroth string in proc/[pid]/cmdline. On Windows, can + // be set to the first parameter extracted from GetCommandLineW. + // + // Type: string + // Requirement Level: Conditionally Required - See alternative attributes below. + // Stability: experimental + // Examples: 'cmd/otelcol' + AttributeProcessCommand = "process.command" + // All the command arguments (including the command/executable itself) as received + // by the process. On Linux-based systems (and some other Unixoid systems + // supporting procfs), can be set according to the list of null-delimited strings + // extracted from proc/[pid]/cmdline. For libc-based executables, this would be + // the full argv vector passed to main. + // + // Type: string[] + // Requirement Level: Conditionally Required - See alternative attributes below. + // Stability: experimental + // Examples: 'cmd/otecol', '--config=config.yaml' + AttributeProcessCommandArgs = "process.command_args" + // The full command used to launch the process as a single string representing the + // full command. On Windows, can be set to the result of GetCommandLineW. Do not + // set this if you have to assemble it just for monitoring; use + // process.command_args instead. + // + // Type: string + // Requirement Level: Conditionally Required - See alternative attributes below. + // Stability: experimental + // Examples: 'C:\\cmd\\otecol --config="my directory\\config.yaml"' + AttributeProcessCommandLine = "process.command_line" + // The name of the process executable. On Linux based systems, can be set to the + // Name in proc/[pid]/status. On Windows, can be set to the base name of + // GetProcessImageFileNameW. + // + // Type: string + // Requirement Level: Conditionally Required - See alternative attributes below. + // Stability: experimental + // Examples: 'otelcol' + AttributeProcessExecutableName = "process.executable.name" + // The full path to the process executable. On Linux based systems, can be set to + // the target of proc/[pid]/exe. On Windows, can be set to the result of + // GetProcessImageFileNameW. + // + // Type: string + // Requirement Level: Conditionally Required - See alternative attributes below. + // Stability: experimental + // Examples: '/usr/bin/cmd/otelcol' + AttributeProcessExecutablePath = "process.executable.path" + // The username of the user that owns the process. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'root' + AttributeProcessOwner = "process.owner" + // Parent Process identifier (PID). + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 111 + AttributeProcessParentPID = "process.parent_pid" + // Process identifier (PID). + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 1234 + AttributeProcessPID = "process.pid" +) + +// The single (language) runtime instance which is monitored. +const ( + // An additional description about the runtime of the process, for example a + // specific vendor customization of the runtime environment. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Eclipse OpenJ9 Eclipse OpenJ9 VM openj9-0.21.0' + AttributeProcessRuntimeDescription = "process.runtime.description" + // The name of the runtime of this process. For compiled native binaries, this + // SHOULD be the name of the compiler. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'OpenJDK Runtime Environment' + AttributeProcessRuntimeName = "process.runtime.name" + // The version of the runtime of this process, as returned by the runtime without + // modification. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '14.0.2' + AttributeProcessRuntimeVersion = "process.runtime.version" +) + +// A service instance. +const ( + // Logical name of the service. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'shoppingcart' + // Note: MUST be the same for all instances of horizontally scaled services. If + // the value was not specified, SDKs MUST fallback to unknown_service: + // concatenated with process.executable.name, e.g. unknown_service:bash. If + // process.executable.name is not available, the value MUST be set to + // unknown_service. + AttributeServiceName = "service.name" + // The version string of the service API or implementation. The format is not + // defined by these conventions. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2.0.0', 'a01dbef8a' + AttributeServiceVersion = "service.version" +) + +// A service instance. +const ( + // The string ID of the service instance. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'my-k8s-pod-deployment-1', '627cc493-f310-47de-96bd-71410b7dec09' + // Note: MUST be unique for each instance of the same + // service.namespace,service.name pair (in other words + // service.namespace,service.name,service.instance.id triplet MUST be globally + // unique). The ID helps to distinguish instances of the same service that exist + // at the same time (e.g. instances of a horizontally scaled service). It is + // preferable for the ID to be persistent and stay the same for the lifetime of + // the service instance, however it is acceptable that the ID is ephemeral and + // changes during important lifetime events for the service (e.g. service + // restarts). If the service has no inherent unique ID that can be used as the + // value of this attribute it is recommended to generate a random Version 1 or + // Version 4 RFC 4122 UUID (services aiming for reproducible UUIDs may also use + // Version 5, see RFC 4122 for more recommendations). + AttributeServiceInstanceID = "service.instance.id" + // A namespace for service.name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Shop' + // Note: A string value having a meaning that helps to distinguish a group of + // services, for example the team name that owns a group of services. service.name + // is expected to be unique within the same namespace. If service.namespace is not + // specified in the Resource then service.name is expected to be unique for all + // services that have no explicit namespace defined (so the empty/unspecified + // namespace is simply one more valid namespace). Zero-length namespace string is + // assumed equal to unspecified namespace. + AttributeServiceNamespace = "service.namespace" +) + +// The telemetry SDK used to capture data recorded by the instrumentation +// libraries. +const ( + // The language of the telemetry SDK. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + AttributeTelemetrySDKLanguage = "telemetry.sdk.language" + // The name of the telemetry SDK as defined above. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'opentelemetry' + // Note: The OpenTelemetry SDK MUST set the telemetry.sdk.name attribute to + // opentelemetry. + // If another SDK, like a fork or a vendor-provided implementation, is used, this + // SDK MUST set the + // telemetry.sdk.name attribute to the fully-qualified class or module name of + // this SDK's main entry point + // or another suitable identifier depending on the language. + // The identifier opentelemetry is reserved and MUST NOT be used in this case. + // All custom identifiers SHOULD be stable across different versions of an + // implementation. + AttributeTelemetrySDKName = "telemetry.sdk.name" + // The version string of the telemetry SDK. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: '1.2.3' + AttributeTelemetrySDKVersion = "telemetry.sdk.version" +) + +const ( + // cpp + AttributeTelemetrySDKLanguageCPP = "cpp" + // dotnet + AttributeTelemetrySDKLanguageDotnet = "dotnet" + // erlang + AttributeTelemetrySDKLanguageErlang = "erlang" + // go + AttributeTelemetrySDKLanguageGo = "go" + // java + AttributeTelemetrySDKLanguageJava = "java" + // nodejs + AttributeTelemetrySDKLanguageNodejs = "nodejs" + // php + AttributeTelemetrySDKLanguagePHP = "php" + // python + AttributeTelemetrySDKLanguagePython = "python" + // ruby + AttributeTelemetrySDKLanguageRuby = "ruby" + // rust + AttributeTelemetrySDKLanguageRust = "rust" + // swift + AttributeTelemetrySDKLanguageSwift = "swift" + // webjs + AttributeTelemetrySDKLanguageWebjs = "webjs" +) + +// The telemetry SDK used to capture data recorded by the instrumentation +// libraries. +const ( + // The version string of the auto instrumentation agent, if used. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '1.2.3' + AttributeTelemetryAutoVersion = "telemetry.auto.version" +) + +// Resource describing the packaged software running the application code. Web +// engines are typically executed using process.runtime. +const ( + // Additional description of the web engine (e.g. detailed version and edition + // information). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'WildFly Full 21.0.0.Final (WildFly Core 13.0.1.Final) - 2.2.2.Final' + AttributeWebEngineDescription = "webengine.description" + // The name of the web engine. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'WildFly' + AttributeWebEngineName = "webengine.name" + // The version of the web engine. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '21.0.0' + AttributeWebEngineVersion = "webengine.version" +) + +// Attributes used by non-OTLP exporters to represent OpenTelemetry Scope's +// concepts. +const ( + // The name of the instrumentation scope - (InstrumentationScope.Name in OTLP). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'io.opentelemetry.contrib.mongodb' + AttributeOTelScopeName = "otel.scope.name" + // The version of the instrumentation scope - (InstrumentationScope.Version in + // OTLP). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '1.0.0' + AttributeOTelScopeVersion = "otel.scope.version" +) + +// Span attributes used by non-OTLP exporters to represent OpenTelemetry +// Scope's concepts. +const ( + // Deprecated, use the otel.scope.name attribute. + // + // Type: string + // Requirement Level: Optional + // Stability: deprecated + // Examples: 'io.opentelemetry.contrib.mongodb' + AttributeOTelLibraryName = "otel.library.name" + // Deprecated, use the otel.scope.version attribute. + // + // Type: string + // Requirement Level: Optional + // Stability: deprecated + // Examples: '1.0.0' + AttributeOTelLibraryVersion = "otel.library.version" +) + +func GetResourceSemanticConventionAttributeNames() []string { + return []string{ + AttributeBrowserBrands, + AttributeBrowserLanguage, + AttributeBrowserMobile, + AttributeBrowserPlatform, + AttributeCloudAccountID, + AttributeCloudAvailabilityZone, + AttributeCloudPlatform, + AttributeCloudProvider, + AttributeCloudRegion, + AttributeCloudResourceID, + AttributeAWSECSClusterARN, + AttributeAWSECSContainerARN, + AttributeAWSECSLaunchtype, + AttributeAWSECSTaskARN, + AttributeAWSECSTaskFamily, + AttributeAWSECSTaskRevision, + AttributeAWSEKSClusterARN, + AttributeAWSLogGroupARNs, + AttributeAWSLogGroupNames, + AttributeAWSLogStreamARNs, + AttributeAWSLogStreamNames, + AttributeGCPCloudRunJobExecution, + AttributeGCPCloudRunJobTaskIndex, + AttributeGCPGceInstanceHostname, + AttributeGCPGceInstanceName, + AttributeHerokuAppID, + AttributeHerokuReleaseCommit, + AttributeHerokuReleaseCreationTimestamp, + AttributeContainerCommand, + AttributeContainerCommandArgs, + AttributeContainerCommandLine, + AttributeContainerID, + AttributeContainerImageID, + AttributeContainerImageName, + AttributeContainerImageTag, + AttributeContainerName, + AttributeContainerRuntime, + AttributeDeploymentEnvironment, + AttributeDeviceID, + AttributeDeviceManufacturer, + AttributeDeviceModelIdentifier, + AttributeDeviceModelName, + AttributeFaaSInstance, + AttributeFaaSMaxMemory, + AttributeFaaSName, + AttributeFaaSVersion, + AttributeHostArch, + AttributeHostID, + AttributeHostImageID, + AttributeHostImageName, + AttributeHostImageVersion, + AttributeHostName, + AttributeHostType, + AttributeK8SClusterName, + AttributeK8SClusterUID, + AttributeK8SNodeName, + AttributeK8SNodeUID, + AttributeK8SNamespaceName, + AttributeK8SPodName, + AttributeK8SPodUID, + AttributeK8SContainerName, + AttributeK8SContainerRestartCount, + AttributeK8SReplicaSetName, + AttributeK8SReplicaSetUID, + AttributeK8SDeploymentName, + AttributeK8SDeploymentUID, + AttributeK8SStatefulSetName, + AttributeK8SStatefulSetUID, + AttributeK8SDaemonSetName, + AttributeK8SDaemonSetUID, + AttributeK8SJobName, + AttributeK8SJobUID, + AttributeK8SCronJobName, + AttributeK8SCronJobUID, + AttributeOSDescription, + AttributeOSName, + AttributeOSType, + AttributeOSVersion, + AttributeProcessCommand, + AttributeProcessCommandArgs, + AttributeProcessCommandLine, + AttributeProcessExecutableName, + AttributeProcessExecutablePath, + AttributeProcessOwner, + AttributeProcessParentPID, + AttributeProcessPID, + AttributeProcessRuntimeDescription, + AttributeProcessRuntimeName, + AttributeProcessRuntimeVersion, + AttributeServiceName, + AttributeServiceVersion, + AttributeServiceInstanceID, + AttributeServiceNamespace, + AttributeTelemetrySDKLanguage, + AttributeTelemetrySDKName, + AttributeTelemetrySDKVersion, + AttributeTelemetryAutoVersion, + AttributeWebEngineDescription, + AttributeWebEngineName, + AttributeWebEngineVersion, + AttributeOTelScopeName, + AttributeOTelScopeVersion, + AttributeOTelLibraryName, + AttributeOTelLibraryVersion, + } +} diff --git a/semconv/v1.21.0/generated_trace.go b/semconv/v1.21.0/generated_trace.go new file mode 100644 index 00000000000..9bbd3cfbf5f --- /dev/null +++ b/semconv/v1.21.0/generated_trace.go @@ -0,0 +1,1536 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Code generated from semantic convention specification. DO NOT EDIT. + +package semconv + +// The shared attributes used to report a single exception associated with a +// span or log. +const ( + // The exception message. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Division by zero', "Can't convert 'int' object to str implicitly" + AttributeExceptionMessage = "exception.message" + // A stacktrace as a string in the natural representation for the language + // runtime. The representation is to be determined and documented by each language + // SIG. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Exception in thread "main" java.lang.RuntimeException: Test + // exception\\n at ' + // 'com.example.GenerateTrace.methodB(GenerateTrace.java:13)\\n at ' + // 'com.example.GenerateTrace.methodA(GenerateTrace.java:9)\\n at ' + // 'com.example.GenerateTrace.main(GenerateTrace.java:5)' + AttributeExceptionStacktrace = "exception.stacktrace" + // The type of the exception (its fully-qualified class name, if applicable). The + // dynamic type of the exception should be preferred over the static type in + // languages that support it. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'java.net.ConnectException', 'OSError' + AttributeExceptionType = "exception.type" +) + +// Span attributes used by AWS Lambda (in addition to general `faas` +// attributes). +const ( + // The full invoked ARN as provided on the Context passed to the function (Lambda- + // Runtime-Invoked-Function-ARN header on the /runtime/invocation/next + // applicable). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:lambda:us-east-1:123456:function:myfunction:myalias' + // Note: This may be different from cloud.resource_id if an alias is involved. + AttributeAWSLambdaInvokedARN = "aws.lambda.invoked_arn" +) + +// Attributes for CloudEvents. CloudEvents is a specification on how to define +// event data in a standard way. These attributes can be attached to spans when +// performing operations with CloudEvents, regardless of the protocol being +// used. +const ( + // The event_id uniquely identifies the event. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: '123e4567-e89b-12d3-a456-426614174000', '0001' + AttributeCloudeventsEventID = "cloudevents.event_id" + // The source identifies the context in which an event happened. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'https://github.com/cloudevents', '/cloudevents/spec/pull/123', 'my- + // service' + AttributeCloudeventsEventSource = "cloudevents.event_source" + // The version of the CloudEvents specification which the event uses. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '1.0' + AttributeCloudeventsEventSpecVersion = "cloudevents.event_spec_version" + // The subject of the event in the context of the event producer (identified by + // source). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'mynewfile.jpg' + AttributeCloudeventsEventSubject = "cloudevents.event_subject" + // The event_type contains a value describing the type of event related to the + // originating occurrence. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'com.github.pull_request.opened', 'com.example.object.deleted.v2' + AttributeCloudeventsEventType = "cloudevents.event_type" +) + +// Semantic conventions for the OpenTracing Shim +const ( + // Parent-child Reference type + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Note: The causal relationship between a child Span and a parent Span. + AttributeOpentracingRefType = "opentracing.ref_type" +) + +const ( + // The parent Span depends on the child Span in some capacity + AttributeOpentracingRefTypeChildOf = "child_of" + // The parent Span does not depend in any way on the result of the child Span + AttributeOpentracingRefTypeFollowsFrom = "follows_from" +) + +// The attributes used to perform database client calls. +const ( + // The connection string used to connect to the database. It is recommended to + // remove embedded credentials. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Server=(localdb)\\v11.0;Integrated Security=true;' + AttributeDBConnectionString = "db.connection_string" + // The fully-qualified class name of the Java Database Connectivity (JDBC) driver + // used to connect. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'org.postgresql.Driver', + // 'com.microsoft.sqlserver.jdbc.SQLServerDriver' + AttributeDBJDBCDriverClassname = "db.jdbc.driver_classname" + // This attribute is used to report the name of the database being accessed. For + // commands that switch the database, this should be set to the target database + // (even if the command fails). + // + // Type: string + // Requirement Level: Conditionally Required - If applicable. + // Stability: experimental + // Examples: 'customers', 'main' + // Note: In some SQL databases, the database name to be used is called + // "schema name". In case there are multiple layers that could be + // considered for database name (e.g. Oracle instance name and schema name), the + // database name to be used is the more specific layer (e.g. Oracle schema name). + AttributeDBName = "db.name" + // The name of the operation being executed, e.g. the MongoDB command name such as + // findAndModify, or the SQL keyword. + // + // Type: string + // Requirement Level: Conditionally Required - If `db.statement` is not + // applicable. + // Stability: experimental + // Examples: 'findAndModify', 'HMSET', 'SELECT' + // Note: When setting this to an SQL keyword, it is not recommended to attempt any + // client-side parsing of db.statement just to get this property, but it should be + // set if the operation name is provided by the library being instrumented. If the + // SQL statement has an ambiguous operation, or performs more than one operation, + // this value may be omitted. + AttributeDBOperation = "db.operation" + // The database statement being executed. + // + // Type: string + // Requirement Level: Recommended - Should be collected by default only if there + // is sanitization that excludes sensitive information. + // Stability: experimental + // Examples: 'SELECT * FROM wuser_table', 'SET mykey "WuValue"' + AttributeDBStatement = "db.statement" + // An identifier for the database management system (DBMS) product being used. See + // below for a list of well-known identifiers. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + AttributeDBSystem = "db.system" + // Username for accessing the database. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'readonly_user', 'reporting_user' + AttributeDBUser = "db.user" +) + +const ( + // Some other SQL database. Fallback only. See notes + AttributeDBSystemOtherSQL = "other_sql" + // Microsoft SQL Server + AttributeDBSystemMSSQL = "mssql" + // Microsoft SQL Server Compact + AttributeDBSystemMssqlcompact = "mssqlcompact" + // MySQL + AttributeDBSystemMySQL = "mysql" + // Oracle Database + AttributeDBSystemOracle = "oracle" + // IBM DB2 + AttributeDBSystemDB2 = "db2" + // PostgreSQL + AttributeDBSystemPostgreSQL = "postgresql" + // Amazon Redshift + AttributeDBSystemRedshift = "redshift" + // Apache Hive + AttributeDBSystemHive = "hive" + // Cloudscape + AttributeDBSystemCloudscape = "cloudscape" + // HyperSQL DataBase + AttributeDBSystemHSQLDB = "hsqldb" + // Progress Database + AttributeDBSystemProgress = "progress" + // SAP MaxDB + AttributeDBSystemMaxDB = "maxdb" + // SAP HANA + AttributeDBSystemHanaDB = "hanadb" + // Ingres + AttributeDBSystemIngres = "ingres" + // FirstSQL + AttributeDBSystemFirstSQL = "firstsql" + // EnterpriseDB + AttributeDBSystemEDB = "edb" + // InterSystems Caché + AttributeDBSystemCache = "cache" + // Adabas (Adaptable Database System) + AttributeDBSystemAdabas = "adabas" + // Firebird + AttributeDBSystemFirebird = "firebird" + // Apache Derby + AttributeDBSystemDerby = "derby" + // FileMaker + AttributeDBSystemFilemaker = "filemaker" + // Informix + AttributeDBSystemInformix = "informix" + // InstantDB + AttributeDBSystemInstantDB = "instantdb" + // InterBase + AttributeDBSystemInterbase = "interbase" + // MariaDB + AttributeDBSystemMariaDB = "mariadb" + // Netezza + AttributeDBSystemNetezza = "netezza" + // Pervasive PSQL + AttributeDBSystemPervasive = "pervasive" + // PointBase + AttributeDBSystemPointbase = "pointbase" + // SQLite + AttributeDBSystemSqlite = "sqlite" + // Sybase + AttributeDBSystemSybase = "sybase" + // Teradata + AttributeDBSystemTeradata = "teradata" + // Vertica + AttributeDBSystemVertica = "vertica" + // H2 + AttributeDBSystemH2 = "h2" + // ColdFusion IMQ + AttributeDBSystemColdfusion = "coldfusion" + // Apache Cassandra + AttributeDBSystemCassandra = "cassandra" + // Apache HBase + AttributeDBSystemHBase = "hbase" + // MongoDB + AttributeDBSystemMongoDB = "mongodb" + // Redis + AttributeDBSystemRedis = "redis" + // Couchbase + AttributeDBSystemCouchbase = "couchbase" + // CouchDB + AttributeDBSystemCouchDB = "couchdb" + // Microsoft Azure Cosmos DB + AttributeDBSystemCosmosDB = "cosmosdb" + // Amazon DynamoDB + AttributeDBSystemDynamoDB = "dynamodb" + // Neo4j + AttributeDBSystemNeo4j = "neo4j" + // Apache Geode + AttributeDBSystemGeode = "geode" + // Elasticsearch + AttributeDBSystemElasticsearch = "elasticsearch" + // Memcached + AttributeDBSystemMemcached = "memcached" + // CockroachDB + AttributeDBSystemCockroachdb = "cockroachdb" + // OpenSearch + AttributeDBSystemOpensearch = "opensearch" + // ClickHouse + AttributeDBSystemClickhouse = "clickhouse" + // Cloud Spanner + AttributeDBSystemSpanner = "spanner" + // Trino + AttributeDBSystemTrino = "trino" +) + +// Connection-level attributes for Microsoft SQL Server +const ( + // The Microsoft SQL Server instance name connecting to. This name is used to + // determine the port of a named instance. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'MSSQLSERVER' + // Note: If setting a db.mssql.instance_name, server.port is no longer required + // (but still recommended if non-standard). + AttributeDBMSSQLInstanceName = "db.mssql.instance_name" +) + +// Call-level attributes for Cassandra +const ( + // The consistency level of the query. Based on consistency values from CQL. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeDBCassandraConsistencyLevel = "db.cassandra.consistency_level" + // The data center of the coordinating node for a query. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'us-west-2' + AttributeDBCassandraCoordinatorDC = "db.cassandra.coordinator.dc" + // The ID of the coordinating node for a query. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'be13faa2-8574-4d71-926d-27f16cf8a7af' + AttributeDBCassandraCoordinatorID = "db.cassandra.coordinator.id" + // Whether or not the query is idempotent. + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + AttributeDBCassandraIdempotence = "db.cassandra.idempotence" + // The fetch size used for paging, i.e. how many rows will be returned at once. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 5000 + AttributeDBCassandraPageSize = "db.cassandra.page_size" + // The number of times a query was speculatively executed. Not set or 0 if the + // query was not executed speculatively. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 0, 2 + AttributeDBCassandraSpeculativeExecutionCount = "db.cassandra.speculative_execution_count" + // The name of the primary table that the operation is acting upon, including the + // keyspace name (if applicable). + // + // Type: string + // Requirement Level: Recommended + // Stability: experimental + // Examples: 'mytable' + // Note: This mirrors the db.sql.table attribute but references cassandra rather + // than sql. It is not recommended to attempt any client-side parsing of + // db.statement just to get this property, but it should be set if it is provided + // by the library being instrumented. If the operation is acting upon an anonymous + // table, or more than one table, this value MUST NOT be set. + AttributeDBCassandraTable = "db.cassandra.table" +) + +const ( + // all + AttributeDBCassandraConsistencyLevelAll = "all" + // each_quorum + AttributeDBCassandraConsistencyLevelEachQuorum = "each_quorum" + // quorum + AttributeDBCassandraConsistencyLevelQuorum = "quorum" + // local_quorum + AttributeDBCassandraConsistencyLevelLocalQuorum = "local_quorum" + // one + AttributeDBCassandraConsistencyLevelOne = "one" + // two + AttributeDBCassandraConsistencyLevelTwo = "two" + // three + AttributeDBCassandraConsistencyLevelThree = "three" + // local_one + AttributeDBCassandraConsistencyLevelLocalOne = "local_one" + // any + AttributeDBCassandraConsistencyLevelAny = "any" + // serial + AttributeDBCassandraConsistencyLevelSerial = "serial" + // local_serial + AttributeDBCassandraConsistencyLevelLocalSerial = "local_serial" +) + +// Call-level attributes for Redis +const ( + // The index of the database being accessed as used in the SELECT command, + // provided as an integer. To be used instead of the generic db.name attribute. + // + // Type: int + // Requirement Level: Conditionally Required - If other than the default database + // (`0`). + // Stability: experimental + // Examples: 0, 1, 15 + AttributeDBRedisDBIndex = "db.redis.database_index" +) + +// Call-level attributes for MongoDB +const ( + // The collection being accessed within the database stated in db.name. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'customers', 'products' + AttributeDBMongoDBCollection = "db.mongodb.collection" +) + +// Call-level attributes for SQL databases +const ( + // The name of the primary table that the operation is acting upon, including the + // database name (if applicable). + // + // Type: string + // Requirement Level: Recommended + // Stability: experimental + // Examples: 'public.users', 'customers' + // Note: It is not recommended to attempt any client-side parsing of db.statement + // just to get this property, but it should be set if it is provided by the + // library being instrumented. If the operation is acting upon an anonymous table, + // or more than one table, this value MUST NOT be set. + AttributeDBSQLTable = "db.sql.table" +) + +// Call-level attributes for Cosmos DB. +const ( + // Unique Cosmos client instance id. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '3ba4827d-4422-483f-b59f-85b74211c11d' + AttributeDBCosmosDBClientID = "db.cosmosdb.client_id" + // Cosmos client connection mode. + // + // Type: Enum + // Requirement Level: Conditionally Required - if not `direct` (or pick gw as + // default) + // Stability: experimental + AttributeDBCosmosDBConnectionMode = "db.cosmosdb.connection_mode" + // Cosmos DB container name. + // + // Type: string + // Requirement Level: Conditionally Required - if available + // Stability: experimental + // Examples: 'anystring' + AttributeDBCosmosDBContainer = "db.cosmosdb.container" + // CosmosDB Operation Type. + // + // Type: Enum + // Requirement Level: Conditionally Required - when performing one of the + // operations in this list + // Stability: experimental + AttributeDBCosmosDBOperationType = "db.cosmosdb.operation_type" + // RU consumed for that operation + // + // Type: double + // Requirement Level: Conditionally Required - when available + // Stability: experimental + // Examples: 46.18, 1.0 + AttributeDBCosmosDBRequestCharge = "db.cosmosdb.request_charge" + // Request payload size in bytes + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + AttributeDBCosmosDBRequestContentLength = "db.cosmosdb.request_content_length" + // Cosmos DB status code. + // + // Type: int + // Requirement Level: Conditionally Required - if response was received + // Stability: experimental + // Examples: 200, 201 + AttributeDBCosmosDBStatusCode = "db.cosmosdb.status_code" + // Cosmos DB sub status code. + // + // Type: int + // Requirement Level: Conditionally Required - when response was received and + // contained sub-code. + // Stability: experimental + // Examples: 1000, 1002 + AttributeDBCosmosDBSubStatusCode = "db.cosmosdb.sub_status_code" +) + +const ( + // Gateway (HTTP) connections mode + AttributeDBCosmosDBConnectionModeGateway = "gateway" + // Direct connection + AttributeDBCosmosDBConnectionModeDirect = "direct" +) + +const ( + // invalid + AttributeDBCosmosDBOperationTypeInvalid = "Invalid" + // create + AttributeDBCosmosDBOperationTypeCreate = "Create" + // patch + AttributeDBCosmosDBOperationTypePatch = "Patch" + // read + AttributeDBCosmosDBOperationTypeRead = "Read" + // read_feed + AttributeDBCosmosDBOperationTypeReadFeed = "ReadFeed" + // delete + AttributeDBCosmosDBOperationTypeDelete = "Delete" + // replace + AttributeDBCosmosDBOperationTypeReplace = "Replace" + // execute + AttributeDBCosmosDBOperationTypeExecute = "Execute" + // query + AttributeDBCosmosDBOperationTypeQuery = "Query" + // head + AttributeDBCosmosDBOperationTypeHead = "Head" + // head_feed + AttributeDBCosmosDBOperationTypeHeadFeed = "HeadFeed" + // upsert + AttributeDBCosmosDBOperationTypeUpsert = "Upsert" + // batch + AttributeDBCosmosDBOperationTypeBatch = "Batch" + // query_plan + AttributeDBCosmosDBOperationTypeQueryPlan = "QueryPlan" + // execute_javascript + AttributeDBCosmosDBOperationTypeExecuteJavascript = "ExecuteJavaScript" +) + +// Span attributes used by non-OTLP exporters to represent OpenTelemetry Span's +// concepts. +const ( + // Name of the code, either "OK" or "ERROR". MUST NOT be set + // if the status code is UNSET. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeOTelStatusCode = "otel.status_code" + // Description of the Status if it has a value, otherwise not set. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'resource not found' + AttributeOTelStatusDescription = "otel.status_description" +) + +const ( + // The operation has been validated by an Application developer or Operator to have completed successfully + AttributeOTelStatusCodeOk = "OK" + // The operation contains an error + AttributeOTelStatusCodeError = "ERROR" +) + +// This semantic convention describes an instance of a function that runs +// without provisioning or managing of servers (also known as serverless +// functions or Function as a Service (FaaS)) with spans. +const ( + // The invocation ID of the current function invocation. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'af9d5aa4-a685-4c5f-a22b-444f80b3cc28' + AttributeFaaSInvocationID = "faas.invocation_id" + // Type of the trigger which caused this function invocation. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Note: For the server/consumer span on the incoming side, + // faas.trigger MUST be set.Clients invoking FaaS instances usually cannot set + // faas.trigger, + // since they would typically need to look in the payload to determine + // the event type. If clients set it, it should be the same as the + // trigger that corresponding incoming would have (i.e., this has + // nothing to do with the underlying transport used to make the API + // call to invoke the lambda, which is often HTTP). + AttributeFaaSTrigger = "faas.trigger" +) + +const ( + // A response to some data source operation such as a database or filesystem read/write + AttributeFaaSTriggerDatasource = "datasource" + // To provide an answer to an inbound HTTP request + AttributeFaaSTriggerHTTP = "http" + // A function is set to be executed when messages are sent to a messaging system + AttributeFaaSTriggerPubsub = "pubsub" + // A function is scheduled to be executed regularly + AttributeFaaSTriggerTimer = "timer" + // If none of the others apply + AttributeFaaSTriggerOther = "other" +) + +// Semantic Convention for FaaS triggered as a response to some data source +// operation such as a database or filesystem read/write. +const ( + // The name of the source on which the triggering operation was performed. For + // example, in Cloud Storage or S3 corresponds to the bucket name, and in Cosmos + // DB to the database name. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'myBucketName', 'myDBName' + AttributeFaaSDocumentCollection = "faas.document.collection" + // The document name/table subjected to the operation. For example, in Cloud + // Storage or S3 is the name of the file, and in Cosmos DB the table name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'myFile.txt', 'myTableName' + AttributeFaaSDocumentName = "faas.document.name" + // Describes the type of the operation that was performed on the data. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + AttributeFaaSDocumentOperation = "faas.document.operation" + // A string containing the time when the data was accessed in the ISO 8601 format + // expressed in UTC. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2020-01-23T13:47:06Z' + AttributeFaaSDocumentTime = "faas.document.time" +) + +const ( + // When a new object is created + AttributeFaaSDocumentOperationInsert = "insert" + // When an object is modified + AttributeFaaSDocumentOperationEdit = "edit" + // When an object is deleted + AttributeFaaSDocumentOperationDelete = "delete" +) + +// Semantic Convention for FaaS scheduled to be executed regularly. +const ( + // A string containing the schedule period as Cron Expression. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '0/5 * * * ? *' + AttributeFaaSCron = "faas.cron" + // A string containing the function invocation time in the ISO 8601 format + // expressed in UTC. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2020-01-23T13:47:06Z' + AttributeFaaSTime = "faas.time" +) + +// Contains additional attributes for incoming FaaS spans. +const ( + // A boolean that is true if the serverless function is executed for the first + // time (aka cold-start). + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + AttributeFaaSColdstart = "faas.coldstart" +) + +// Contains additional attributes for outgoing FaaS spans. +const ( + // The name of the invoked function. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'my-function' + // Note: SHOULD be equal to the faas.name resource attribute of the invoked + // function. + AttributeFaaSInvokedName = "faas.invoked_name" + // The cloud provider of the invoked function. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + // Note: SHOULD be equal to the cloud.provider resource attribute of the invoked + // function. + AttributeFaaSInvokedProvider = "faas.invoked_provider" + // The cloud region of the invoked function. + // + // Type: string + // Requirement Level: Conditionally Required - For some cloud providers, like AWS + // or GCP, the region in which a function is hosted is essential to uniquely + // identify the function and also part of its endpoint. Since it's part of the + // endpoint being called, the region is always known to clients. In these cases, + // `faas.invoked_region` MUST be set accordingly. If the region is unknown to the + // client or not required for identifying the invoked function, setting + // `faas.invoked_region` is optional. + // Stability: experimental + // Examples: 'eu-central-1' + // Note: SHOULD be equal to the cloud.region resource attribute of the invoked + // function. + AttributeFaaSInvokedRegion = "faas.invoked_region" +) + +const ( + // Alibaba Cloud + AttributeFaaSInvokedProviderAlibabaCloud = "alibaba_cloud" + // Amazon Web Services + AttributeFaaSInvokedProviderAWS = "aws" + // Microsoft Azure + AttributeFaaSInvokedProviderAzure = "azure" + // Google Cloud Platform + AttributeFaaSInvokedProviderGCP = "gcp" + // Tencent Cloud + AttributeFaaSInvokedProviderTencentCloud = "tencent_cloud" +) + +// Operations that access some remote service. +const ( + // The service.name of the remote service. SHOULD be equal to the actual + // service.name resource attribute of the remote service if any. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'AuthTokenCache' + AttributePeerService = "peer.service" +) + +// These attributes may be used for any operation with an authenticated and/or +// authorized enduser. +const ( + // Username or client_id extracted from the access token or Authorization header + // in the inbound request from outside the system. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'username' + AttributeEnduserID = "enduser.id" + // Actual/assumed role the client is making the request under extracted from token + // or application security context. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'admin' + AttributeEnduserRole = "enduser.role" + // Scopes or granted authorities the client currently possesses extracted from + // token or application security context. The value would come from the scope + // associated with an OAuth 2.0 Access Token or an attribute value in a SAML 2.0 + // Assertion. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'read:message, write:files' + AttributeEnduserScope = "enduser.scope" +) + +// These attributes may be used for any operation to store information about a +// thread that started a span. +const ( + // Current "managed" thread ID (as opposed to OS thread ID). + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 42 + AttributeThreadID = "thread.id" + // Current thread name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'main' + AttributeThreadName = "thread.name" +) + +// These attributes allow to report this unit of code and therefore to provide +// more context about the span. +const ( + // The column number in code.filepath best representing the operation. It SHOULD + // point within the code unit named in code.function. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 16 + AttributeCodeColumn = "code.column" + // The source code file name that identifies the code unit as uniquely as possible + // (preferably an absolute file path). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '/usr/local/MyApplication/content_root/app/index.php' + AttributeCodeFilepath = "code.filepath" + // The method or function name, or equivalent (usually rightmost part of the code + // unit's name). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'serveRequest' + AttributeCodeFunction = "code.function" + // The line number in code.filepath best representing the operation. It SHOULD + // point within the code unit named in code.function. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 42 + AttributeCodeLineNumber = "code.lineno" + // The "namespace" within which code.function is defined. Usually the + // qualified class or module name, such that code.namespace + some separator + + // code.function form a unique identifier for the code unit. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'com.example.MyHTTPService' + AttributeCodeNamespace = "code.namespace" +) + +// Semantic Convention for HTTP Client +const ( + // The ordinal number of request resending attempt (for any reason, including + // redirects). + // + // Type: int + // Requirement Level: Recommended - if and only if request was retried. + // Stability: experimental + // Examples: 3 + // Note: The resend count SHOULD be updated each time an HTTP request gets resent + // by the client, regardless of what was the cause of the resending (e.g. + // redirection, authorization failure, 503 Server Unavailable, network issues, or + // any other). + AttributeHTTPResendCount = "http.resend_count" +) + +// The `aws` conventions apply to operations using the AWS SDK. They map +// request or response parameters in AWS SDK API calls to attributes on a Span. +// The conventions have been collected over time based on feedback from AWS +// users of tracing and will continue to evolve as new interesting conventions +// are found. +// Some descriptions are also provided for populating general OpenTelemetry +// semantic conventions based on these APIs. +const ( + // The AWS request ID as returned in the response headers x-amz-request-id or + // x-amz-requestid. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '79b9da39-b7ae-508a-a6bc-864b2829c622', 'C9ER4AJX75574TDJ' + AttributeAWSRequestID = "aws.request_id" +) + +// Attributes that exist for multiple DynamoDB request types. +const ( + // The value of the AttributesToGet request parameter. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'lives', 'id' + AttributeAWSDynamoDBAttributesToGet = "aws.dynamodb.attributes_to_get" + // The value of the ConsistentRead request parameter. + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + AttributeAWSDynamoDBConsistentRead = "aws.dynamodb.consistent_read" + // The JSON-serialized value of each item in the ConsumedCapacity response field. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: '{ "CapacityUnits": number, "GlobalSecondaryIndexes": { "string" : { + // "CapacityUnits": number, "ReadCapacityUnits": number, "WriteCapacityUnits": + // number } }, "LocalSecondaryIndexes": { "string" : { "CapacityUnits": number, + // "ReadCapacityUnits": number, "WriteCapacityUnits": number } }, + // "ReadCapacityUnits": number, "Table": { "CapacityUnits": number, + // "ReadCapacityUnits": number, "WriteCapacityUnits": number }, "TableName": + // "string", "WriteCapacityUnits": number }' + AttributeAWSDynamoDBConsumedCapacity = "aws.dynamodb.consumed_capacity" + // The value of the IndexName request parameter. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'name_to_group' + AttributeAWSDynamoDBIndexName = "aws.dynamodb.index_name" + // The JSON-serialized value of the ItemCollectionMetrics response field. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '{ "string" : [ { "ItemCollectionKey": { "string" : { "B": blob, + // "BOOL": boolean, "BS": [ blob ], "L": [ "AttributeValue" ], "M": { "string" : + // "AttributeValue" }, "N": "string", "NS": [ "string" ], "NULL": boolean, "S": + // "string", "SS": [ "string" ] } }, "SizeEstimateRangeGB": [ number ] } ] }' + AttributeAWSDynamoDBItemCollectionMetrics = "aws.dynamodb.item_collection_metrics" + // The value of the Limit request parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 10 + AttributeAWSDynamoDBLimit = "aws.dynamodb.limit" + // The value of the ProjectionExpression request parameter. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Title', 'Title, Price, Color', 'Title, Description, RelatedItems, + // ProductReviews' + AttributeAWSDynamoDBProjection = "aws.dynamodb.projection" + // The value of the ProvisionedThroughput.ReadCapacityUnits request parameter. + // + // Type: double + // Requirement Level: Optional + // Stability: experimental + // Examples: 1.0, 2.0 + AttributeAWSDynamoDBProvisionedReadCapacity = "aws.dynamodb.provisioned_read_capacity" + // The value of the ProvisionedThroughput.WriteCapacityUnits request parameter. + // + // Type: double + // Requirement Level: Optional + // Stability: experimental + // Examples: 1.0, 2.0 + AttributeAWSDynamoDBProvisionedWriteCapacity = "aws.dynamodb.provisioned_write_capacity" + // The value of the Select request parameter. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'ALL_ATTRIBUTES', 'COUNT' + AttributeAWSDynamoDBSelect = "aws.dynamodb.select" + // The keys in the RequestItems object field. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Users', 'Cats' + AttributeAWSDynamoDBTableNames = "aws.dynamodb.table_names" +) + +// DynamoDB.CreateTable +const ( + // The JSON-serialized value of each item of the GlobalSecondaryIndexes request + // field + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: '{ "IndexName": "string", "KeySchema": [ { "AttributeName": "string", + // "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ "string" ], + // "ProjectionType": "string" }, "ProvisionedThroughput": { "ReadCapacityUnits": + // number, "WriteCapacityUnits": number } }' + AttributeAWSDynamoDBGlobalSecondaryIndexes = "aws.dynamodb.global_secondary_indexes" + // The JSON-serialized value of each item of the LocalSecondaryIndexes request + // field. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: '{ "IndexARN": "string", "IndexName": "string", "IndexSizeBytes": + // number, "ItemCount": number, "KeySchema": [ { "AttributeName": "string", + // "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ "string" ], + // "ProjectionType": "string" } }' + AttributeAWSDynamoDBLocalSecondaryIndexes = "aws.dynamodb.local_secondary_indexes" +) + +// DynamoDB.ListTables +const ( + // The value of the ExclusiveStartTableName request parameter. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Users', 'CatsTable' + AttributeAWSDynamoDBExclusiveStartTable = "aws.dynamodb.exclusive_start_table" + // The the number of items in the TableNames response parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 20 + AttributeAWSDynamoDBTableCount = "aws.dynamodb.table_count" +) + +// DynamoDB.Query +const ( + // The value of the ScanIndexForward request parameter. + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + AttributeAWSDynamoDBScanForward = "aws.dynamodb.scan_forward" +) + +// DynamoDB.Scan +const ( + // The value of the Count response parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 10 + AttributeAWSDynamoDBCount = "aws.dynamodb.count" + // The value of the ScannedCount response parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 50 + AttributeAWSDynamoDBScannedCount = "aws.dynamodb.scanned_count" + // The value of the Segment request parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 10 + AttributeAWSDynamoDBSegment = "aws.dynamodb.segment" + // The value of the TotalSegments request parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 100 + AttributeAWSDynamoDBTotalSegments = "aws.dynamodb.total_segments" +) + +// DynamoDB.UpdateTable +const ( + // The JSON-serialized value of each item in the AttributeDefinitions request + // field. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: '{ "AttributeName": "string", "AttributeType": "string" }' + AttributeAWSDynamoDBAttributeDefinitions = "aws.dynamodb.attribute_definitions" + // The JSON-serialized value of each item in the the GlobalSecondaryIndexUpdates + // request field. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: '{ "Create": { "IndexName": "string", "KeySchema": [ { + // "AttributeName": "string", "KeyType": "string" } ], "Projection": { + // "NonKeyAttributes": [ "string" ], "ProjectionType": "string" }, + // "ProvisionedThroughput": { "ReadCapacityUnits": number, "WriteCapacityUnits": + // number } }' + AttributeAWSDynamoDBGlobalSecondaryIndexUpdates = "aws.dynamodb.global_secondary_index_updates" +) + +// Attributes that exist for S3 request types. +const ( + // The S3 bucket name the request refers to. Corresponds to the --bucket parameter + // of the S3 API operations. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'some-bucket-name' + // Note: The bucket attribute is applicable to all S3 operations that reference a + // bucket, i.e. that require the bucket name as a mandatory parameter. + // This applies to almost all S3 operations except list-buckets. + AttributeAWSS3Bucket = "aws.s3.bucket" + // The source object (in the form bucket/key) for the copy operation. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'someFile.yml' + // Note: The copy_source attribute applies to S3 copy operations and corresponds + // to the --copy-source parameter + // of the copy-object operation within the S3 API. + // This applies in particular to the following operations:
    + //
  • copy-object
  • + //
  • upload-part-copy
  • + //
+ AttributeAWSS3CopySource = "aws.s3.copy_source" + // The delete request container that specifies the objects to be deleted. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Objects=[{Key=string,VersionID=string},{Key=string,VersionID=string} + // ],Quiet=boolean' + // Note: The delete attribute is only applicable to the delete-object operation. + // The delete attribute corresponds to the --delete parameter of the + // delete-objects operation within the S3 API. + AttributeAWSS3Delete = "aws.s3.delete" + // The S3 object key the request refers to. Corresponds to the --key parameter of + // the S3 API operations. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'someFile.yml' + // Note: The key attribute is applicable to all object-related S3 operations, i.e. + // that require the object key as a mandatory parameter. + // This applies in particular to the following operations:
    + //
  • copy-object
  • + //
  • delete-object
  • + //
  • get-object
  • + //
  • head-object
  • + //
  • put-object
  • + //
  • restore-object
  • + //
  • select-object-content
  • + //
  • abort-multipart-upload
  • + //
  • complete-multipart-upload
  • + //
  • create-multipart-upload
  • + //
  • list-parts
  • + //
  • upload-part
  • + //
  • upload-part-copy
  • + //
+ AttributeAWSS3Key = "aws.s3.key" + // The part number of the part being uploaded in a multipart-upload operation. + // This is a positive integer between 1 and 10,000. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 3456 + // Note: The part_number attribute is only applicable to the upload-part + // and upload-part-copy operations. + // The part_number attribute corresponds to the --part-number parameter of the + // upload-part operation within the S3 API. + AttributeAWSS3PartNumber = "aws.s3.part_number" + // Upload ID that identifies the multipart upload. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'dfRtDYWFbkRONycy.Yxwh66Yjlx.cph0gtNBtJ' + // Note: The upload_id attribute applies to S3 multipart-upload operations and + // corresponds to the --upload-id parameter + // of the S3 API multipart operations. + // This applies in particular to the following operations:
    + //
  • abort-multipart-upload
  • + //
  • complete-multipart-upload
  • + //
  • list-parts
  • + //
  • upload-part
  • + //
  • upload-part-copy
  • + //
+ AttributeAWSS3UploadID = "aws.s3.upload_id" +) + +// Semantic conventions to apply when instrumenting the GraphQL implementation. +// They map GraphQL operations to attributes on a Span. +const ( + // The GraphQL document being executed. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'query findBookByID { bookByID(id: ?) { name } }' + // Note: The value may be sanitized to exclude sensitive information. + AttributeGraphqlDocument = "graphql.document" + // The name of the operation being executed. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'findBookByID' + AttributeGraphqlOperationName = "graphql.operation.name" + // The type of the operation being executed. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'query', 'mutation', 'subscription' + AttributeGraphqlOperationType = "graphql.operation.type" +) + +const ( + // GraphQL query + AttributeGraphqlOperationTypeQuery = "query" + // GraphQL mutation + AttributeGraphqlOperationTypeMutation = "mutation" + // GraphQL subscription + AttributeGraphqlOperationTypeSubscription = "subscription" +) + +// General attributes used in messaging systems. +const ( + // The number of messages sent, received, or processed in the scope of the + // batching operation. + // + // Type: int + // Requirement Level: Conditionally Required - If the span describes an operation + // on a batch of messages. + // Stability: experimental + // Examples: 0, 1, 2 + // Note: Instrumentations SHOULD NOT set messaging.batch.message_count on spans + // that operate with a single message. When a messaging client library supports + // both batch and single-message API for the same operation, instrumentations + // SHOULD use messaging.batch.message_count for batching APIs and SHOULD NOT use + // it for single-message APIs. + AttributeMessagingBatchMessageCount = "messaging.batch.message_count" + // A unique identifier for the client that consumes or produces a message. + // + // Type: string + // Requirement Level: Recommended - If a client id is available + // Stability: experimental + // Examples: 'client-5', 'myhost@8742@s8083jm' + AttributeMessagingClientID = "messaging.client_id" + // A string identifying the kind of messaging operation as defined in the + // Operation names section above. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + // Note: If a custom value is used, it MUST be of low cardinality. + AttributeMessagingOperation = "messaging.operation" + // A string identifying the messaging system. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'kafka', 'rabbitmq', 'rocketmq', 'activemq', 'AmazonSQS' + AttributeMessagingSystem = "messaging.system" +) + +const ( + // publish + AttributeMessagingOperationPublish = "publish" + // receive + AttributeMessagingOperationReceive = "receive" + // process + AttributeMessagingOperationProcess = "process" +) + +// Semantic conventions for remote procedure calls. +const ( + // The name of the (logical) method being called, must be equal to the $method + // part in the span name. + // + // Type: string + // Requirement Level: Recommended + // Stability: experimental + // Examples: 'exampleMethod' + // Note: This is the logical name of the method from the RPC interface + // perspective, which can be different from the name of any implementing + // method/function. The code.function attribute may be used to store the latter + // (e.g., method actually executing the call on the server side, RPC client stub + // method on the client side). + AttributeRPCMethod = "rpc.method" + // The full (logical) name of the service being called, including its package + // name, if applicable. + // + // Type: string + // Requirement Level: Recommended + // Stability: experimental + // Examples: 'myservice.EchoService' + // Note: This is the logical name of the service from the RPC interface + // perspective, which can be different from the name of any implementing class. + // The code.namespace attribute may be used to store the latter (despite the + // attribute name, it may include a class name; e.g., class with method actually + // executing the call on the server side, RPC client stub class on the client + // side). + AttributeRPCService = "rpc.service" + // A string identifying the remoting system. See below for a list of well-known + // identifiers. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + AttributeRPCSystem = "rpc.system" +) + +const ( + // gRPC + AttributeRPCSystemGRPC = "grpc" + // Java RMI + AttributeRPCSystemJavaRmi = "java_rmi" + // .NET WCF + AttributeRPCSystemDotnetWcf = "dotnet_wcf" + // Apache Dubbo + AttributeRPCSystemApacheDubbo = "apache_dubbo" + // Connect RPC + AttributeRPCSystemConnectRPC = "connect_rpc" +) + +// Tech-specific attributes for gRPC. +const ( + // The numeric status code of the gRPC request. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + AttributeRPCGRPCStatusCode = "rpc.grpc.status_code" +) + +const ( + // OK + AttributeRPCGRPCStatusCodeOk = "0" + // CANCELLED + AttributeRPCGRPCStatusCodeCancelled = "1" + // UNKNOWN + AttributeRPCGRPCStatusCodeUnknown = "2" + // INVALID_ARGUMENT + AttributeRPCGRPCStatusCodeInvalidArgument = "3" + // DEADLINE_EXCEEDED + AttributeRPCGRPCStatusCodeDeadlineExceeded = "4" + // NOT_FOUND + AttributeRPCGRPCStatusCodeNotFound = "5" + // ALREADY_EXISTS + AttributeRPCGRPCStatusCodeAlreadyExists = "6" + // PERMISSION_DENIED + AttributeRPCGRPCStatusCodePermissionDenied = "7" + // RESOURCE_EXHAUSTED + AttributeRPCGRPCStatusCodeResourceExhausted = "8" + // FAILED_PRECONDITION + AttributeRPCGRPCStatusCodeFailedPrecondition = "9" + // ABORTED + AttributeRPCGRPCStatusCodeAborted = "10" + // OUT_OF_RANGE + AttributeRPCGRPCStatusCodeOutOfRange = "11" + // UNIMPLEMENTED + AttributeRPCGRPCStatusCodeUnimplemented = "12" + // INTERNAL + AttributeRPCGRPCStatusCodeInternal = "13" + // UNAVAILABLE + AttributeRPCGRPCStatusCodeUnavailable = "14" + // DATA_LOSS + AttributeRPCGRPCStatusCodeDataLoss = "15" + // UNAUTHENTICATED + AttributeRPCGRPCStatusCodeUnauthenticated = "16" +) + +// Tech-specific attributes for [JSON RPC](https://www.jsonrpc.org/). +const ( + // error.code property of response if it is an error response. + // + // Type: int + // Requirement Level: Conditionally Required - If response is not successful. + // Stability: experimental + // Examples: -32700, 100 + AttributeRPCJsonrpcErrorCode = "rpc.jsonrpc.error_code" + // error.message property of response if it is an error response. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Parse error', 'User already exists' + AttributeRPCJsonrpcErrorMessage = "rpc.jsonrpc.error_message" + // id property of request or response. Since protocol allows id to be int, string, + // null or missing (for notifications), value is expected to be cast to string for + // simplicity. Use empty string in case of null value. Omit entirely if this is a + // notification. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '10', 'request-7', '' + AttributeRPCJsonrpcRequestID = "rpc.jsonrpc.request_id" + // Protocol version as in jsonrpc property of request/response. Since JSON-RPC 1.0 + // does not specify this, the value can be omitted. + // + // Type: string + // Requirement Level: Conditionally Required - If other than the default version + // (`1.0`) + // Stability: experimental + // Examples: '2.0', '1.0' + AttributeRPCJsonrpcVersion = "rpc.jsonrpc.version" +) + +// Tech-specific attributes for Connect RPC. +const ( + // The error codes of the Connect request. Error codes are always string values. + // + // Type: Enum + // Requirement Level: Conditionally Required - If response is not successful and + // if error code available. + // Stability: experimental + AttributeRPCConnectRPCErrorCode = "rpc.connect_rpc.error_code" +) + +const ( + // cancelled + AttributeRPCConnectRPCErrorCodeCancelled = "cancelled" + // unknown + AttributeRPCConnectRPCErrorCodeUnknown = "unknown" + // invalid_argument + AttributeRPCConnectRPCErrorCodeInvalidArgument = "invalid_argument" + // deadline_exceeded + AttributeRPCConnectRPCErrorCodeDeadlineExceeded = "deadline_exceeded" + // not_found + AttributeRPCConnectRPCErrorCodeNotFound = "not_found" + // already_exists + AttributeRPCConnectRPCErrorCodeAlreadyExists = "already_exists" + // permission_denied + AttributeRPCConnectRPCErrorCodePermissionDenied = "permission_denied" + // resource_exhausted + AttributeRPCConnectRPCErrorCodeResourceExhausted = "resource_exhausted" + // failed_precondition + AttributeRPCConnectRPCErrorCodeFailedPrecondition = "failed_precondition" + // aborted + AttributeRPCConnectRPCErrorCodeAborted = "aborted" + // out_of_range + AttributeRPCConnectRPCErrorCodeOutOfRange = "out_of_range" + // unimplemented + AttributeRPCConnectRPCErrorCodeUnimplemented = "unimplemented" + // internal + AttributeRPCConnectRPCErrorCodeInternal = "internal" + // unavailable + AttributeRPCConnectRPCErrorCodeUnavailable = "unavailable" + // data_loss + AttributeRPCConnectRPCErrorCodeDataLoss = "data_loss" + // unauthenticated + AttributeRPCConnectRPCErrorCodeUnauthenticated = "unauthenticated" +) + +func GetTraceSemanticConventionAttributeNames() []string { + return []string{ + AttributeExceptionMessage, + AttributeExceptionStacktrace, + AttributeExceptionType, + AttributeAWSLambdaInvokedARN, + AttributeCloudeventsEventID, + AttributeCloudeventsEventSource, + AttributeCloudeventsEventSpecVersion, + AttributeCloudeventsEventSubject, + AttributeCloudeventsEventType, + AttributeOpentracingRefType, + AttributeDBConnectionString, + AttributeDBJDBCDriverClassname, + AttributeDBName, + AttributeDBOperation, + AttributeDBStatement, + AttributeDBSystem, + AttributeDBUser, + AttributeDBMSSQLInstanceName, + AttributeDBCassandraConsistencyLevel, + AttributeDBCassandraCoordinatorDC, + AttributeDBCassandraCoordinatorID, + AttributeDBCassandraIdempotence, + AttributeDBCassandraPageSize, + AttributeDBCassandraSpeculativeExecutionCount, + AttributeDBCassandraTable, + AttributeDBRedisDBIndex, + AttributeDBMongoDBCollection, + AttributeDBSQLTable, + AttributeDBCosmosDBClientID, + AttributeDBCosmosDBConnectionMode, + AttributeDBCosmosDBContainer, + AttributeDBCosmosDBOperationType, + AttributeDBCosmosDBRequestCharge, + AttributeDBCosmosDBRequestContentLength, + AttributeDBCosmosDBStatusCode, + AttributeDBCosmosDBSubStatusCode, + AttributeOTelStatusCode, + AttributeOTelStatusDescription, + AttributeFaaSInvocationID, + AttributeFaaSTrigger, + AttributeFaaSDocumentCollection, + AttributeFaaSDocumentName, + AttributeFaaSDocumentOperation, + AttributeFaaSDocumentTime, + AttributeFaaSCron, + AttributeFaaSTime, + AttributeFaaSColdstart, + AttributeFaaSInvokedName, + AttributeFaaSInvokedProvider, + AttributeFaaSInvokedRegion, + AttributePeerService, + AttributeEnduserID, + AttributeEnduserRole, + AttributeEnduserScope, + AttributeThreadID, + AttributeThreadName, + AttributeCodeColumn, + AttributeCodeFilepath, + AttributeCodeFunction, + AttributeCodeLineNumber, + AttributeCodeNamespace, + AttributeHTTPResendCount, + AttributeAWSRequestID, + AttributeAWSDynamoDBAttributesToGet, + AttributeAWSDynamoDBConsistentRead, + AttributeAWSDynamoDBConsumedCapacity, + AttributeAWSDynamoDBIndexName, + AttributeAWSDynamoDBItemCollectionMetrics, + AttributeAWSDynamoDBLimit, + AttributeAWSDynamoDBProjection, + AttributeAWSDynamoDBProvisionedReadCapacity, + AttributeAWSDynamoDBProvisionedWriteCapacity, + AttributeAWSDynamoDBSelect, + AttributeAWSDynamoDBTableNames, + AttributeAWSDynamoDBGlobalSecondaryIndexes, + AttributeAWSDynamoDBLocalSecondaryIndexes, + AttributeAWSDynamoDBExclusiveStartTable, + AttributeAWSDynamoDBTableCount, + AttributeAWSDynamoDBScanForward, + AttributeAWSDynamoDBCount, + AttributeAWSDynamoDBScannedCount, + AttributeAWSDynamoDBSegment, + AttributeAWSDynamoDBTotalSegments, + AttributeAWSDynamoDBAttributeDefinitions, + AttributeAWSDynamoDBGlobalSecondaryIndexUpdates, + AttributeAWSS3Bucket, + AttributeAWSS3CopySource, + AttributeAWSS3Delete, + AttributeAWSS3Key, + AttributeAWSS3PartNumber, + AttributeAWSS3UploadID, + AttributeGraphqlDocument, + AttributeGraphqlOperationName, + AttributeGraphqlOperationType, + AttributeMessagingBatchMessageCount, + AttributeMessagingClientID, + AttributeMessagingOperation, + AttributeMessagingSystem, + AttributeRPCMethod, + AttributeRPCService, + AttributeRPCSystem, + AttributeRPCGRPCStatusCode, + AttributeRPCJsonrpcErrorCode, + AttributeRPCJsonrpcErrorMessage, + AttributeRPCJsonrpcRequestID, + AttributeRPCJsonrpcVersion, + AttributeRPCConnectRPCErrorCode, + } +} diff --git a/semconv/v1.21.0/schema.go b/semconv/v1.21.0/schema.go new file mode 100644 index 00000000000..6db9125c204 --- /dev/null +++ b/semconv/v1.21.0/schema.go @@ -0,0 +1,9 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package semconv // import "go.opentelemetry.io/collector/semconv/v1.21.0" + +// SchemaURL is the schema URL that matches the version of the semantic conventions +// that this package defines. Semconv packages starting from v1.4.0 must declare +// non-empty schema URL in the form https://opentelemetry.io/schemas/ +const SchemaURL = "https://opentelemetry.io/schemas/1.21.0" diff --git a/semconv/v1.22.0/doc.go b/semconv/v1.22.0/doc.go new file mode 100644 index 00000000000..87554f9da80 --- /dev/null +++ b/semconv/v1.22.0/doc.go @@ -0,0 +1,9 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package semconv implements OpenTelemetry semantic conventions. +// +// OpenTelemetry semantic conventions are agreed standardized naming +// patterns for OpenTelemetry things. This package represents the v1.22.0 +// version of the OpenTelemetry semantic conventions. +package semconv // import "go.opentelemetry.io/collector/semconv/v1.22.0" diff --git a/semconv/v1.22.0/generated_event.go b/semconv/v1.22.0/generated_event.go new file mode 100644 index 00000000000..ec6c733ecd4 --- /dev/null +++ b/semconv/v1.22.0/generated_event.go @@ -0,0 +1,119 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Code generated from semantic convention specification. DO NOT EDIT. + +package semconv + +// This semantic convention defines the attributes used to represent a feature +// flag evaluation as an event. +const ( + // The unique identifier of the feature flag. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'logo-color' + AttributeFeatureFlagKey = "feature_flag.key" + // The name of the service provider that performs the flag evaluation. + // + // Type: string + // Requirement Level: Recommended + // Stability: experimental + // Examples: 'Flag Manager' + AttributeFeatureFlagProviderName = "feature_flag.provider_name" + // SHOULD be a semantic identifier for a value. If one is unavailable, a + // stringified version of the value can be used. + // + // Type: string + // Requirement Level: Recommended + // Stability: experimental + // Examples: 'red', 'true', 'on' + // Note: A semantic identifier, commonly referred to as a variant, provides a + // means + // for referring to a value without including the value itself. This can + // provide additional context for understanding the meaning behind a value. + // For example, the variant red maybe be used for the value #c05543.A stringified + // version of the value can be used in situations where a + // semantic identifier is unavailable. String representation of the value + // should be determined by the implementer. + AttributeFeatureFlagVariant = "feature_flag.variant" +) + +// RPC received/sent message. +const ( + // Compressed size of the message in bytes. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + AttributeMessageCompressedSize = "message.compressed_size" + // MUST be calculated as two different counters starting from 1 one for sent + // messages and one for received message. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Note: This way we guarantee that the values will be consistent between + // different implementations. + AttributeMessageID = "message.id" + // Whether this is a received or sent message. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeMessageType = "message.type" + // Uncompressed size of the message in bytes. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + AttributeMessageUncompressedSize = "message.uncompressed_size" +) + +const ( + // sent + AttributeMessageTypeSent = "SENT" + // received + AttributeMessageTypeReceived = "RECEIVED" +) + +// The attributes used to report a single exception associated with a span. +const ( + // SHOULD be set to true if the exception event is recorded at a point where it is + // known that the exception is escaping the scope of the span. + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + // Note: An exception is considered to have escaped (or left) the scope of a span, + // if that span is ended while the exception is still logically "in + // flight". + // This may be actually "in flight" in some languages (e.g. if the + // exception + // is passed to a Context manager's __exit__ method in Python) but will + // usually be caught at the point of recording the exception in most languages.It + // is usually not possible to determine at the point where an exception is thrown + // whether it will escape the scope of a span. + // However, it is trivial to know that an exception + // will escape, if one checks for an active exception just before ending the span, + // as done in the example above.It follows that an exception may still escape the + // scope of the span + // even if the exception.escaped attribute was not set or set to false, + // since the event might have been recorded at a time where it was not + // clear whether the exception will escape. + AttributeExceptionEscaped = "exception.escaped" +) + +func GetEventSemanticConventionAttributeNames() []string { + return []string{ + AttributeFeatureFlagKey, + AttributeFeatureFlagProviderName, + AttributeFeatureFlagVariant, + AttributeMessageCompressedSize, + AttributeMessageID, + AttributeMessageType, + AttributeMessageUncompressedSize, + AttributeExceptionEscaped, + } +} diff --git a/semconv/v1.22.0/generated_resource.go b/semconv/v1.22.0/generated_resource.go new file mode 100644 index 00000000000..9c86ae85a73 --- /dev/null +++ b/semconv/v1.22.0/generated_resource.go @@ -0,0 +1,1473 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Code generated from semantic convention specification. DO NOT EDIT. + +package semconv + +// The Android platform on which the Android application is running. +const ( + // Uniquely identifies the framework API revision offered by a version + // (os.version) of the android operating system. More information can be found + // here. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '33', '32' + AttributeAndroidOSAPILevel = "android.os.api_level" +) + +// The web browser in which the application represented by the resource is +// running. The `browser.*` attributes MUST be used only for resources that +// represent applications running in a web browser (regardless of whether +// running on a mobile or desktop device). +const ( + // Array of brand name and version separated by a space + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: ' Not A;Brand 99', 'Chromium 99', 'Chrome 99' + // Note: This value is intended to be taken from the UA client hints API + // (navigator.userAgentData.brands). + AttributeBrowserBrands = "browser.brands" + // Preferred language of the user using the browser + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'en', 'en-US', 'fr', 'fr-FR' + // Note: This value is intended to be taken from the Navigator API + // navigator.language. + AttributeBrowserLanguage = "browser.language" + // A boolean that is true if the browser is running on a mobile device + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + // Note: This value is intended to be taken from the UA client hints API + // (navigator.userAgentData.mobile). If unavailable, this attribute SHOULD be left + // unset. + AttributeBrowserMobile = "browser.mobile" + // The platform on which the browser is running + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Windows', 'macOS', 'Android' + // Note: This value is intended to be taken from the UA client hints API + // (navigator.userAgentData.platform). If unavailable, the legacy + // navigator.platform API SHOULD NOT be used instead and this attribute SHOULD be + // left unset in order for the values to be consistent. + // The list of possible values is defined in the W3C User-Agent Client Hints + // specification. Note that some (but not all) of these values can overlap with + // values in the os.type and os.name attributes. However, for consistency, the + // values in the browser.platform attribute should capture the exact value that + // the user agent provides. + AttributeBrowserPlatform = "browser.platform" +) + +// A cloud environment (e.g. GCP, Azure, AWS) +const ( + // The cloud account ID the resource is assigned to. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '111111111111', 'opentelemetry' + AttributeCloudAccountID = "cloud.account.id" + // Cloud regions often have multiple, isolated locations known as zones to + // increase availability. Availability zone represents the zone where the resource + // is running. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'us-east-1c' + // Note: Availability zones are called "zones" on Alibaba Cloud and + // Google Cloud. + AttributeCloudAvailabilityZone = "cloud.availability_zone" + // The cloud platform in use. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Note: The prefix of the service SHOULD match the one specified in + // cloud.provider. + AttributeCloudPlatform = "cloud.platform" + // Name of the cloud provider. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeCloudProvider = "cloud.provider" + // The geographical region the resource is running. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'us-central1', 'us-east-1' + // Note: Refer to your provider's docs to see the available regions, for example + // Alibaba Cloud regions, AWS regions, Azure regions, Google Cloud regions, or + // Tencent Cloud regions. + AttributeCloudRegion = "cloud.region" + // Cloud provider-specific native identifier of the monitored cloud resource (e.g. + // an ARN on AWS, a fully qualified resource ID on Azure, a full resource name on + // GCP) + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:lambda:REGION:ACCOUNT_ID:function:my-function', '//run.googl + // eapis.com/projects/PROJECT_ID/locations/LOCATION_ID/services/SERVICE_ID', '/sub + // scriptions//resourceGroups//providers/Microsoft.Web/sites + // //functions/' + // Note: On some cloud providers, it may not be possible to determine the full ID + // at startup, + // so it may be necessary to set cloud.resource_id as a span attribute instead.The + // exact value to use for cloud.resource_id depends on the cloud provider. + // The following well-known definitions MUST be used if you set this attribute and + // they apply:
    + //
  • AWS Lambda: The function ARN. + // Take care not to use the "invoked ARN" directly but replace any + // alias suffix + // with the resolved function version, as the same runtime instance may be + // invokable with + // multiple different aliases.
  • + //
  • GCP: The URI of the resource
  • + //
  • Azure: The Fully Qualified Resource ID of the invoked function, + // not the function app, having the form + // /subscriptions//resourceGroups//providers/Microsoft.Web/s + // ites//functions/. + // This means that a span attribute MUST be used, as an Azure function app can + // host multiple functions that would usually share + // a TracerProvider.
  • + //
+ AttributeCloudResourceID = "cloud.resource_id" +) + +const ( + // Alibaba Cloud Elastic Compute Service + AttributeCloudPlatformAlibabaCloudECS = "alibaba_cloud_ecs" + // Alibaba Cloud Function Compute + AttributeCloudPlatformAlibabaCloudFc = "alibaba_cloud_fc" + // Red Hat OpenShift on Alibaba Cloud + AttributeCloudPlatformAlibabaCloudOpenshift = "alibaba_cloud_openshift" + // AWS Elastic Compute Cloud + AttributeCloudPlatformAWSEC2 = "aws_ec2" + // AWS Elastic Container Service + AttributeCloudPlatformAWSECS = "aws_ecs" + // AWS Elastic Kubernetes Service + AttributeCloudPlatformAWSEKS = "aws_eks" + // AWS Lambda + AttributeCloudPlatformAWSLambda = "aws_lambda" + // AWS Elastic Beanstalk + AttributeCloudPlatformAWSElasticBeanstalk = "aws_elastic_beanstalk" + // AWS App Runner + AttributeCloudPlatformAWSAppRunner = "aws_app_runner" + // Red Hat OpenShift on AWS (ROSA) + AttributeCloudPlatformAWSOpenshift = "aws_openshift" + // Azure Virtual Machines + AttributeCloudPlatformAzureVM = "azure_vm" + // Azure Container Instances + AttributeCloudPlatformAzureContainerInstances = "azure_container_instances" + // Azure Kubernetes Service + AttributeCloudPlatformAzureAKS = "azure_aks" + // Azure Functions + AttributeCloudPlatformAzureFunctions = "azure_functions" + // Azure App Service + AttributeCloudPlatformAzureAppService = "azure_app_service" + // Azure Red Hat OpenShift + AttributeCloudPlatformAzureOpenshift = "azure_openshift" + // Google Bare Metal Solution (BMS) + AttributeCloudPlatformGCPBareMetalSolution = "gcp_bare_metal_solution" + // Google Cloud Compute Engine (GCE) + AttributeCloudPlatformGCPComputeEngine = "gcp_compute_engine" + // Google Cloud Run + AttributeCloudPlatformGCPCloudRun = "gcp_cloud_run" + // Google Cloud Kubernetes Engine (GKE) + AttributeCloudPlatformGCPKubernetesEngine = "gcp_kubernetes_engine" + // Google Cloud Functions (GCF) + AttributeCloudPlatformGCPCloudFunctions = "gcp_cloud_functions" + // Google Cloud App Engine (GAE) + AttributeCloudPlatformGCPAppEngine = "gcp_app_engine" + // Red Hat OpenShift on Google Cloud + AttributeCloudPlatformGCPOpenshift = "gcp_openshift" + // Red Hat OpenShift on IBM Cloud + AttributeCloudPlatformIbmCloudOpenshift = "ibm_cloud_openshift" + // Tencent Cloud Cloud Virtual Machine (CVM) + AttributeCloudPlatformTencentCloudCvm = "tencent_cloud_cvm" + // Tencent Cloud Elastic Kubernetes Service (EKS) + AttributeCloudPlatformTencentCloudEKS = "tencent_cloud_eks" + // Tencent Cloud Serverless Cloud Function (SCF) + AttributeCloudPlatformTencentCloudScf = "tencent_cloud_scf" +) + +const ( + // Alibaba Cloud + AttributeCloudProviderAlibabaCloud = "alibaba_cloud" + // Amazon Web Services + AttributeCloudProviderAWS = "aws" + // Microsoft Azure + AttributeCloudProviderAzure = "azure" + // Google Cloud Platform + AttributeCloudProviderGCP = "gcp" + // Heroku Platform as a Service + AttributeCloudProviderHeroku = "heroku" + // IBM Cloud + AttributeCloudProviderIbmCloud = "ibm_cloud" + // Tencent Cloud + AttributeCloudProviderTencentCloud = "tencent_cloud" +) + +// Resources used by AWS Elastic Container Service (ECS). +const ( + // The ARN of an ECS cluster. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster' + AttributeAWSECSClusterARN = "aws.ecs.cluster.arn" + // The Amazon Resource Name (ARN) of an ECS container instance. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:ecs:us- + // west-1:123456789123:container/32624152-9086-4f0e-acae-1a75b14fe4d9' + AttributeAWSECSContainerARN = "aws.ecs.container.arn" + // The launch type for an ECS task. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeAWSECSLaunchtype = "aws.ecs.launchtype" + // The ARN of an ECS task definition. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:ecs:us- + // west-1:123456789123:task/10838bed-421f-43ef-870a-f43feacbbb5b' + AttributeAWSECSTaskARN = "aws.ecs.task.arn" + // The task definition family this task definition is a member of. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry-family' + AttributeAWSECSTaskFamily = "aws.ecs.task.family" + // The revision for this task definition. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '8', '26' + AttributeAWSECSTaskRevision = "aws.ecs.task.revision" +) + +const ( + // ec2 + AttributeAWSECSLaunchtypeEC2 = "ec2" + // fargate + AttributeAWSECSLaunchtypeFargate = "fargate" +) + +// Resources used by AWS Elastic Kubernetes Service (EKS). +const ( + // The ARN of an EKS cluster. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster' + AttributeAWSEKSClusterARN = "aws.eks.cluster.arn" +) + +// Resources specific to Amazon Web Services. +const ( + // The Amazon Resource Name(s) (ARN) of the AWS log group(s). + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:*' + // Note: See the log group ARN format documentation. + AttributeAWSLogGroupARNs = "aws.log.group.arns" + // The name(s) of the AWS log group(s) an application is writing to. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: '/aws/lambda/my-function', 'opentelemetry-service' + // Note: Multiple log groups must be supported for cases like multi-container + // applications, where a single application has sidecar containers, and each write + // to their own log group. + AttributeAWSLogGroupNames = "aws.log.group.names" + // The ARN(s) of the AWS log stream(s). + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:log- + // stream:logs/main/10838bed-421f-43ef-870a-f43feacbbb5b' + // Note: See the log stream ARN format documentation. One log group can contain + // several log streams, so these ARNs necessarily identify both a log group and a + // log stream. + AttributeAWSLogStreamARNs = "aws.log.stream.arns" + // The name(s) of the AWS log stream(s) an application is writing to. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'logs/main/10838bed-421f-43ef-870a-f43feacbbb5b' + AttributeAWSLogStreamNames = "aws.log.stream.names" +) + +// Resource used by Google Cloud Run. +const ( + // The name of the Cloud Run execution being run for the Job, as set by the + // CLOUD_RUN_EXECUTION environment variable. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'job-name-xxxx', 'sample-job-mdw84' + AttributeGCPCloudRunJobExecution = "gcp.cloud_run.job.execution" + // The index for a task within an execution as provided by the + // CLOUD_RUN_TASK_INDEX environment variable. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 0, 1 + AttributeGCPCloudRunJobTaskIndex = "gcp.cloud_run.job.task_index" +) + +// Resources used by Google Compute Engine (GCE). +const ( + // The hostname of a GCE instance. This is the full value of the default or custom + // hostname. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'my-host1234.example.com', 'sample-vm.us-west1-b.c.my- + // project.internal' + AttributeGCPGceInstanceHostname = "gcp.gce.instance.hostname" + // The instance name of a GCE instance. This is the value provided by host.name, + // the visible name of the instance in the Cloud Console UI, and the prefix for + // the default hostname of the instance as defined by the default internal DNS + // name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'instance-1', 'my-vm-name' + AttributeGCPGceInstanceName = "gcp.gce.instance.name" +) + +// Heroku dyno metadata +const ( + // Unique identifier for the application + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2daa2797-e42b-4624-9322-ec3f968df4da' + AttributeHerokuAppID = "heroku.app.id" + // Commit hash for the current release + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'e6134959463efd8966b20e75b913cafe3f5ec' + AttributeHerokuReleaseCommit = "heroku.release.commit" + // Time and date the release was created + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2022-10-23T18:00:42Z' + AttributeHerokuReleaseCreationTimestamp = "heroku.release.creation_timestamp" +) + +// A container instance. +const ( + // The command used to run the container (i.e. the command name). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'otelcontribcol' + // Note: If using embedded credentials or sensitive data, it is recommended to + // remove them to prevent potential leakage. + AttributeContainerCommand = "container.command" + // All the command arguments (including the command/executable itself) run by the + // container. [2] + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'otelcontribcol, --config, config.yaml' + AttributeContainerCommandArgs = "container.command_args" + // The full command run by the container as a single string representing the full + // command. [2] + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'otelcontribcol --config config.yaml' + AttributeContainerCommandLine = "container.command_line" + // Container ID. Usually a UUID, as for example used to identify Docker + // containers. The UUID might be abbreviated. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'a3bf90e006b2' + AttributeContainerID = "container.id" + // Runtime specific image identifier. Usually a hash algorithm followed by a UUID. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: + // 'sha256:19c92d0a00d1b66d897bceaa7319bee0dd38a10a851c60bcec9474aa3f01e50f' + // Note: Docker defines a sha256 of the image id; container.image.id corresponds + // to the Image field from the Docker container inspect API endpoint. + // K8S defines a link to the container registry repository with digest "imageID": + // "registry.azurecr.io /namespace/service/dockerfile@sha256:bdeabd40c3a8a492eaf9e + // 8e44d0ebbb84bac7ee25ac0cf8a7159d25f62555625". + // The ID is assinged by the container runtime and can vary in different + // environments. Consider using oci.manifest.digest if it is important to identify + // the same image in different environments/runtimes. + AttributeContainerImageID = "container.image.id" + // Name of the image the container was built on. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'gcr.io/opentelemetry/operator' + AttributeContainerImageName = "container.image.name" + // Repo digests of the container image as provided by the container runtime. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'example@sha256:afcc7f1ac1b49db317a7196c902e61c6c3c4607d63599ee1a82d7 + // 02d249a0ccb', 'internal.registry.example.com:5000/example@sha256:b69959407d21e8 + // a062e0416bf13405bb2b71ed7a84dde4158ebafacfa06f5578' + // Note: Docker and CRI report those under the RepoDigests field. + AttributeContainerImageRepoDigests = "container.image.repo_digests" + // Container image tags. An example can be found in Docker Image Inspect. Should + // be only the section of the full name for example from + // registry.example.com/my-org/my-image:. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'v1.27.1', '3.5.7-0' + AttributeContainerImageTags = "container.image.tags" + // Container name used by container runtime. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry-autoconf' + AttributeContainerName = "container.name" + // The container runtime managing this container. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'docker', 'containerd', 'rkt' + AttributeContainerRuntime = "container.runtime" +) + +// The software deployment. +const ( + // Name of the deployment environment (aka deployment tier). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'staging', 'production' + AttributeDeploymentEnvironment = "deployment.environment" +) + +// The device on which the process represented by this resource is running. +const ( + // A unique identifier representing the device + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2ab2916d-a51f-4ac8-80ee-45ac31a28092' + // Note: The device identifier MUST only be defined using the values outlined + // below. This value is not an advertising identifier and MUST NOT be used as + // such. On iOS (Swift or Objective-C), this value MUST be equal to the vendor + // identifier. On Android (Java or Kotlin), this value MUST be equal to the + // Firebase Installation ID or a globally unique UUID which is persisted across + // sessions in your application. More information can be found here on best + // practices and exact implementation details. Caution should be taken when + // storing personal data or anything which can identify a user. GDPR and data + // protection laws may apply, ensure you do your own due diligence. + AttributeDeviceID = "device.id" + // The name of the device manufacturer + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Apple', 'Samsung' + // Note: The Android OS provides this field via Build. iOS apps SHOULD hardcode + // the value Apple. + AttributeDeviceManufacturer = "device.manufacturer" + // The model identifier for the device + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'iPhone3,4', 'SM-G920F' + // Note: It's recommended this value represents a machine readable version of the + // model identifier rather than the market or consumer-friendly name of the + // device. + AttributeDeviceModelIdentifier = "device.model.identifier" + // The marketing name for the device model + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'iPhone 6s Plus', 'Samsung Galaxy S6' + // Note: It's recommended this value represents a human readable version of the + // device model rather than a machine readable alternative. + AttributeDeviceModelName = "device.model.name" +) + +// A serverless instance. +const ( + // The execution environment ID as a string, that will be potentially reused for + // other invocations to the same function/function version. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2021/06/28/[$LATEST]2f399eb14537447da05ab2a2e39309de' + // Note:
    + //
  • AWS Lambda: Use the (full) log stream name.
  • + //
+ AttributeFaaSInstance = "faas.instance" + // The amount of memory available to the serverless function converted to Bytes. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 134217728 + // Note: It's recommended to set this attribute since e.g. too little memory can + // easily stop a Java AWS Lambda function from working correctly. On AWS Lambda, + // the environment variable AWS_LAMBDA_FUNCTION_MEMORY_SIZE provides this + // information (which must be multiplied by 1,048,576). + AttributeFaaSMaxMemory = "faas.max_memory" + // The name of the single function that this runtime instance executes. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'my-function', 'myazurefunctionapp/some-function-name' + // Note: This is the name of the function as configured/deployed on the FaaS + // platform and is usually different from the name of the callback + // function (which may be stored in the + // code.namespace/code.function + // span attributes).For some cloud providers, the above definition is ambiguous. + // The following + // definition of function name MUST be used for this attribute + // (and consequently the span name) for the listed cloud providers/products:
    + //
  • Azure: The full name /, i.e., function app name + // followed by a forward slash followed by the function name (this form + // can also be seen in the resource JSON for the function). + // This means that a span attribute MUST be used, as an Azure function + // app can host multiple functions that would usually share + // a TracerProvider (see also the cloud.resource_id attribute).
  • + //
+ AttributeFaaSName = "faas.name" + // The immutable version of the function being executed. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '26', 'pinkfroid-00002' + // Note: Depending on the cloud provider and platform, use:
    + //
  • AWS Lambda: The function version + // (an integer represented as a decimal string).
  • + //
  • Google Cloud Run (Services): The revision + // (i.e., the function name plus the revision suffix).
  • + //
  • Google Cloud Functions: The value of the + // K_REVISION environment variable.
  • + //
  • Azure Functions: Not applicable. Do not set this attribute.
  • + //
+ AttributeFaaSVersion = "faas.version" +) + +// A host is defined as a computing instance. For example, physical servers, +// virtual machines, switches or disk array. +const ( + // The CPU architecture the host system is running on. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeHostArch = "host.arch" + // Unique host ID. For Cloud, this must be the instance_id assigned by the cloud + // provider. For non-containerized systems, this should be the machine-id. See the + // table below for the sources to use to determine the machine-id based on + // operating system. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'fdbf79e8af94cb7f9e8df36789187052' + AttributeHostID = "host.id" + // VM image ID or host OS image ID. For Cloud, this value is from the provider. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'ami-07b06b442921831e5' + AttributeHostImageID = "host.image.id" + // Name of the VM image or OS install the host was instantiated from. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'infra-ami-eks-worker-node-7d4ec78312', 'CentOS-8-x86_64-1905' + AttributeHostImageName = "host.image.name" + // The version string of the VM image or host OS as defined in Version Attributes. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '0.1' + AttributeHostImageVersion = "host.image.version" + // Available IP addresses of the host, excluding loopback interfaces. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: '192.168.1.140', 'fe80::abc2:4a28:737a:609e' + // Note: IPv4 Addresses MUST be specified in dotted-quad notation. IPv6 addresses + // MUST be specified in the RFC 5952 format. + AttributeHostIP = "host.ip" + // Name of the host. On Unix systems, it may contain what the hostname command + // returns, or the fully qualified hostname, or another name specified by the + // user. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry-test' + AttributeHostName = "host.name" + // Type of host. For Cloud, this must be the machine type. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'n1-standard-1' + AttributeHostType = "host.type" +) + +const ( + // AMD64 + AttributeHostArchAMD64 = "amd64" + // ARM32 + AttributeHostArchARM32 = "arm32" + // ARM64 + AttributeHostArchARM64 = "arm64" + // Itanium + AttributeHostArchIA64 = "ia64" + // 32-bit PowerPC + AttributeHostArchPPC32 = "ppc32" + // 64-bit PowerPC + AttributeHostArchPPC64 = "ppc64" + // IBM z/Architecture + AttributeHostArchS390x = "s390x" + // 32-bit x86 + AttributeHostArchX86 = "x86" +) + +// A host's CPU information +const ( + // The amount of level 2 memory cache available to the processor (in Bytes). + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 12288000 + AttributeHostCPUCacheL2Size = "host.cpu.cache.l2.size" + // Numeric value specifying the family or generation of the CPU. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 6 + AttributeHostCPUFamily = "host.cpu.family" + // Model identifier. It provides more granular information about the CPU, + // distinguishing it from other CPUs within the same family. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 6 + AttributeHostCPUModelID = "host.cpu.model.id" + // Model designation of the processor. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz' + AttributeHostCPUModelName = "host.cpu.model.name" + // Stepping or core revisions. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 1 + AttributeHostCPUStepping = "host.cpu.stepping" + // Processor manufacturer identifier. A maximum 12-character string. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'GenuineIntel' + // Note: CPUID command returns the vendor ID string in EBX, EDX and ECX registers. + // Writing these to memory in this order results in a 12-character string. + AttributeHostCPUVendorID = "host.cpu.vendor.id" +) + +// A Kubernetes Cluster. +const ( + // The name of the cluster. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry-cluster' + AttributeK8SClusterName = "k8s.cluster.name" + // A pseudo-ID for the cluster, set to the UID of the kube-system namespace. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '218fc5a9-a5f1-4b54-aa05-46717d0ab26d' + // Note: K8S does not have support for obtaining a cluster ID. If this is ever + // added, we will recommend collecting the k8s.cluster.uid through the + // official APIs. In the meantime, we are able to use the uid of the + // kube-system namespace as a proxy for cluster ID. Read on for the + // rationale.Every object created in a K8S cluster is assigned a distinct UID. The + // kube-system namespace is used by Kubernetes itself and will exist + // for the lifetime of the cluster. Using the uid of the kube-system + // namespace is a reasonable proxy for the K8S ClusterID as it will only + // change if the cluster is rebuilt. Furthermore, Kubernetes UIDs are + // UUIDs as standardized by + // ISO/IEC 9834-8 and ITU-T X.667. + // Which states:
+ // If generated according to one of the mechanisms defined in Rec.
+ // ITU-T X.667 | ISO/IEC 9834-8, a UUID is either guaranteed to be + // different from all other UUIDs generated before 3603 A.D., or is + // extremely likely to be different (depending on the mechanism + // chosen).Therefore, UIDs between clusters should be extremely unlikely to + // conflict. + AttributeK8SClusterUID = "k8s.cluster.uid" +) + +// A Kubernetes Node object. +const ( + // The name of the Node. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'node-1' + AttributeK8SNodeName = "k8s.node.name" + // The UID of the Node. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '1eb3a0c6-0477-4080-a9cb-0cb7db65c6a2' + AttributeK8SNodeUID = "k8s.node.uid" +) + +// A Kubernetes Namespace. +const ( + // The name of the namespace that the pod is running in. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'default' + AttributeK8SNamespaceName = "k8s.namespace.name" +) + +// A Kubernetes Pod object. +const ( + // The name of the Pod. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry-pod-autoconf' + AttributeK8SPodName = "k8s.pod.name" + // The UID of the Pod. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + AttributeK8SPodUID = "k8s.pod.uid" +) + +// A container in a +// [PodTemplate](https://kubernetes.io/docs/concepts/workloads/pods/#pod-templates). +const ( + // The name of the Container from Pod specification, must be unique within a Pod. + // Container runtime usually uses different globally unique name (container.name). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'redis' + AttributeK8SContainerName = "k8s.container.name" + // Number of times the container was restarted. This attribute can be used to + // identify a particular container (running or stopped) within a container spec. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 0, 2 + AttributeK8SContainerRestartCount = "k8s.container.restart_count" +) + +// A Kubernetes ReplicaSet object. +const ( + // The name of the ReplicaSet. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry' + AttributeK8SReplicaSetName = "k8s.replicaset.name" + // The UID of the ReplicaSet. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + AttributeK8SReplicaSetUID = "k8s.replicaset.uid" +) + +// A Kubernetes Deployment object. +const ( + // The name of the Deployment. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry' + AttributeK8SDeploymentName = "k8s.deployment.name" + // The UID of the Deployment. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + AttributeK8SDeploymentUID = "k8s.deployment.uid" +) + +// A Kubernetes StatefulSet object. +const ( + // The name of the StatefulSet. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry' + AttributeK8SStatefulSetName = "k8s.statefulset.name" + // The UID of the StatefulSet. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + AttributeK8SStatefulSetUID = "k8s.statefulset.uid" +) + +// A Kubernetes DaemonSet object. +const ( + // The name of the DaemonSet. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry' + AttributeK8SDaemonSetName = "k8s.daemonset.name" + // The UID of the DaemonSet. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + AttributeK8SDaemonSetUID = "k8s.daemonset.uid" +) + +// A Kubernetes Job object. +const ( + // The name of the Job. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry' + AttributeK8SJobName = "k8s.job.name" + // The UID of the Job. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + AttributeK8SJobUID = "k8s.job.uid" +) + +// A Kubernetes CronJob object. +const ( + // The name of the CronJob. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry' + AttributeK8SCronJobName = "k8s.cronjob.name" + // The UID of the CronJob. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + AttributeK8SCronJobUID = "k8s.cronjob.uid" +) + +// An OCI image manifest. +const ( + // The digest of the OCI image manifest. For container images specifically is the + // digest by which the container image is known. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: + // 'sha256:e4ca62c0d62f3e886e684806dfe9d4e0cda60d54986898173c1083856cfda0f4' + // Note: Follows OCI Image Manifest Specification, and specifically the Digest + // property. + // An example can be found in Example Image Manifest. + AttributeOciManifestDigest = "oci.manifest.digest" +) + +// The operating system (OS) on which the process represented by this resource +// is running. +const ( + // Unique identifier for a particular build or compilation of the operating + // system. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'TQ3C.230805.001.B2', '20E247', '22621' + AttributeOSBuildID = "os.build_id" + // Human readable (not intended to be parsed) OS version information, like e.g. + // reported by ver or lsb_release -a commands. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Microsoft Windows [Version 10.0.18363.778]', 'Ubuntu 18.04.1 LTS' + AttributeOSDescription = "os.description" + // Human readable operating system name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'iOS', 'Android', 'Ubuntu' + AttributeOSName = "os.name" + // The operating system type. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + AttributeOSType = "os.type" + // The version string of the operating system as defined in Version Attributes. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '14.2.1', '18.04.1' + AttributeOSVersion = "os.version" +) + +const ( + // Microsoft Windows + AttributeOSTypeWindows = "windows" + // Linux + AttributeOSTypeLinux = "linux" + // Apple Darwin + AttributeOSTypeDarwin = "darwin" + // FreeBSD + AttributeOSTypeFreeBSD = "freebsd" + // NetBSD + AttributeOSTypeNetBSD = "netbsd" + // OpenBSD + AttributeOSTypeOpenBSD = "openbsd" + // DragonFly BSD + AttributeOSTypeDragonflyBSD = "dragonflybsd" + // HP-UX (Hewlett Packard Unix) + AttributeOSTypeHPUX = "hpux" + // AIX (Advanced Interactive eXecutive) + AttributeOSTypeAIX = "aix" + // SunOS, Oracle Solaris + AttributeOSTypeSolaris = "solaris" + // IBM z/OS + AttributeOSTypeZOS = "z_os" +) + +// An operating system process. +const ( + // The command used to launch the process (i.e. the command name). On Linux based + // systems, can be set to the zeroth string in proc/[pid]/cmdline. On Windows, can + // be set to the first parameter extracted from GetCommandLineW. + // + // Type: string + // Requirement Level: Conditionally Required - See alternative attributes below. + // Stability: experimental + // Examples: 'cmd/otelcol' + AttributeProcessCommand = "process.command" + // All the command arguments (including the command/executable itself) as received + // by the process. On Linux-based systems (and some other Unixoid systems + // supporting procfs), can be set according to the list of null-delimited strings + // extracted from proc/[pid]/cmdline. For libc-based executables, this would be + // the full argv vector passed to main. + // + // Type: string[] + // Requirement Level: Conditionally Required - See alternative attributes below. + // Stability: experimental + // Examples: 'cmd/otecol', '--config=config.yaml' + AttributeProcessCommandArgs = "process.command_args" + // The full command used to launch the process as a single string representing the + // full command. On Windows, can be set to the result of GetCommandLineW. Do not + // set this if you have to assemble it just for monitoring; use + // process.command_args instead. + // + // Type: string + // Requirement Level: Conditionally Required - See alternative attributes below. + // Stability: experimental + // Examples: 'C:\\cmd\\otecol --config="my directory\\config.yaml"' + AttributeProcessCommandLine = "process.command_line" + // The name of the process executable. On Linux based systems, can be set to the + // Name in proc/[pid]/status. On Windows, can be set to the base name of + // GetProcessImageFileNameW. + // + // Type: string + // Requirement Level: Conditionally Required - See alternative attributes below. + // Stability: experimental + // Examples: 'otelcol' + AttributeProcessExecutableName = "process.executable.name" + // The full path to the process executable. On Linux based systems, can be set to + // the target of proc/[pid]/exe. On Windows, can be set to the result of + // GetProcessImageFileNameW. + // + // Type: string + // Requirement Level: Conditionally Required - See alternative attributes below. + // Stability: experimental + // Examples: '/usr/bin/cmd/otelcol' + AttributeProcessExecutablePath = "process.executable.path" + // The username of the user that owns the process. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'root' + AttributeProcessOwner = "process.owner" + // Parent Process identifier (PID). + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 111 + AttributeProcessParentPID = "process.parent_pid" + // Process identifier (PID). + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 1234 + AttributeProcessPID = "process.pid" +) + +// The single (language) runtime instance which is monitored. +const ( + // An additional description about the runtime of the process, for example a + // specific vendor customization of the runtime environment. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Eclipse OpenJ9 Eclipse OpenJ9 VM openj9-0.21.0' + AttributeProcessRuntimeDescription = "process.runtime.description" + // The name of the runtime of this process. For compiled native binaries, this + // SHOULD be the name of the compiler. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'OpenJDK Runtime Environment' + AttributeProcessRuntimeName = "process.runtime.name" + // The version of the runtime of this process, as returned by the runtime without + // modification. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '14.0.2' + AttributeProcessRuntimeVersion = "process.runtime.version" +) + +// A service instance. +const ( + // Logical name of the service. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'shoppingcart' + // Note: MUST be the same for all instances of horizontally scaled services. If + // the value was not specified, SDKs MUST fallback to unknown_service: + // concatenated with process.executable.name, e.g. unknown_service:bash. If + // process.executable.name is not available, the value MUST be set to + // unknown_service. + AttributeServiceName = "service.name" + // The version string of the service API or implementation. The format is not + // defined by these conventions. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2.0.0', 'a01dbef8a' + AttributeServiceVersion = "service.version" +) + +// A service instance. +const ( + // The string ID of the service instance. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'my-k8s-pod-deployment-1', '627cc493-f310-47de-96bd-71410b7dec09' + // Note: MUST be unique for each instance of the same + // service.namespace,service.name pair (in other words + // service.namespace,service.name,service.instance.id triplet MUST be globally + // unique). The ID helps to distinguish instances of the same service that exist + // at the same time (e.g. instances of a horizontally scaled service). It is + // preferable for the ID to be persistent and stay the same for the lifetime of + // the service instance, however it is acceptable that the ID is ephemeral and + // changes during important lifetime events for the service (e.g. service + // restarts). If the service has no inherent unique ID that can be used as the + // value of this attribute it is recommended to generate a random Version 1 or + // Version 4 RFC 4122 UUID (services aiming for reproducible UUIDs may also use + // Version 5, see RFC 4122 for more recommendations). + AttributeServiceInstanceID = "service.instance.id" + // A namespace for service.name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Shop' + // Note: A string value having a meaning that helps to distinguish a group of + // services, for example the team name that owns a group of services. service.name + // is expected to be unique within the same namespace. If service.namespace is not + // specified in the Resource then service.name is expected to be unique for all + // services that have no explicit namespace defined (so the empty/unspecified + // namespace is simply one more valid namespace). Zero-length namespace string is + // assumed equal to unspecified namespace. + AttributeServiceNamespace = "service.namespace" +) + +// The telemetry SDK used to capture data recorded by the instrumentation +// libraries. +const ( + // The language of the telemetry SDK. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + AttributeTelemetrySDKLanguage = "telemetry.sdk.language" + // The name of the telemetry SDK as defined above. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'opentelemetry' + // Note: The OpenTelemetry SDK MUST set the telemetry.sdk.name attribute to + // opentelemetry. + // If another SDK, like a fork or a vendor-provided implementation, is used, this + // SDK MUST set the + // telemetry.sdk.name attribute to the fully-qualified class or module name of + // this SDK's main entry point + // or another suitable identifier depending on the language. + // The identifier opentelemetry is reserved and MUST NOT be used in this case. + // All custom identifiers SHOULD be stable across different versions of an + // implementation. + AttributeTelemetrySDKName = "telemetry.sdk.name" + // The version string of the telemetry SDK. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: '1.2.3' + AttributeTelemetrySDKVersion = "telemetry.sdk.version" +) + +const ( + // cpp + AttributeTelemetrySDKLanguageCPP = "cpp" + // dotnet + AttributeTelemetrySDKLanguageDotnet = "dotnet" + // erlang + AttributeTelemetrySDKLanguageErlang = "erlang" + // go + AttributeTelemetrySDKLanguageGo = "go" + // java + AttributeTelemetrySDKLanguageJava = "java" + // nodejs + AttributeTelemetrySDKLanguageNodejs = "nodejs" + // php + AttributeTelemetrySDKLanguagePHP = "php" + // python + AttributeTelemetrySDKLanguagePython = "python" + // ruby + AttributeTelemetrySDKLanguageRuby = "ruby" + // rust + AttributeTelemetrySDKLanguageRust = "rust" + // swift + AttributeTelemetrySDKLanguageSwift = "swift" + // webjs + AttributeTelemetrySDKLanguageWebjs = "webjs" +) + +// The telemetry SDK used to capture data recorded by the instrumentation +// libraries. +const ( + // The name of the auto instrumentation agent or distribution, if used. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'parts-unlimited-java' + // Note: Official auto instrumentation agents and distributions SHOULD set the + // telemetry.distro.name attribute to + // a string starting with opentelemetry-, e.g. opentelemetry-java-instrumentation. + AttributeTelemetryDistroName = "telemetry.distro.name" + // The version string of the auto instrumentation agent or distribution, if used. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '1.2.3' + AttributeTelemetryDistroVersion = "telemetry.distro.version" +) + +// Resource describing the packaged software running the application code. Web +// engines are typically executed using process.runtime. +const ( + // Additional description of the web engine (e.g. detailed version and edition + // information). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'WildFly Full 21.0.0.Final (WildFly Core 13.0.1.Final) - 2.2.2.Final' + AttributeWebEngineDescription = "webengine.description" + // The name of the web engine. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'WildFly' + AttributeWebEngineName = "webengine.name" + // The version of the web engine. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '21.0.0' + AttributeWebEngineVersion = "webengine.version" +) + +// Attributes used by non-OTLP exporters to represent OpenTelemetry Scope's +// concepts. +const ( + // The name of the instrumentation scope - (InstrumentationScope.Name in OTLP). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'io.opentelemetry.contrib.mongodb' + AttributeOTelScopeName = "otel.scope.name" + // The version of the instrumentation scope - (InstrumentationScope.Version in + // OTLP). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '1.0.0' + AttributeOTelScopeVersion = "otel.scope.version" +) + +// Span attributes used by non-OTLP exporters to represent OpenTelemetry +// Scope's concepts. +const ( + // Deprecated, use the otel.scope.name attribute. + // + // Type: string + // Requirement Level: Optional + // Stability: deprecated + // Examples: 'io.opentelemetry.contrib.mongodb' + AttributeOTelLibraryName = "otel.library.name" + // Deprecated, use the otel.scope.version attribute. + // + // Type: string + // Requirement Level: Optional + // Stability: deprecated + // Examples: '1.0.0' + AttributeOTelLibraryVersion = "otel.library.version" +) + +func GetResourceSemanticConventionAttributeNames() []string { + return []string{ + AttributeAndroidOSAPILevel, + AttributeBrowserBrands, + AttributeBrowserLanguage, + AttributeBrowserMobile, + AttributeBrowserPlatform, + AttributeCloudAccountID, + AttributeCloudAvailabilityZone, + AttributeCloudPlatform, + AttributeCloudProvider, + AttributeCloudRegion, + AttributeCloudResourceID, + AttributeAWSECSClusterARN, + AttributeAWSECSContainerARN, + AttributeAWSECSLaunchtype, + AttributeAWSECSTaskARN, + AttributeAWSECSTaskFamily, + AttributeAWSECSTaskRevision, + AttributeAWSEKSClusterARN, + AttributeAWSLogGroupARNs, + AttributeAWSLogGroupNames, + AttributeAWSLogStreamARNs, + AttributeAWSLogStreamNames, + AttributeGCPCloudRunJobExecution, + AttributeGCPCloudRunJobTaskIndex, + AttributeGCPGceInstanceHostname, + AttributeGCPGceInstanceName, + AttributeHerokuAppID, + AttributeHerokuReleaseCommit, + AttributeHerokuReleaseCreationTimestamp, + AttributeContainerCommand, + AttributeContainerCommandArgs, + AttributeContainerCommandLine, + AttributeContainerID, + AttributeContainerImageID, + AttributeContainerImageName, + AttributeContainerImageRepoDigests, + AttributeContainerImageTags, + AttributeContainerName, + AttributeContainerRuntime, + AttributeDeploymentEnvironment, + AttributeDeviceID, + AttributeDeviceManufacturer, + AttributeDeviceModelIdentifier, + AttributeDeviceModelName, + AttributeFaaSInstance, + AttributeFaaSMaxMemory, + AttributeFaaSName, + AttributeFaaSVersion, + AttributeHostArch, + AttributeHostID, + AttributeHostImageID, + AttributeHostImageName, + AttributeHostImageVersion, + AttributeHostIP, + AttributeHostName, + AttributeHostType, + AttributeHostCPUCacheL2Size, + AttributeHostCPUFamily, + AttributeHostCPUModelID, + AttributeHostCPUModelName, + AttributeHostCPUStepping, + AttributeHostCPUVendorID, + AttributeK8SClusterName, + AttributeK8SClusterUID, + AttributeK8SNodeName, + AttributeK8SNodeUID, + AttributeK8SNamespaceName, + AttributeK8SPodName, + AttributeK8SPodUID, + AttributeK8SContainerName, + AttributeK8SContainerRestartCount, + AttributeK8SReplicaSetName, + AttributeK8SReplicaSetUID, + AttributeK8SDeploymentName, + AttributeK8SDeploymentUID, + AttributeK8SStatefulSetName, + AttributeK8SStatefulSetUID, + AttributeK8SDaemonSetName, + AttributeK8SDaemonSetUID, + AttributeK8SJobName, + AttributeK8SJobUID, + AttributeK8SCronJobName, + AttributeK8SCronJobUID, + AttributeOciManifestDigest, + AttributeOSBuildID, + AttributeOSDescription, + AttributeOSName, + AttributeOSType, + AttributeOSVersion, + AttributeProcessCommand, + AttributeProcessCommandArgs, + AttributeProcessCommandLine, + AttributeProcessExecutableName, + AttributeProcessExecutablePath, + AttributeProcessOwner, + AttributeProcessParentPID, + AttributeProcessPID, + AttributeProcessRuntimeDescription, + AttributeProcessRuntimeName, + AttributeProcessRuntimeVersion, + AttributeServiceName, + AttributeServiceVersion, + AttributeServiceInstanceID, + AttributeServiceNamespace, + AttributeTelemetrySDKLanguage, + AttributeTelemetrySDKName, + AttributeTelemetrySDKVersion, + AttributeTelemetryDistroName, + AttributeTelemetryDistroVersion, + AttributeWebEngineDescription, + AttributeWebEngineName, + AttributeWebEngineVersion, + AttributeOTelScopeName, + AttributeOTelScopeVersion, + AttributeOTelLibraryName, + AttributeOTelLibraryVersion, + } +} diff --git a/semconv/v1.22.0/generated_trace.go b/semconv/v1.22.0/generated_trace.go new file mode 100644 index 00000000000..2630302dae1 --- /dev/null +++ b/semconv/v1.22.0/generated_trace.go @@ -0,0 +1,1471 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Code generated from semantic convention specification. DO NOT EDIT. + +package semconv + +// The shared attributes used to report a single exception associated with a +// span or log. +const ( + // The exception message. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Division by zero', "Can't convert 'int' object to str implicitly" + AttributeExceptionMessage = "exception.message" + // A stacktrace as a string in the natural representation for the language + // runtime. The representation is to be determined and documented by each language + // SIG. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Exception in thread "main" java.lang.RuntimeException: Test + // exception\\n at ' + // 'com.example.GenerateTrace.methodB(GenerateTrace.java:13)\\n at ' + // 'com.example.GenerateTrace.methodA(GenerateTrace.java:9)\\n at ' + // 'com.example.GenerateTrace.main(GenerateTrace.java:5)' + AttributeExceptionStacktrace = "exception.stacktrace" + // The type of the exception (its fully-qualified class name, if applicable). The + // dynamic type of the exception should be preferred over the static type in + // languages that support it. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'java.net.ConnectException', 'OSError' + AttributeExceptionType = "exception.type" +) + +// Operations that access some remote service. +const ( + // The service.name of the remote service. SHOULD be equal to the actual + // service.name resource attribute of the remote service if any. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'AuthTokenCache' + AttributePeerService = "peer.service" +) + +// These attributes may be used for any operation with an authenticated and/or +// authorized enduser. +const ( + // Username or client_id extracted from the access token or Authorization header + // in the inbound request from outside the system. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'username' + AttributeEnduserID = "enduser.id" + // Actual/assumed role the client is making the request under extracted from token + // or application security context. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'admin' + AttributeEnduserRole = "enduser.role" + // Scopes or granted authorities the client currently possesses extracted from + // token or application security context. The value would come from the scope + // associated with an OAuth 2.0 Access Token or an attribute value in a SAML 2.0 + // Assertion. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'read:message, write:files' + AttributeEnduserScope = "enduser.scope" +) + +// These attributes may be used for any operation to store information about a +// thread that started a span. +const ( + // Whether the thread is daemon or not. + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + AttributeThreadDaemon = "thread.daemon" + // Current "managed" thread ID (as opposed to OS thread ID). + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 42 + AttributeThreadID = "thread.id" + // Current thread name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'main' + AttributeThreadName = "thread.name" +) + +// These attributes allow to report this unit of code and therefore to provide +// more context about the span. +const ( + // The column number in code.filepath best representing the operation. It SHOULD + // point within the code unit named in code.function. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 16 + AttributeCodeColumn = "code.column" + // The source code file name that identifies the code unit as uniquely as possible + // (preferably an absolute file path). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '/usr/local/MyApplication/content_root/app/index.php' + AttributeCodeFilepath = "code.filepath" + // The method or function name, or equivalent (usually rightmost part of the code + // unit's name). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'serveRequest' + AttributeCodeFunction = "code.function" + // The line number in code.filepath best representing the operation. It SHOULD + // point within the code unit named in code.function. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 42 + AttributeCodeLineNumber = "code.lineno" + // The "namespace" within which code.function is defined. Usually the + // qualified class or module name, such that code.namespace + some separator + + // code.function form a unique identifier for the code unit. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'com.example.MyHTTPService' + AttributeCodeNamespace = "code.namespace" +) + +// Span attributes used by AWS Lambda (in addition to general `faas` +// attributes). +const ( + // The full invoked ARN as provided on the Context passed to the function (Lambda- + // Runtime-Invoked-Function-ARN header on the /runtime/invocation/next + // applicable). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:lambda:us-east-1:123456:function:myfunction:myalias' + // Note: This may be different from cloud.resource_id if an alias is involved. + AttributeAWSLambdaInvokedARN = "aws.lambda.invoked_arn" +) + +// Attributes for CloudEvents. CloudEvents is a specification on how to define +// event data in a standard way. These attributes can be attached to spans when +// performing operations with CloudEvents, regardless of the protocol being +// used. +const ( + // The event_id uniquely identifies the event. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: '123e4567-e89b-12d3-a456-426614174000', '0001' + AttributeCloudeventsEventID = "cloudevents.event_id" + // The source identifies the context in which an event happened. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'https://github.com/cloudevents', '/cloudevents/spec/pull/123', 'my- + // service' + AttributeCloudeventsEventSource = "cloudevents.event_source" + // The version of the CloudEvents specification which the event uses. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '1.0' + AttributeCloudeventsEventSpecVersion = "cloudevents.event_spec_version" + // The subject of the event in the context of the event producer (identified by + // source). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'mynewfile.jpg' + AttributeCloudeventsEventSubject = "cloudevents.event_subject" + // The event_type contains a value describing the type of event related to the + // originating occurrence. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'com.github.pull_request.opened', 'com.example.object.deleted.v2' + AttributeCloudeventsEventType = "cloudevents.event_type" +) + +// Semantic conventions for the OpenTracing Shim +const ( + // Parent-child Reference type + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Note: The causal relationship between a child Span and a parent Span. + AttributeOpentracingRefType = "opentracing.ref_type" +) + +const ( + // The parent Span depends on the child Span in some capacity + AttributeOpentracingRefTypeChildOf = "child_of" + // The parent Span does not depend in any way on the result of the child Span + AttributeOpentracingRefTypeFollowsFrom = "follows_from" +) + +// The attributes used to perform database client calls. +const ( + // The connection string used to connect to the database. It is recommended to + // remove embedded credentials. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Server=(localdb)\\v11.0;Integrated Security=true;' + AttributeDBConnectionString = "db.connection_string" + // The fully-qualified class name of the Java Database Connectivity (JDBC) driver + // used to connect. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'org.postgresql.Driver', + // 'com.microsoft.sqlserver.jdbc.SQLServerDriver' + AttributeDBJDBCDriverClassname = "db.jdbc.driver_classname" + // This attribute is used to report the name of the database being accessed. For + // commands that switch the database, this should be set to the target database + // (even if the command fails). + // + // Type: string + // Requirement Level: Conditionally Required - If applicable. + // Stability: experimental + // Examples: 'customers', 'main' + // Note: In some SQL databases, the database name to be used is called + // "schema name". In case there are multiple layers that could be + // considered for database name (e.g. Oracle instance name and schema name), the + // database name to be used is the more specific layer (e.g. Oracle schema name). + AttributeDBName = "db.name" + // The name of the operation being executed, e.g. the MongoDB command name such as + // findAndModify, or the SQL keyword. + // + // Type: string + // Requirement Level: Conditionally Required - If `db.statement` is not + // applicable. + // Stability: experimental + // Examples: 'findAndModify', 'HMSET', 'SELECT' + // Note: When setting this to an SQL keyword, it is not recommended to attempt any + // client-side parsing of db.statement just to get this property, but it should be + // set if the operation name is provided by the library being instrumented. If the + // SQL statement has an ambiguous operation, or performs more than one operation, + // this value may be omitted. + AttributeDBOperation = "db.operation" + // The database statement being executed. + // + // Type: string + // Requirement Level: Recommended - Should be collected by default only if there + // is sanitization that excludes sensitive information. + // Stability: experimental + // Examples: 'SELECT * FROM wuser_table', 'SET mykey "WuValue"' + AttributeDBStatement = "db.statement" + // An identifier for the database management system (DBMS) product being used. See + // below for a list of well-known identifiers. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + AttributeDBSystem = "db.system" + // Username for accessing the database. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'readonly_user', 'reporting_user' + AttributeDBUser = "db.user" +) + +const ( + // Some other SQL database. Fallback only. See notes + AttributeDBSystemOtherSQL = "other_sql" + // Microsoft SQL Server + AttributeDBSystemMSSQL = "mssql" + // Microsoft SQL Server Compact + AttributeDBSystemMssqlcompact = "mssqlcompact" + // MySQL + AttributeDBSystemMySQL = "mysql" + // Oracle Database + AttributeDBSystemOracle = "oracle" + // IBM DB2 + AttributeDBSystemDB2 = "db2" + // PostgreSQL + AttributeDBSystemPostgreSQL = "postgresql" + // Amazon Redshift + AttributeDBSystemRedshift = "redshift" + // Apache Hive + AttributeDBSystemHive = "hive" + // Cloudscape + AttributeDBSystemCloudscape = "cloudscape" + // HyperSQL DataBase + AttributeDBSystemHSQLDB = "hsqldb" + // Progress Database + AttributeDBSystemProgress = "progress" + // SAP MaxDB + AttributeDBSystemMaxDB = "maxdb" + // SAP HANA + AttributeDBSystemHanaDB = "hanadb" + // Ingres + AttributeDBSystemIngres = "ingres" + // FirstSQL + AttributeDBSystemFirstSQL = "firstsql" + // EnterpriseDB + AttributeDBSystemEDB = "edb" + // InterSystems Caché + AttributeDBSystemCache = "cache" + // Adabas (Adaptable Database System) + AttributeDBSystemAdabas = "adabas" + // Firebird + AttributeDBSystemFirebird = "firebird" + // Apache Derby + AttributeDBSystemDerby = "derby" + // FileMaker + AttributeDBSystemFilemaker = "filemaker" + // Informix + AttributeDBSystemInformix = "informix" + // InstantDB + AttributeDBSystemInstantDB = "instantdb" + // InterBase + AttributeDBSystemInterbase = "interbase" + // MariaDB + AttributeDBSystemMariaDB = "mariadb" + // Netezza + AttributeDBSystemNetezza = "netezza" + // Pervasive PSQL + AttributeDBSystemPervasive = "pervasive" + // PointBase + AttributeDBSystemPointbase = "pointbase" + // SQLite + AttributeDBSystemSqlite = "sqlite" + // Sybase + AttributeDBSystemSybase = "sybase" + // Teradata + AttributeDBSystemTeradata = "teradata" + // Vertica + AttributeDBSystemVertica = "vertica" + // H2 + AttributeDBSystemH2 = "h2" + // ColdFusion IMQ + AttributeDBSystemColdfusion = "coldfusion" + // Apache Cassandra + AttributeDBSystemCassandra = "cassandra" + // Apache HBase + AttributeDBSystemHBase = "hbase" + // MongoDB + AttributeDBSystemMongoDB = "mongodb" + // Redis + AttributeDBSystemRedis = "redis" + // Couchbase + AttributeDBSystemCouchbase = "couchbase" + // CouchDB + AttributeDBSystemCouchDB = "couchdb" + // Microsoft Azure Cosmos DB + AttributeDBSystemCosmosDB = "cosmosdb" + // Amazon DynamoDB + AttributeDBSystemDynamoDB = "dynamodb" + // Neo4j + AttributeDBSystemNeo4j = "neo4j" + // Apache Geode + AttributeDBSystemGeode = "geode" + // Elasticsearch + AttributeDBSystemElasticsearch = "elasticsearch" + // Memcached + AttributeDBSystemMemcached = "memcached" + // CockroachDB + AttributeDBSystemCockroachdb = "cockroachdb" + // OpenSearch + AttributeDBSystemOpensearch = "opensearch" + // ClickHouse + AttributeDBSystemClickhouse = "clickhouse" + // Cloud Spanner + AttributeDBSystemSpanner = "spanner" + // Trino + AttributeDBSystemTrino = "trino" +) + +// Connection-level attributes for Microsoft SQL Server +const ( + // The Microsoft SQL Server instance name connecting to. This name is used to + // determine the port of a named instance. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'MSSQLSERVER' + // Note: If setting a db.mssql.instance_name, server.port is no longer required + // (but still recommended if non-standard). + AttributeDBMSSQLInstanceName = "db.mssql.instance_name" +) + +// Call-level attributes for Cassandra +const ( + // The consistency level of the query. Based on consistency values from CQL. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeDBCassandraConsistencyLevel = "db.cassandra.consistency_level" + // The data center of the coordinating node for a query. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'us-west-2' + AttributeDBCassandraCoordinatorDC = "db.cassandra.coordinator.dc" + // The ID of the coordinating node for a query. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'be13faa2-8574-4d71-926d-27f16cf8a7af' + AttributeDBCassandraCoordinatorID = "db.cassandra.coordinator.id" + // Whether or not the query is idempotent. + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + AttributeDBCassandraIdempotence = "db.cassandra.idempotence" + // The fetch size used for paging, i.e. how many rows will be returned at once. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 5000 + AttributeDBCassandraPageSize = "db.cassandra.page_size" + // The number of times a query was speculatively executed. Not set or 0 if the + // query was not executed speculatively. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 0, 2 + AttributeDBCassandraSpeculativeExecutionCount = "db.cassandra.speculative_execution_count" + // The name of the primary table that the operation is acting upon, including the + // keyspace name (if applicable). + // + // Type: string + // Requirement Level: Recommended + // Stability: experimental + // Examples: 'mytable' + // Note: This mirrors the db.sql.table attribute but references cassandra rather + // than sql. It is not recommended to attempt any client-side parsing of + // db.statement just to get this property, but it should be set if it is provided + // by the library being instrumented. If the operation is acting upon an anonymous + // table, or more than one table, this value MUST NOT be set. + AttributeDBCassandraTable = "db.cassandra.table" +) + +const ( + // all + AttributeDBCassandraConsistencyLevelAll = "all" + // each_quorum + AttributeDBCassandraConsistencyLevelEachQuorum = "each_quorum" + // quorum + AttributeDBCassandraConsistencyLevelQuorum = "quorum" + // local_quorum + AttributeDBCassandraConsistencyLevelLocalQuorum = "local_quorum" + // one + AttributeDBCassandraConsistencyLevelOne = "one" + // two + AttributeDBCassandraConsistencyLevelTwo = "two" + // three + AttributeDBCassandraConsistencyLevelThree = "three" + // local_one + AttributeDBCassandraConsistencyLevelLocalOne = "local_one" + // any + AttributeDBCassandraConsistencyLevelAny = "any" + // serial + AttributeDBCassandraConsistencyLevelSerial = "serial" + // local_serial + AttributeDBCassandraConsistencyLevelLocalSerial = "local_serial" +) + +// Call-level attributes for Redis +const ( + // The index of the database being accessed as used in the SELECT command, + // provided as an integer. To be used instead of the generic db.name attribute. + // + // Type: int + // Requirement Level: Conditionally Required - If other than the default database + // (`0`). + // Stability: experimental + // Examples: 0, 1, 15 + AttributeDBRedisDBIndex = "db.redis.database_index" +) + +// Call-level attributes for MongoDB +const ( + // The collection being accessed within the database stated in db.name. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'customers', 'products' + AttributeDBMongoDBCollection = "db.mongodb.collection" +) + +// Call-level attributes for Elasticsearch +const ( + // Represents the identifier of an Elasticsearch cluster. + // + // Type: string + // Requirement Level: Recommended - When communicating with an Elastic Cloud + // deployment, this should be collected from the "X-Found-Handling-Cluster" HTTP + // response header. + // Stability: experimental + // Examples: 'e9106fc68e3044f0b1475b04bf4ffd5f' + AttributeDBElasticsearchClusterName = "db.elasticsearch.cluster.name" + // Represents the human-readable identifier of the node/instance to which a + // request was routed. + // + // Type: string + // Requirement Level: Recommended - When communicating with an Elastic Cloud + // deployment, this should be collected from the "X-Found-Handling-Instance" HTTP + // response header. + // Stability: experimental + // Examples: 'instance-0000000001' + AttributeDBElasticsearchNodeName = "db.elasticsearch.node.name" +) + +// Call-level attributes for SQL databases +const ( + // The name of the primary table that the operation is acting upon, including the + // database name (if applicable). + // + // Type: string + // Requirement Level: Recommended + // Stability: experimental + // Examples: 'public.users', 'customers' + // Note: It is not recommended to attempt any client-side parsing of db.statement + // just to get this property, but it should be set if it is provided by the + // library being instrumented. If the operation is acting upon an anonymous table, + // or more than one table, this value MUST NOT be set. + AttributeDBSQLTable = "db.sql.table" +) + +// Call-level attributes for Cosmos DB. +const ( + // Unique Cosmos client instance id. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '3ba4827d-4422-483f-b59f-85b74211c11d' + AttributeDBCosmosDBClientID = "db.cosmosdb.client_id" + // Cosmos client connection mode. + // + // Type: Enum + // Requirement Level: Conditionally Required - if not `direct` (or pick gw as + // default) + // Stability: experimental + AttributeDBCosmosDBConnectionMode = "db.cosmosdb.connection_mode" + // Cosmos DB container name. + // + // Type: string + // Requirement Level: Conditionally Required - if available + // Stability: experimental + // Examples: 'anystring' + AttributeDBCosmosDBContainer = "db.cosmosdb.container" + // CosmosDB Operation Type. + // + // Type: Enum + // Requirement Level: Conditionally Required - when performing one of the + // operations in this list + // Stability: experimental + AttributeDBCosmosDBOperationType = "db.cosmosdb.operation_type" + // RU consumed for that operation + // + // Type: double + // Requirement Level: Conditionally Required - when available + // Stability: experimental + // Examples: 46.18, 1.0 + AttributeDBCosmosDBRequestCharge = "db.cosmosdb.request_charge" + // Request payload size in bytes + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + AttributeDBCosmosDBRequestContentLength = "db.cosmosdb.request_content_length" + // Cosmos DB status code. + // + // Type: int + // Requirement Level: Conditionally Required - if response was received + // Stability: experimental + // Examples: 200, 201 + AttributeDBCosmosDBStatusCode = "db.cosmosdb.status_code" + // Cosmos DB sub status code. + // + // Type: int + // Requirement Level: Conditionally Required - when response was received and + // contained sub-code. + // Stability: experimental + // Examples: 1000, 1002 + AttributeDBCosmosDBSubStatusCode = "db.cosmosdb.sub_status_code" +) + +const ( + // Gateway (HTTP) connections mode + AttributeDBCosmosDBConnectionModeGateway = "gateway" + // Direct connection + AttributeDBCosmosDBConnectionModeDirect = "direct" +) + +const ( + // invalid + AttributeDBCosmosDBOperationTypeInvalid = "Invalid" + // create + AttributeDBCosmosDBOperationTypeCreate = "Create" + // patch + AttributeDBCosmosDBOperationTypePatch = "Patch" + // read + AttributeDBCosmosDBOperationTypeRead = "Read" + // read_feed + AttributeDBCosmosDBOperationTypeReadFeed = "ReadFeed" + // delete + AttributeDBCosmosDBOperationTypeDelete = "Delete" + // replace + AttributeDBCosmosDBOperationTypeReplace = "Replace" + // execute + AttributeDBCosmosDBOperationTypeExecute = "Execute" + // query + AttributeDBCosmosDBOperationTypeQuery = "Query" + // head + AttributeDBCosmosDBOperationTypeHead = "Head" + // head_feed + AttributeDBCosmosDBOperationTypeHeadFeed = "HeadFeed" + // upsert + AttributeDBCosmosDBOperationTypeUpsert = "Upsert" + // batch + AttributeDBCosmosDBOperationTypeBatch = "Batch" + // query_plan + AttributeDBCosmosDBOperationTypeQueryPlan = "QueryPlan" + // execute_javascript + AttributeDBCosmosDBOperationTypeExecuteJavascript = "ExecuteJavaScript" +) + +// Span attributes used by non-OTLP exporters to represent OpenTelemetry Span's +// concepts. +const ( + // Name of the code, either "OK" or "ERROR". MUST NOT be set + // if the status code is UNSET. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeOTelStatusCode = "otel.status_code" + // Description of the Status if it has a value, otherwise not set. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'resource not found' + AttributeOTelStatusDescription = "otel.status_description" +) + +const ( + // The operation has been validated by an Application developer or Operator to have completed successfully + AttributeOTelStatusCodeOk = "OK" + // The operation contains an error + AttributeOTelStatusCodeError = "ERROR" +) + +// This semantic convention describes an instance of a function that runs +// without provisioning or managing of servers (also known as serverless +// functions or Function as a Service (FaaS)) with spans. +const ( + // The invocation ID of the current function invocation. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'af9d5aa4-a685-4c5f-a22b-444f80b3cc28' + AttributeFaaSInvocationID = "faas.invocation_id" +) + +// Semantic Convention for FaaS triggered as a response to some data source +// operation such as a database or filesystem read/write. +const ( + // The name of the source on which the triggering operation was performed. For + // example, in Cloud Storage or S3 corresponds to the bucket name, and in Cosmos + // DB to the database name. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'myBucketName', 'myDBName' + AttributeFaaSDocumentCollection = "faas.document.collection" + // The document name/table subjected to the operation. For example, in Cloud + // Storage or S3 is the name of the file, and in Cosmos DB the table name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'myFile.txt', 'myTableName' + AttributeFaaSDocumentName = "faas.document.name" + // Describes the type of the operation that was performed on the data. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + AttributeFaaSDocumentOperation = "faas.document.operation" + // A string containing the time when the data was accessed in the ISO 8601 format + // expressed in UTC. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2020-01-23T13:47:06Z' + AttributeFaaSDocumentTime = "faas.document.time" +) + +const ( + // When a new object is created + AttributeFaaSDocumentOperationInsert = "insert" + // When an object is modified + AttributeFaaSDocumentOperationEdit = "edit" + // When an object is deleted + AttributeFaaSDocumentOperationDelete = "delete" +) + +// Semantic Convention for FaaS scheduled to be executed regularly. +const ( + // A string containing the schedule period as Cron Expression. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '0/5 * * * ? *' + AttributeFaaSCron = "faas.cron" + // A string containing the function invocation time in the ISO 8601 format + // expressed in UTC. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2020-01-23T13:47:06Z' + AttributeFaaSTime = "faas.time" +) + +// Contains additional attributes for incoming FaaS spans. +const ( + // A boolean that is true if the serverless function is executed for the first + // time (aka cold-start). + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + AttributeFaaSColdstart = "faas.coldstart" +) + +// The `aws` conventions apply to operations using the AWS SDK. They map +// request or response parameters in AWS SDK API calls to attributes on a Span. +// The conventions have been collected over time based on feedback from AWS +// users of tracing and will continue to evolve as new interesting conventions +// are found. +// Some descriptions are also provided for populating general OpenTelemetry +// semantic conventions based on these APIs. +const ( + // The AWS request ID as returned in the response headers x-amz-request-id or + // x-amz-requestid. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '79b9da39-b7ae-508a-a6bc-864b2829c622', 'C9ER4AJX75574TDJ' + AttributeAWSRequestID = "aws.request_id" +) + +// Attributes that exist for multiple DynamoDB request types. +const ( + // The value of the AttributesToGet request parameter. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'lives', 'id' + AttributeAWSDynamoDBAttributesToGet = "aws.dynamodb.attributes_to_get" + // The value of the ConsistentRead request parameter. + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + AttributeAWSDynamoDBConsistentRead = "aws.dynamodb.consistent_read" + // The JSON-serialized value of each item in the ConsumedCapacity response field. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: '{ "CapacityUnits": number, "GlobalSecondaryIndexes": { "string" : { + // "CapacityUnits": number, "ReadCapacityUnits": number, "WriteCapacityUnits": + // number } }, "LocalSecondaryIndexes": { "string" : { "CapacityUnits": number, + // "ReadCapacityUnits": number, "WriteCapacityUnits": number } }, + // "ReadCapacityUnits": number, "Table": { "CapacityUnits": number, + // "ReadCapacityUnits": number, "WriteCapacityUnits": number }, "TableName": + // "string", "WriteCapacityUnits": number }' + AttributeAWSDynamoDBConsumedCapacity = "aws.dynamodb.consumed_capacity" + // The value of the IndexName request parameter. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'name_to_group' + AttributeAWSDynamoDBIndexName = "aws.dynamodb.index_name" + // The JSON-serialized value of the ItemCollectionMetrics response field. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '{ "string" : [ { "ItemCollectionKey": { "string" : { "B": blob, + // "BOOL": boolean, "BS": [ blob ], "L": [ "AttributeValue" ], "M": { "string" : + // "AttributeValue" }, "N": "string", "NS": [ "string" ], "NULL": boolean, "S": + // "string", "SS": [ "string" ] } }, "SizeEstimateRangeGB": [ number ] } ] }' + AttributeAWSDynamoDBItemCollectionMetrics = "aws.dynamodb.item_collection_metrics" + // The value of the Limit request parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 10 + AttributeAWSDynamoDBLimit = "aws.dynamodb.limit" + // The value of the ProjectionExpression request parameter. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Title', 'Title, Price, Color', 'Title, Description, RelatedItems, + // ProductReviews' + AttributeAWSDynamoDBProjection = "aws.dynamodb.projection" + // The value of the ProvisionedThroughput.ReadCapacityUnits request parameter. + // + // Type: double + // Requirement Level: Optional + // Stability: experimental + // Examples: 1.0, 2.0 + AttributeAWSDynamoDBProvisionedReadCapacity = "aws.dynamodb.provisioned_read_capacity" + // The value of the ProvisionedThroughput.WriteCapacityUnits request parameter. + // + // Type: double + // Requirement Level: Optional + // Stability: experimental + // Examples: 1.0, 2.0 + AttributeAWSDynamoDBProvisionedWriteCapacity = "aws.dynamodb.provisioned_write_capacity" + // The value of the Select request parameter. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'ALL_ATTRIBUTES', 'COUNT' + AttributeAWSDynamoDBSelect = "aws.dynamodb.select" + // The keys in the RequestItems object field. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Users', 'Cats' + AttributeAWSDynamoDBTableNames = "aws.dynamodb.table_names" +) + +// DynamoDB.CreateTable +const ( + // The JSON-serialized value of each item of the GlobalSecondaryIndexes request + // field + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: '{ "IndexName": "string", "KeySchema": [ { "AttributeName": "string", + // "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ "string" ], + // "ProjectionType": "string" }, "ProvisionedThroughput": { "ReadCapacityUnits": + // number, "WriteCapacityUnits": number } }' + AttributeAWSDynamoDBGlobalSecondaryIndexes = "aws.dynamodb.global_secondary_indexes" + // The JSON-serialized value of each item of the LocalSecondaryIndexes request + // field. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: '{ "IndexARN": "string", "IndexName": "string", "IndexSizeBytes": + // number, "ItemCount": number, "KeySchema": [ { "AttributeName": "string", + // "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ "string" ], + // "ProjectionType": "string" } }' + AttributeAWSDynamoDBLocalSecondaryIndexes = "aws.dynamodb.local_secondary_indexes" +) + +// DynamoDB.ListTables +const ( + // The value of the ExclusiveStartTableName request parameter. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Users', 'CatsTable' + AttributeAWSDynamoDBExclusiveStartTable = "aws.dynamodb.exclusive_start_table" + // The the number of items in the TableNames response parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 20 + AttributeAWSDynamoDBTableCount = "aws.dynamodb.table_count" +) + +// DynamoDB.Query +const ( + // The value of the ScanIndexForward request parameter. + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + AttributeAWSDynamoDBScanForward = "aws.dynamodb.scan_forward" +) + +// DynamoDB.Scan +const ( + // The value of the Count response parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 10 + AttributeAWSDynamoDBCount = "aws.dynamodb.count" + // The value of the ScannedCount response parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 50 + AttributeAWSDynamoDBScannedCount = "aws.dynamodb.scanned_count" + // The value of the Segment request parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 10 + AttributeAWSDynamoDBSegment = "aws.dynamodb.segment" + // The value of the TotalSegments request parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 100 + AttributeAWSDynamoDBTotalSegments = "aws.dynamodb.total_segments" +) + +// DynamoDB.UpdateTable +const ( + // The JSON-serialized value of each item in the AttributeDefinitions request + // field. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: '{ "AttributeName": "string", "AttributeType": "string" }' + AttributeAWSDynamoDBAttributeDefinitions = "aws.dynamodb.attribute_definitions" + // The JSON-serialized value of each item in the the GlobalSecondaryIndexUpdates + // request field. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: '{ "Create": { "IndexName": "string", "KeySchema": [ { + // "AttributeName": "string", "KeyType": "string" } ], "Projection": { + // "NonKeyAttributes": [ "string" ], "ProjectionType": "string" }, + // "ProvisionedThroughput": { "ReadCapacityUnits": number, "WriteCapacityUnits": + // number } }' + AttributeAWSDynamoDBGlobalSecondaryIndexUpdates = "aws.dynamodb.global_secondary_index_updates" +) + +// Attributes that exist for S3 request types. +const ( + // The S3 bucket name the request refers to. Corresponds to the --bucket parameter + // of the S3 API operations. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'some-bucket-name' + // Note: The bucket attribute is applicable to all S3 operations that reference a + // bucket, i.e. that require the bucket name as a mandatory parameter. + // This applies to almost all S3 operations except list-buckets. + AttributeAWSS3Bucket = "aws.s3.bucket" + // The source object (in the form bucket/key) for the copy operation. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'someFile.yml' + // Note: The copy_source attribute applies to S3 copy operations and corresponds + // to the --copy-source parameter + // of the copy-object operation within the S3 API. + // This applies in particular to the following operations:
    + //
  • copy-object
  • + //
  • upload-part-copy
  • + //
+ AttributeAWSS3CopySource = "aws.s3.copy_source" + // The delete request container that specifies the objects to be deleted. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Objects=[{Key=string,VersionID=string},{Key=string,VersionID=string} + // ],Quiet=boolean' + // Note: The delete attribute is only applicable to the delete-object operation. + // The delete attribute corresponds to the --delete parameter of the + // delete-objects operation within the S3 API. + AttributeAWSS3Delete = "aws.s3.delete" + // The S3 object key the request refers to. Corresponds to the --key parameter of + // the S3 API operations. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'someFile.yml' + // Note: The key attribute is applicable to all object-related S3 operations, i.e. + // that require the object key as a mandatory parameter. + // This applies in particular to the following operations:
    + //
  • copy-object
  • + //
  • delete-object
  • + //
  • get-object
  • + //
  • head-object
  • + //
  • put-object
  • + //
  • restore-object
  • + //
  • select-object-content
  • + //
  • abort-multipart-upload
  • + //
  • complete-multipart-upload
  • + //
  • create-multipart-upload
  • + //
  • list-parts
  • + //
  • upload-part
  • + //
  • upload-part-copy
  • + //
+ AttributeAWSS3Key = "aws.s3.key" + // The part number of the part being uploaded in a multipart-upload operation. + // This is a positive integer between 1 and 10,000. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 3456 + // Note: The part_number attribute is only applicable to the upload-part + // and upload-part-copy operations. + // The part_number attribute corresponds to the --part-number parameter of the + // upload-part operation within the S3 API. + AttributeAWSS3PartNumber = "aws.s3.part_number" + // Upload ID that identifies the multipart upload. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'dfRtDYWFbkRONycy.Yxwh66Yjlx.cph0gtNBtJ' + // Note: The upload_id attribute applies to S3 multipart-upload operations and + // corresponds to the --upload-id parameter + // of the S3 API multipart operations. + // This applies in particular to the following operations:
    + //
  • abort-multipart-upload
  • + //
  • complete-multipart-upload
  • + //
  • list-parts
  • + //
  • upload-part
  • + //
  • upload-part-copy
  • + //
+ AttributeAWSS3UploadID = "aws.s3.upload_id" +) + +// Semantic conventions to apply when instrumenting the GraphQL implementation. +// They map GraphQL operations to attributes on a Span. +const ( + // The GraphQL document being executed. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'query findBookByID { bookByID(id: ?) { name } }' + // Note: The value may be sanitized to exclude sensitive information. + AttributeGraphqlDocument = "graphql.document" + // The name of the operation being executed. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'findBookByID' + AttributeGraphqlOperationName = "graphql.operation.name" + // The type of the operation being executed. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'query', 'mutation', 'subscription' + AttributeGraphqlOperationType = "graphql.operation.type" +) + +const ( + // GraphQL query + AttributeGraphqlOperationTypeQuery = "query" + // GraphQL mutation + AttributeGraphqlOperationTypeMutation = "mutation" + // GraphQL subscription + AttributeGraphqlOperationTypeSubscription = "subscription" +) + +// General attributes used in messaging systems. +const ( + // The number of messages sent, received, or processed in the scope of the + // batching operation. + // + // Type: int + // Requirement Level: Conditionally Required - If the span describes an operation + // on a batch of messages. + // Stability: experimental + // Examples: 0, 1, 2 + // Note: Instrumentations SHOULD NOT set messaging.batch.message_count on spans + // that operate with a single message. When a messaging client library supports + // both batch and single-message API for the same operation, instrumentations + // SHOULD use messaging.batch.message_count for batching APIs and SHOULD NOT use + // it for single-message APIs. + AttributeMessagingBatchMessageCount = "messaging.batch.message_count" + // A unique identifier for the client that consumes or produces a message. + // + // Type: string + // Requirement Level: Recommended - If a client id is available + // Stability: experimental + // Examples: 'client-5', 'myhost@8742@s8083jm' + AttributeMessagingClientID = "messaging.client_id" + // A string identifying the kind of messaging operation as defined in the + // Operation names section above. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + // Note: If a custom value is used, it MUST be of low cardinality. + AttributeMessagingOperation = "messaging.operation" + // A string identifying the messaging system. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'kafka', 'rabbitmq', 'rocketmq', 'activemq', 'AmazonSQS' + AttributeMessagingSystem = "messaging.system" +) + +const ( + // publish + AttributeMessagingOperationPublish = "publish" + // receive + AttributeMessagingOperationReceive = "receive" + // process + AttributeMessagingOperationProcess = "process" +) + +// Semantic conventions for remote procedure calls. +const ( + // The name of the (logical) method being called, must be equal to the $method + // part in the span name. + // + // Type: string + // Requirement Level: Recommended + // Stability: experimental + // Examples: 'exampleMethod' + // Note: This is the logical name of the method from the RPC interface + // perspective, which can be different from the name of any implementing + // method/function. The code.function attribute may be used to store the latter + // (e.g., method actually executing the call on the server side, RPC client stub + // method on the client side). + AttributeRPCMethod = "rpc.method" + // The full (logical) name of the service being called, including its package + // name, if applicable. + // + // Type: string + // Requirement Level: Recommended + // Stability: experimental + // Examples: 'myservice.EchoService' + // Note: This is the logical name of the service from the RPC interface + // perspective, which can be different from the name of any implementing class. + // The code.namespace attribute may be used to store the latter (despite the + // attribute name, it may include a class name; e.g., class with method actually + // executing the call on the server side, RPC client stub class on the client + // side). + AttributeRPCService = "rpc.service" + // A string identifying the remoting system. See below for a list of well-known + // identifiers. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + AttributeRPCSystem = "rpc.system" +) + +const ( + // gRPC + AttributeRPCSystemGRPC = "grpc" + // Java RMI + AttributeRPCSystemJavaRmi = "java_rmi" + // .NET WCF + AttributeRPCSystemDotnetWcf = "dotnet_wcf" + // Apache Dubbo + AttributeRPCSystemApacheDubbo = "apache_dubbo" + // Connect RPC + AttributeRPCSystemConnectRPC = "connect_rpc" +) + +// Tech-specific attributes for gRPC. +const ( + // The numeric status code of the gRPC request. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + AttributeRPCGRPCStatusCode = "rpc.grpc.status_code" +) + +const ( + // OK + AttributeRPCGRPCStatusCodeOk = "0" + // CANCELLED + AttributeRPCGRPCStatusCodeCancelled = "1" + // UNKNOWN + AttributeRPCGRPCStatusCodeUnknown = "2" + // INVALID_ARGUMENT + AttributeRPCGRPCStatusCodeInvalidArgument = "3" + // DEADLINE_EXCEEDED + AttributeRPCGRPCStatusCodeDeadlineExceeded = "4" + // NOT_FOUND + AttributeRPCGRPCStatusCodeNotFound = "5" + // ALREADY_EXISTS + AttributeRPCGRPCStatusCodeAlreadyExists = "6" + // PERMISSION_DENIED + AttributeRPCGRPCStatusCodePermissionDenied = "7" + // RESOURCE_EXHAUSTED + AttributeRPCGRPCStatusCodeResourceExhausted = "8" + // FAILED_PRECONDITION + AttributeRPCGRPCStatusCodeFailedPrecondition = "9" + // ABORTED + AttributeRPCGRPCStatusCodeAborted = "10" + // OUT_OF_RANGE + AttributeRPCGRPCStatusCodeOutOfRange = "11" + // UNIMPLEMENTED + AttributeRPCGRPCStatusCodeUnimplemented = "12" + // INTERNAL + AttributeRPCGRPCStatusCodeInternal = "13" + // UNAVAILABLE + AttributeRPCGRPCStatusCodeUnavailable = "14" + // DATA_LOSS + AttributeRPCGRPCStatusCodeDataLoss = "15" + // UNAUTHENTICATED + AttributeRPCGRPCStatusCodeUnauthenticated = "16" +) + +// Tech-specific attributes for [JSON RPC](https://www.jsonrpc.org/). +const ( + // error.code property of response if it is an error response. + // + // Type: int + // Requirement Level: Conditionally Required - If response is not successful. + // Stability: experimental + // Examples: -32700, 100 + AttributeRPCJsonrpcErrorCode = "rpc.jsonrpc.error_code" + // error.message property of response if it is an error response. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Parse error', 'User already exists' + AttributeRPCJsonrpcErrorMessage = "rpc.jsonrpc.error_message" + // id property of request or response. Since protocol allows id to be int, string, + // null or missing (for notifications), value is expected to be cast to string for + // simplicity. Use empty string in case of null value. Omit entirely if this is a + // notification. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '10', 'request-7', '' + AttributeRPCJsonrpcRequestID = "rpc.jsonrpc.request_id" + // Protocol version as in jsonrpc property of request/response. Since JSON-RPC 1.0 + // does not specify this, the value can be omitted. + // + // Type: string + // Requirement Level: Conditionally Required - If other than the default version + // (`1.0`) + // Stability: experimental + // Examples: '2.0', '1.0' + AttributeRPCJsonrpcVersion = "rpc.jsonrpc.version" +) + +// Tech-specific attributes for Connect RPC. +const ( + // The error codes of the Connect request. Error codes are always string values. + // + // Type: Enum + // Requirement Level: Conditionally Required - If response is not successful and + // if error code available. + // Stability: experimental + AttributeRPCConnectRPCErrorCode = "rpc.connect_rpc.error_code" +) + +const ( + // cancelled + AttributeRPCConnectRPCErrorCodeCancelled = "cancelled" + // unknown + AttributeRPCConnectRPCErrorCodeUnknown = "unknown" + // invalid_argument + AttributeRPCConnectRPCErrorCodeInvalidArgument = "invalid_argument" + // deadline_exceeded + AttributeRPCConnectRPCErrorCodeDeadlineExceeded = "deadline_exceeded" + // not_found + AttributeRPCConnectRPCErrorCodeNotFound = "not_found" + // already_exists + AttributeRPCConnectRPCErrorCodeAlreadyExists = "already_exists" + // permission_denied + AttributeRPCConnectRPCErrorCodePermissionDenied = "permission_denied" + // resource_exhausted + AttributeRPCConnectRPCErrorCodeResourceExhausted = "resource_exhausted" + // failed_precondition + AttributeRPCConnectRPCErrorCodeFailedPrecondition = "failed_precondition" + // aborted + AttributeRPCConnectRPCErrorCodeAborted = "aborted" + // out_of_range + AttributeRPCConnectRPCErrorCodeOutOfRange = "out_of_range" + // unimplemented + AttributeRPCConnectRPCErrorCodeUnimplemented = "unimplemented" + // internal + AttributeRPCConnectRPCErrorCodeInternal = "internal" + // unavailable + AttributeRPCConnectRPCErrorCodeUnavailable = "unavailable" + // data_loss + AttributeRPCConnectRPCErrorCodeDataLoss = "data_loss" + // unauthenticated + AttributeRPCConnectRPCErrorCodeUnauthenticated = "unauthenticated" +) + +func GetTraceSemanticConventionAttributeNames() []string { + return []string{ + AttributeExceptionMessage, + AttributeExceptionStacktrace, + AttributeExceptionType, + AttributePeerService, + AttributeEnduserID, + AttributeEnduserRole, + AttributeEnduserScope, + AttributeThreadDaemon, + AttributeThreadID, + AttributeThreadName, + AttributeCodeColumn, + AttributeCodeFilepath, + AttributeCodeFunction, + AttributeCodeLineNumber, + AttributeCodeNamespace, + AttributeAWSLambdaInvokedARN, + AttributeCloudeventsEventID, + AttributeCloudeventsEventSource, + AttributeCloudeventsEventSpecVersion, + AttributeCloudeventsEventSubject, + AttributeCloudeventsEventType, + AttributeOpentracingRefType, + AttributeDBConnectionString, + AttributeDBJDBCDriverClassname, + AttributeDBName, + AttributeDBOperation, + AttributeDBStatement, + AttributeDBSystem, + AttributeDBUser, + AttributeDBMSSQLInstanceName, + AttributeDBCassandraConsistencyLevel, + AttributeDBCassandraCoordinatorDC, + AttributeDBCassandraCoordinatorID, + AttributeDBCassandraIdempotence, + AttributeDBCassandraPageSize, + AttributeDBCassandraSpeculativeExecutionCount, + AttributeDBCassandraTable, + AttributeDBRedisDBIndex, + AttributeDBMongoDBCollection, + AttributeDBElasticsearchClusterName, + AttributeDBElasticsearchNodeName, + AttributeDBSQLTable, + AttributeDBCosmosDBClientID, + AttributeDBCosmosDBConnectionMode, + AttributeDBCosmosDBContainer, + AttributeDBCosmosDBOperationType, + AttributeDBCosmosDBRequestCharge, + AttributeDBCosmosDBRequestContentLength, + AttributeDBCosmosDBStatusCode, + AttributeDBCosmosDBSubStatusCode, + AttributeOTelStatusCode, + AttributeOTelStatusDescription, + AttributeFaaSInvocationID, + AttributeFaaSDocumentCollection, + AttributeFaaSDocumentName, + AttributeFaaSDocumentOperation, + AttributeFaaSDocumentTime, + AttributeFaaSCron, + AttributeFaaSTime, + AttributeFaaSColdstart, + AttributeAWSRequestID, + AttributeAWSDynamoDBAttributesToGet, + AttributeAWSDynamoDBConsistentRead, + AttributeAWSDynamoDBConsumedCapacity, + AttributeAWSDynamoDBIndexName, + AttributeAWSDynamoDBItemCollectionMetrics, + AttributeAWSDynamoDBLimit, + AttributeAWSDynamoDBProjection, + AttributeAWSDynamoDBProvisionedReadCapacity, + AttributeAWSDynamoDBProvisionedWriteCapacity, + AttributeAWSDynamoDBSelect, + AttributeAWSDynamoDBTableNames, + AttributeAWSDynamoDBGlobalSecondaryIndexes, + AttributeAWSDynamoDBLocalSecondaryIndexes, + AttributeAWSDynamoDBExclusiveStartTable, + AttributeAWSDynamoDBTableCount, + AttributeAWSDynamoDBScanForward, + AttributeAWSDynamoDBCount, + AttributeAWSDynamoDBScannedCount, + AttributeAWSDynamoDBSegment, + AttributeAWSDynamoDBTotalSegments, + AttributeAWSDynamoDBAttributeDefinitions, + AttributeAWSDynamoDBGlobalSecondaryIndexUpdates, + AttributeAWSS3Bucket, + AttributeAWSS3CopySource, + AttributeAWSS3Delete, + AttributeAWSS3Key, + AttributeAWSS3PartNumber, + AttributeAWSS3UploadID, + AttributeGraphqlDocument, + AttributeGraphqlOperationName, + AttributeGraphqlOperationType, + AttributeMessagingBatchMessageCount, + AttributeMessagingClientID, + AttributeMessagingOperation, + AttributeMessagingSystem, + AttributeRPCMethod, + AttributeRPCService, + AttributeRPCSystem, + AttributeRPCGRPCStatusCode, + AttributeRPCJsonrpcErrorCode, + AttributeRPCJsonrpcErrorMessage, + AttributeRPCJsonrpcRequestID, + AttributeRPCJsonrpcVersion, + AttributeRPCConnectRPCErrorCode, + } +} diff --git a/semconv/v1.22.0/schema.go b/semconv/v1.22.0/schema.go new file mode 100644 index 00000000000..bf32dc2f18c --- /dev/null +++ b/semconv/v1.22.0/schema.go @@ -0,0 +1,9 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package semconv // import "go.opentelemetry.io/collector/semconv/v1.22.0" + +// SchemaURL is the schema URL that matches the version of the semantic conventions +// that this package defines. Semconv packages starting from v1.4.0 must declare +// non-empty schema URL in the form https://opentelemetry.io/schemas/ +const SchemaURL = "https://opentelemetry.io/schemas/1.22.0" diff --git a/service/README.md b/service/README.md index 58409c7f9b8..b954cd85aa4 100644 --- a/service/README.md +++ b/service/README.md @@ -142,7 +142,6 @@ exporters: - debug extensions: - zpages - - memory_ballast ``` ## How to validate configuration file and return all errors without running collector diff --git a/service/config_test.go b/service/config_test.go index c3b659d0dec..6ac9d6e625a 100644 --- a/service/config_test.go +++ b/service/config_test.go @@ -42,7 +42,7 @@ func TestConfigValidate(t *testing.T) { name: "duplicate-processor-reference", cfgFn: func() *Config { cfg := generateConfig() - pipe := cfg.Pipelines[component.NewID("traces")] + pipe := cfg.Pipelines[component.MustNewID("traces")] pipe.Processors = append(pipe.Processors, pipe.Processors...) return cfg }, @@ -52,10 +52,10 @@ func TestConfigValidate(t *testing.T) { name: "invalid-service-pipeline-type", cfgFn: func() *Config { cfg := generateConfig() - cfg.Pipelines[component.NewID("wrongtype")] = &pipelines.PipelineConfig{ - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, + cfg.Pipelines[component.MustNewID("wrongtype")] = &pipelines.PipelineConfig{ + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop")}, } return cfg }, @@ -99,12 +99,12 @@ func generateConfig() *Config { Address: ":8080", }, }, - Extensions: extensions.Config{component.NewID("nop")}, + Extensions: extensions.Config{component.MustNewID("nop")}, Pipelines: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, } diff --git a/service/extensions/extensions.go b/service/extensions/extensions.go index 5ff92cd5852..e05c5aa01f0 100644 --- a/service/extensions/extensions.go +++ b/service/extensions/extensions.go @@ -15,6 +15,7 @@ import ( "go.opentelemetry.io/collector/confmap" "go.opentelemetry.io/collector/extension" "go.opentelemetry.io/collector/service/internal/components" + "go.opentelemetry.io/collector/service/internal/servicetelemetry" "go.opentelemetry.io/collector/service/internal/zpages" ) @@ -22,19 +23,32 @@ const zExtensionName = "zextensionname" // Extensions is a map of extensions created from extension configs. type Extensions struct { - telemetry component.TelemetrySettings - extMap map[component.ID]extension.Extension + telemetry servicetelemetry.TelemetrySettings + extMap map[component.ID]extension.Extension + instanceIDs map[component.ID]*component.InstanceID + extensionIDs []component.ID // start order (and reverse stop order) } // Start starts all extensions. func (bes *Extensions) Start(ctx context.Context, host component.Host) error { bes.telemetry.Logger.Info("Starting extensions...") - for extID, ext := range bes.extMap { + for _, extID := range bes.extensionIDs { extLogger := components.ExtensionLogger(bes.telemetry.Logger, extID) extLogger.Info("Extension is starting...") - if err := ext.Start(ctx, components.NewHostWrapper(host, extLogger)); err != nil { + instanceID := bes.instanceIDs[extID] + ext := bes.extMap[extID] + bes.telemetry.Status.ReportStatus( + instanceID, + component.NewStatusEvent(component.StatusStarting), + ) + if err := ext.Start(ctx, host); err != nil { + bes.telemetry.Status.ReportStatus( + instanceID, + component.NewPermanentErrorEvent(err), + ) return err } + bes.telemetry.Status.ReportOKIfStarting(instanceID) extLogger.Info("Extension started.") } return nil @@ -44,15 +58,34 @@ func (bes *Extensions) Start(ctx context.Context, host component.Host) error { func (bes *Extensions) Shutdown(ctx context.Context) error { bes.telemetry.Logger.Info("Stopping extensions...") var errs error - for _, ext := range bes.extMap { - errs = multierr.Append(errs, ext.Shutdown(ctx)) + for i := len(bes.extensionIDs) - 1; i >= 0; i-- { + extID := bes.extensionIDs[i] + instanceID := bes.instanceIDs[extID] + ext := bes.extMap[extID] + bes.telemetry.Status.ReportStatus( + instanceID, + component.NewStatusEvent(component.StatusStopping), + ) + if err := ext.Shutdown(ctx); err != nil { + bes.telemetry.Status.ReportStatus( + instanceID, + component.NewPermanentErrorEvent(err), + ) + errs = multierr.Append(errs, err) + continue + } + bes.telemetry.Status.ReportStatus( + instanceID, + component.NewStatusEvent(component.StatusStopped), + ) } return errs } func (bes *Extensions) NotifyPipelineReady() error { - for extID, ext := range bes.extMap { + for _, extID := range bes.extensionIDs { + ext := bes.extMap[extID] if pw, ok := ext.(extension.PipelineWatcher); ok { if err := pw.Ready(); err != nil { return fmt.Errorf("failed to notify extension %q: %w", extID, err) @@ -63,9 +96,9 @@ func (bes *Extensions) NotifyPipelineReady() error { } func (bes *Extensions) NotifyPipelineNotReady() error { - // Notify extensions in reverse order. var errs error - for _, ext := range bes.extMap { + for _, extID := range bes.extensionIDs { + ext := bes.extMap[extID] if pw, ok := ext.(extension.PipelineWatcher); ok { errs = multierr.Append(errs, pw.NotReady()) } @@ -75,7 +108,8 @@ func (bes *Extensions) NotifyPipelineNotReady() error { func (bes *Extensions) NotifyConfig(ctx context.Context, conf *confmap.Conf) error { var errs error - for _, ext := range bes.extMap { + for _, extID := range bes.extensionIDs { + ext := bes.extMap[extID] if cw, ok := ext.(extension.ConfigWatcher); ok { clonedConf := confmap.NewFromStringMap(conf.ToStringMap()) errs = multierr.Append(errs, cw.NotifyConfig(ctx, clonedConf)) @@ -84,6 +118,15 @@ func (bes *Extensions) NotifyConfig(ctx context.Context, conf *confmap.Conf) err return errs } +func (bes *Extensions) NotifyComponentStatusChange(source *component.InstanceID, event *component.StatusEvent) { + for _, extID := range bes.extensionIDs { + ext := bes.extMap[extID] + if sw, ok := ext.(extension.StatusWatcher); ok { + sw.ComponentStatusChanged(source, event) + } + } +} + func (bes *Extensions) GetExtensions() map[component.ID]component.Component { result := make(map[component.ID]component.Component, len(bes.extMap)) for extID, v := range bes.extMap { @@ -100,7 +143,7 @@ func (bes *Extensions) HandleZPages(w http.ResponseWriter, r *http.Request) { data := zpages.SummaryExtensionsTableData{} data.Rows = make([]zpages.SummaryExtensionsTableRowData, 0, len(bes.extMap)) - for id := range bes.extMap { + for _, id := range bes.extensionIDs { row := zpages.SummaryExtensionsTableRowData{FullName: id.String()} data.Rows = append(data.Rows, row) } @@ -120,32 +163,29 @@ func (bes *Extensions) HandleZPages(w http.ResponseWriter, r *http.Request) { // Settings holds configuration for building Extensions. type Settings struct { - Telemetry component.TelemetrySettings + Telemetry servicetelemetry.TelemetrySettings BuildInfo component.BuildInfo - // Drepecated: [v0.68.0] use Extensions. - Configs map[component.ID]component.Config - - // Drepecated: [v0.68.0] use Extensions. - Factories map[component.Type]extension.Factory - // Extensions builder for extensions. Extensions *extension.Builder } // New creates a new Extensions from Config. func New(ctx context.Context, set Settings, cfg Config) (*Extensions, error) { - if set.Extensions == nil { - set.Extensions = extension.NewBuilder(set.Configs, set.Factories) - } exts := &Extensions{ - telemetry: set.Telemetry, - extMap: make(map[component.ID]extension.Extension), + telemetry: set.Telemetry, + extMap: make(map[component.ID]extension.Extension), + instanceIDs: make(map[component.ID]*component.InstanceID), + extensionIDs: make([]component.ID, 0, len(cfg)), } for _, extID := range cfg { + instanceID := &component.InstanceID{ + ID: extID, + Kind: component.KindExtension, + } extSet := extension.CreateSettings{ ID: extID, - TelemetrySettings: set.Telemetry, + TelemetrySettings: set.Telemetry.ToComponentTelemetrySettings(instanceID), BuildInfo: set.BuildInfo, } extSet.TelemetrySettings.Logger = components.ExtensionLogger(set.Telemetry.Logger, extID) @@ -161,7 +201,12 @@ func New(ctx context.Context, set Settings, cfg Config) (*Extensions, error) { } exts.extMap[extID] = ext + exts.instanceIDs[extID] = instanceID } - + order, err := computeOrder(exts) + if err != nil { + return nil, err + } + exts.extensionIDs = order return exts, nil } diff --git a/service/extensions/extensions_test.go b/service/extensions/extensions_test.go index d244fe0e8dd..d447582bd54 100644 --- a/service/extensions/extensions_test.go +++ b/service/extensions/extensions_test.go @@ -16,6 +16,8 @@ import ( "go.opentelemetry.io/collector/confmap" "go.opentelemetry.io/collector/extension" "go.opentelemetry.io/collector/extension/extensiontest" + "go.opentelemetry.io/collector/service/internal/servicetelemetry" + "go.opentelemetry.io/collector/service/internal/status" ) func TestBuildExtensions(t *testing.T) { @@ -36,17 +38,17 @@ func TestBuildExtensions(t *testing.T) { { name: "extension_not_configured", config: Config{ - component.NewID("myextension"), + component.MustNewID("myextension"), }, wantErrMsg: "failed to create extension \"myextension\": extension \"myextension\" is not configured", }, { name: "missing_extension_factory", extensionsConfigs: map[component.ID]component.Config{ - component.NewID("unknown"): nopExtensionConfig, + component.MustNewID("unknown"): nopExtensionConfig, }, config: Config{ - component.NewID("unknown"), + component.MustNewID("unknown"), }, wantErrMsg: "failed to create extension \"unknown\": extension factory not available for: \"unknown\"", }, @@ -81,10 +83,9 @@ func TestBuildExtensions(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { _, err := New(context.Background(), Settings{ - Telemetry: componenttest.NewNopTelemetrySettings(), - BuildInfo: component.NewDefaultBuildInfo(), - Configs: tt.extensionsConfigs, - Factories: tt.factories, + Telemetry: servicetelemetry.NewNopTelemetrySettings(), + BuildInfo: component.NewDefaultBuildInfo(), + Extensions: extension.NewBuilder(tt.extensionsConfigs, tt.factories), }, tt.config) require.Error(t, err) assert.EqualError(t, err, tt.wantErrMsg) @@ -92,15 +93,130 @@ func TestBuildExtensions(t *testing.T) { } } +type testOrderExt struct { + name string + deps []string +} + +type testOrderCase struct { + testName string + extensions []testOrderExt + order []string + err string +} + +func TestOrdering(t *testing.T) { + tests := []testOrderCase{ + { + testName: "no_deps", + extensions: []testOrderExt{{name: ""}, {name: "foo"}, {name: "bar"}}, + order: nil, // no predictable order + }, + { + testName: "deps", + extensions: []testOrderExt{ + {name: "foo", deps: []string{"bar"}}, // foo -> bar + {name: "baz", deps: []string{"foo"}}, // baz -> foo + {name: "bar"}, + }, + // baz -> foo -> bar + order: []string{"recording/bar", "recording/foo", "recording/baz"}, + }, + { + testName: "deps_double", + extensions: []testOrderExt{ + {name: "foo", deps: []string{"bar"}}, // foo -> bar + {name: "baz", deps: []string{"foo", "bar"}}, // baz -> {foo, bar} + {name: "bar"}, + }, + // baz -> foo -> bar + order: []string{"recording/bar", "recording/foo", "recording/baz"}, + }, + { + testName: "unknown_dep", + extensions: []testOrderExt{ + {name: "foo", deps: []string{"BAZ"}}, + {name: "bar"}, + }, + err: "unable to find extension", + }, + { + testName: "circular", + extensions: []testOrderExt{ + {name: "foo", deps: []string{"bar"}}, + {name: "bar", deps: []string{"foo"}}, + }, + err: "unable to order extenions", + }, + } + for _, testCase := range tests { + t.Run(testCase.testName, testCase.testOrdering) + } +} + +func (tc testOrderCase) testOrdering(t *testing.T) { + var startOrder []string + var shutdownOrder []string + + recordingExtensionFactory := newRecordingExtensionFactory(func(set extension.CreateSettings, _ component.Host) error { + startOrder = append(startOrder, set.ID.String()) + return nil + }, func(set extension.CreateSettings) error { + shutdownOrder = append(shutdownOrder, set.ID.String()) + return nil + }) + + extCfgs := make(map[component.ID]component.Config) + extIDs := make([]component.ID, len(tc.extensions)) + for i, ext := range tc.extensions { + extID := component.NewIDWithName(recordingExtensionFactory.Type(), ext.name) + extIDs[i] = extID + extCfgs[extID] = recordingExtensionConfig{dependencies: ext.deps} + } + + exts, err := New(context.Background(), Settings{ + Telemetry: servicetelemetry.NewNopTelemetrySettings(), + BuildInfo: component.NewDefaultBuildInfo(), + Extensions: extension.NewBuilder( + extCfgs, + map[component.Type]extension.Factory{ + recordingExtensionFactory.Type(): recordingExtensionFactory, + }), + }, Config(extIDs)) + if tc.err != "" { + require.ErrorContains(t, err, tc.err) + return + } + require.NoError(t, err) + + err = exts.Start(context.Background(), componenttest.NewNopHost()) + require.NoError(t, err) + err = exts.Shutdown(context.Background()) + require.NoError(t, err) + + // TODO From Go 1.21 can use slices.Reverse() + reverseSlice := func(s []string) { + for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { + s[i], s[j] = s[j], s[i] + } + } + + if len(tc.order) > 0 { + require.Equal(t, tc.order, startOrder) + reverseSlice(shutdownOrder) + require.Equal(t, tc.order, shutdownOrder) + } +} + func TestNotifyConfig(t *testing.T) { notificationError := errors.New("Error processing config") nopExtensionFactory := extensiontest.NewNopFactory() nopExtensionConfig := nopExtensionFactory.CreateDefaultConfig() - n1ExtensionFactory := newConfigWatcherExtensionFactory("notifiable1", func() error { return nil }) + n1ExtensionFactory := newConfigWatcherExtensionFactory(component.MustNewType("notifiable1"), func() error { return nil }) n1ExtensionConfig := n1ExtensionFactory.CreateDefaultConfig() - n2ExtensionFactory := newConfigWatcherExtensionFactory("notifiable2", func() error { return nil }) + n2ExtensionFactory := newConfigWatcherExtensionFactory(component.MustNewType("notifiable2"), func() error { return nil }) n2ExtensionConfig := n1ExtensionFactory.CreateDefaultConfig() - nErrExtensionFactory := newConfigWatcherExtensionFactory("notifiableErr", func() error { return notificationError }) + nErrExtensionFactory := newConfigWatcherExtensionFactory(component.MustNewType("notifiableErr"), func() error { return notificationError }) nErrExtensionConfig := nErrExtensionFactory.CreateDefaultConfig() tests := []struct { @@ -114,52 +230,52 @@ func TestNotifyConfig(t *testing.T) { { name: "No notifiable extensions", factories: map[component.Type]extension.Factory{ - "nop": nopExtensionFactory, + component.MustNewType("nop"): nopExtensionFactory, }, extensionsConfigs: map[component.ID]component.Config{ - component.NewID("nop"): nopExtensionConfig, + component.MustNewID("nop"): nopExtensionConfig, }, serviceExtensions: []component.ID{ - component.NewID("nop"), + component.MustNewID("nop"), }, }, { name: "One notifiable extension", factories: map[component.Type]extension.Factory{ - "notifiable1": n1ExtensionFactory, + component.MustNewType("notifiable1"): n1ExtensionFactory, }, extensionsConfigs: map[component.ID]component.Config{ - component.NewID("notifiable1"): n1ExtensionConfig, + component.MustNewID("notifiable1"): n1ExtensionConfig, }, serviceExtensions: []component.ID{ - component.NewID("notifiable1"), + component.MustNewID("notifiable1"), }, }, { name: "Multiple notifiable extensions", factories: map[component.Type]extension.Factory{ - "notifiable1": n1ExtensionFactory, - "notifiable2": n2ExtensionFactory, + component.MustNewType("notifiable1"): n1ExtensionFactory, + component.MustNewType("notifiable2"): n2ExtensionFactory, }, extensionsConfigs: map[component.ID]component.Config{ - component.NewID("notifiable1"): n1ExtensionConfig, - component.NewID("notifiable2"): n2ExtensionConfig, + component.MustNewID("notifiable1"): n1ExtensionConfig, + component.MustNewID("notifiable2"): n2ExtensionConfig, }, serviceExtensions: []component.ID{ - component.NewID("notifiable1"), - component.NewID("notifiable2"), + component.MustNewID("notifiable1"), + component.MustNewID("notifiable2"), }, }, { name: "Errors in extension notification", factories: map[component.Type]extension.Factory{ - "notifiableErr": nErrExtensionFactory, + component.MustNewType("notifiableErr"): nErrExtensionFactory, }, extensionsConfigs: map[component.ID]component.Config{ - component.NewID("notifiableErr"): nErrExtensionConfig, + component.MustNewID("notifiableErr"): nErrExtensionConfig, }, serviceExtensions: []component.ID{ - component.NewID("notifiableErr"), + component.MustNewID("notifiableErr"), }, want: notificationError, }, @@ -168,10 +284,9 @@ func TestNotifyConfig(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { extensions, err := New(context.Background(), Settings{ - Telemetry: componenttest.NewNopTelemetrySettings(), - BuildInfo: component.NewDefaultBuildInfo(), - Configs: tt.extensionsConfigs, - Factories: tt.factories, + Telemetry: servicetelemetry.NewNopTelemetrySettings(), + BuildInfo: component.NewDefaultBuildInfo(), + Extensions: extension.NewBuilder(tt.extensionsConfigs, tt.factories), }, tt.serviceExtensions) assert.NoError(t, err) errs := extensions.NotifyConfig(context.Background(), confmap.NewFromStringMap(map[string]interface{}{})) @@ -184,15 +299,15 @@ type configWatcherExtension struct { fn func() error } -func (comp *configWatcherExtension) Start(_ context.Context, _ component.Host) error { +func (comp *configWatcherExtension) Start(context.Context, component.Host) error { return comp.fn() } -func (comp *configWatcherExtension) Shutdown(_ context.Context) error { +func (comp *configWatcherExtension) Shutdown(context.Context) error { return comp.fn() } -func (comp *configWatcherExtension) NotifyConfig(_ context.Context, _ *confmap.Conf) error { +func (comp *configWatcherExtension) NotifyConfig(context.Context, *confmap.Conf) error { return comp.fn() } @@ -211,7 +326,7 @@ func newConfigWatcherExtensionFactory(name component.Type, fn func() error) exte func() component.Config { return &struct{}{} }, - func(ctx context.Context, set extension.CreateSettings, extension component.Config) (extension.Extension, error) { + func(context.Context, extension.CreateSettings, component.Config) (extension.Extension, error) { return newConfigWatcherExtension(fn), nil }, component.StabilityLevelDevelopment, @@ -220,11 +335,11 @@ func newConfigWatcherExtensionFactory(name component.Type, fn func() error) exte func newBadExtensionFactory() extension.Factory { return extension.NewFactory( - "bf", + component.MustNewType("bf"), func() component.Config { return &struct{}{} }, - func(ctx context.Context, set extension.CreateSettings, extension component.Config) (extension.Extension, error) { + func(context.Context, extension.CreateSettings, component.Config) (extension.Extension, error) { return nil, nil }, component.StabilityLevelDevelopment, @@ -233,13 +348,187 @@ func newBadExtensionFactory() extension.Factory { func newCreateErrorExtensionFactory() extension.Factory { return extension.NewFactory( - "err", + component.MustNewType("err"), func() component.Config { return &struct{}{} }, - func(ctx context.Context, set extension.CreateSettings, extension component.Config) (extension.Extension, error) { + func(context.Context, extension.CreateSettings, component.Config) (extension.Extension, error) { return nil, errors.New("cannot create \"err\" extension type") }, component.StabilityLevelDevelopment, ) } + +func TestStatusReportedOnStartupShutdown(t *testing.T) { + // compare two slices of status events ignoring timestamp + assertEqualStatuses := func(t *testing.T, evts1, evts2 []*component.StatusEvent) { + assert.Equal(t, len(evts1), len(evts2)) + for i := 0; i < len(evts1); i++ { + ev1 := evts1[i] + ev2 := evts2[i] + assert.Equal(t, ev1.Status(), ev2.Status()) + assert.Equal(t, ev1.Err(), ev2.Err()) + } + } + + for _, tc := range []struct { + name string + expectedStatuses []*component.StatusEvent + startErr error + shutdownErr error + }{ + { + name: "successful startup/shutdown", + expectedStatuses: []*component.StatusEvent{ + component.NewStatusEvent(component.StatusStarting), + component.NewStatusEvent(component.StatusOK), + component.NewStatusEvent(component.StatusStopping), + component.NewStatusEvent(component.StatusStopped), + }, + startErr: nil, + shutdownErr: nil, + }, + { + name: "start error", + expectedStatuses: []*component.StatusEvent{ + component.NewStatusEvent(component.StatusStarting), + component.NewPermanentErrorEvent(assert.AnError), + }, + startErr: assert.AnError, + shutdownErr: nil, + }, + { + name: "shutdown error", + expectedStatuses: []*component.StatusEvent{ + component.NewStatusEvent(component.StatusStarting), + component.NewStatusEvent(component.StatusOK), + component.NewStatusEvent(component.StatusStopping), + component.NewPermanentErrorEvent(assert.AnError), + }, + startErr: nil, + shutdownErr: assert.AnError, + }, + } { + t.Run(tc.name, func(t *testing.T) { + statusType := component.MustNewType("statustest") + compID := component.NewID(statusType) + factory := newStatusTestExtensionFactory(statusType, tc.startErr, tc.shutdownErr) + config := factory.CreateDefaultConfig() + extensionsConfigs := map[component.ID]component.Config{ + compID: config, + } + factories := map[component.Type]extension.Factory{ + statusType: factory, + } + extensions, err := New( + context.Background(), + Settings{ + Telemetry: servicetelemetry.NewNopTelemetrySettings(), + BuildInfo: component.NewDefaultBuildInfo(), + Extensions: extension.NewBuilder(extensionsConfigs, factories), + }, + []component.ID{compID}, + ) + + assert.NoError(t, err) + + var actualStatuses []*component.StatusEvent + rep := status.NewReporter(func(_ *component.InstanceID, ev *component.StatusEvent) { + actualStatuses = append(actualStatuses, ev) + }, func(err error) { + require.NoError(t, err) + }) + extensions.telemetry.Status = rep + rep.Ready() + + assert.Equal(t, tc.startErr, extensions.Start(context.Background(), componenttest.NewNopHost())) + if tc.startErr == nil { + assert.Equal(t, tc.shutdownErr, extensions.Shutdown(context.Background())) + } + assertEqualStatuses(t, tc.expectedStatuses, actualStatuses) + }) + } +} + +type statusTestExtension struct { + startErr error + shutdownErr error +} + +func (ext *statusTestExtension) Start(context.Context, component.Host) error { + return ext.startErr +} + +func (ext *statusTestExtension) Shutdown(context.Context) error { + return ext.shutdownErr +} + +func newStatusTestExtension(startErr, shutdownErr error) *statusTestExtension { + return &statusTestExtension{ + startErr: startErr, + shutdownErr: shutdownErr, + } +} + +func newStatusTestExtensionFactory(name component.Type, startErr, shutdownErr error) extension.Factory { + return extension.NewFactory( + name, + func() component.Config { + return &struct{}{} + }, + func(context.Context, extension.CreateSettings, component.Config) (extension.Extension, error) { + return newStatusTestExtension(startErr, shutdownErr), nil + }, + component.StabilityLevelDevelopment, + ) +} + +func newRecordingExtensionFactory(startCallback func(set extension.CreateSettings, host component.Host) error, shutdownCallback func(set extension.CreateSettings) error) extension.Factory { + return extension.NewFactory( + component.MustNewType("recording"), + func() component.Config { + return &recordingExtensionConfig{} + }, + func(_ context.Context, set extension.CreateSettings, cfg component.Config) (extension.Extension, error) { + return &recordingExtension{ + config: cfg.(recordingExtensionConfig), + createSettings: set, + startCallback: startCallback, + shutdownCallback: shutdownCallback, + }, nil + }, + component.StabilityLevelDevelopment, + ) +} + +type recordingExtensionConfig struct { + dependencies []string // names of dependencies of the same extension type +} + +type recordingExtension struct { + config recordingExtensionConfig + startCallback func(set extension.CreateSettings, host component.Host) error + shutdownCallback func(set extension.CreateSettings) error + createSettings extension.CreateSettings +} + +var _ extension.Dependent = (*recordingExtension)(nil) + +func (ext *recordingExtension) Dependencies() []component.ID { + if len(ext.config.dependencies) == 0 { + return nil + } + deps := make([]component.ID, len(ext.config.dependencies)) + for i, dep := range ext.config.dependencies { + deps[i] = component.MustNewIDWithName("recording", dep) + } + return deps +} + +func (ext *recordingExtension) Start(_ context.Context, host component.Host) error { + return ext.startCallback(ext.createSettings, host) +} + +func (ext *recordingExtension) Shutdown(context.Context) error { + return ext.shutdownCallback(ext.createSettings) +} diff --git a/service/extensions/graph.go b/service/extensions/graph.go new file mode 100644 index 00000000000..7099d018a1f --- /dev/null +++ b/service/extensions/graph.go @@ -0,0 +1,77 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package extensions // import "go.opentelemetry.io/collector/service/extensions" + +import ( + "errors" + "fmt" + "strings" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" + "gonum.org/v1/gonum/graph/topo" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/extension" +) + +type node struct { + nodeID int64 + extID component.ID +} + +func (n node) ID() int64 { + return n.nodeID +} + +func computeOrder(exts *Extensions) ([]component.ID, error) { + graph := simple.NewDirectedGraph() + nodes := make(map[component.ID]*node) + for extID := range exts.extMap { + n := &node{ + nodeID: int64(len(nodes) + 1), + extID: extID, + } + graph.AddNode(n) + nodes[extID] = n + } + for extID, ext := range exts.extMap { + n := nodes[extID] + if dep, ok := ext.(extension.Dependent); ok { + for _, depID := range dep.Dependencies() { + if d, ok := nodes[depID]; ok { + graph.SetEdge(graph.NewEdge(d, n)) + } else { + return nil, fmt.Errorf("unable to find extension %s on which extension %s depends", depID, extID) + } + } + } + } + orderedNodes, err := topo.Sort(graph) + if err != nil { + return nil, cycleErr(err, topo.DirectedCyclesIn(graph)) + } + + order := make([]component.ID, len(orderedNodes)) + for i, n := range orderedNodes { + order[i] = n.(*node).extID + } + return order, nil +} + +func cycleErr(err error, cycles [][]graph.Node) error { + var topoErr topo.Unorderable + if !errors.As(err, &topoErr) || len(cycles) == 0 || len(cycles[0]) == 0 { + return err + } + + cycle := cycles[0] + var names []string + for _, n := range cycle { + node := n.(*node) + names = append(names, node.extID.String()) + } + cycleStr := "[" + strings.Join(names, " -> ") + "]" + return fmt.Errorf("unable to order extenions by dependencies, cycle found %s: %w", cycleStr, err) +} diff --git a/service/extensions/graph_test.go b/service/extensions/graph_test.go new file mode 100644 index 00000000000..a3a9d714afe --- /dev/null +++ b/service/extensions/graph_test.go @@ -0,0 +1,21 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package extensions // import "go.opentelemetry.io/collector/service/extensions" + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/topo" +) + +func TestCycleErr(t *testing.T) { + err := errors.New("foo") + assert.Equal(t, err, cycleErr(err, nil), "cycleErr should return the error unchanged when it's unrecognized") + + var topoErr topo.Unorderable = [][]graph.Node{{}} + assert.Equal(t, topoErr, cycleErr(topoErr, nil), "cycleErr should return topo.Unorderable error unchanged when no cycles are found") +} diff --git a/service/extensions/package_test.go b/service/extensions/package_test.go new file mode 100644 index 00000000000..92f3cf19c6a --- /dev/null +++ b/service/extensions/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package extensions + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/service/go.mod b/service/go.mod index dbe78b42af3..602137b3bbc 100644 --- a/service/go.mod +++ b/service/go.mod @@ -1,47 +1,48 @@ module go.opentelemetry.io/collector/service -go 1.20 +go 1.21 require ( - contrib.go.opencensus.io/exporter/prometheus v0.4.2 - github.com/google/uuid v1.3.1 - github.com/prometheus/client_golang v1.16.0 - github.com/prometheus/client_model v0.4.0 - github.com/prometheus/common v0.44.0 - github.com/shirou/gopsutil/v3 v3.23.8 + github.com/google/uuid v1.6.0 + github.com/prometheus/client_golang v1.19.0 + github.com/prometheus/client_model v0.6.0 + github.com/prometheus/common v0.48.0 + github.com/shirou/gopsutil/v3 v3.24.1 github.com/stretchr/testify v1.8.4 go.opencensus.io v0.24.0 - go.opentelemetry.io/collector v0.85.0 - go.opentelemetry.io/collector/component v0.85.0 - go.opentelemetry.io/collector/config/confignet v0.85.0 - go.opentelemetry.io/collector/config/configtelemetry v0.85.0 - go.opentelemetry.io/collector/confmap v0.85.0 - go.opentelemetry.io/collector/connector v0.85.0 - go.opentelemetry.io/collector/consumer v0.85.0 - go.opentelemetry.io/collector/exporter v0.85.0 - go.opentelemetry.io/collector/extension v0.85.0 - go.opentelemetry.io/collector/extension/zpagesextension v0.85.0 - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/collector/processor v0.85.0 - go.opentelemetry.io/collector/receiver v0.85.0 - go.opentelemetry.io/collector/semconv v0.85.0 - go.opentelemetry.io/contrib/propagators/b3 v1.19.0 - go.opentelemetry.io/otel v1.18.0 - go.opentelemetry.io/otel/bridge/opencensus v0.41.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.41.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.18.0 - go.opentelemetry.io/otel/exporters/prometheus v0.41.0 - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 - go.opentelemetry.io/otel/metric v1.18.0 - go.opentelemetry.io/otel/sdk v1.18.0 - go.opentelemetry.io/otel/sdk/metric v0.41.0 - go.opentelemetry.io/otel/trace v1.18.0 + go.opentelemetry.io/collector v0.96.0 + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/config/confignet v0.96.0 + go.opentelemetry.io/collector/config/configtelemetry v0.96.0 + go.opentelemetry.io/collector/confmap v0.96.0 + go.opentelemetry.io/collector/connector v0.96.0 + go.opentelemetry.io/collector/consumer v0.96.0 + go.opentelemetry.io/collector/exporter v0.96.0 + go.opentelemetry.io/collector/extension v0.96.0 + go.opentelemetry.io/collector/extension/zpagesextension v0.96.0 + go.opentelemetry.io/collector/featuregate v1.3.0 + go.opentelemetry.io/collector/pdata v1.3.0 + go.opentelemetry.io/collector/processor v0.96.0 + go.opentelemetry.io/collector/receiver v0.96.0 + go.opentelemetry.io/collector/semconv v0.96.0 + go.opentelemetry.io/contrib/config v0.4.0 + go.opentelemetry.io/contrib/propagators/b3 v1.24.0 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/bridge/opencensus v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.24.0 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 + go.opentelemetry.io/otel/sdk/metric v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 - go.uber.org/zap v1.26.0 + go.uber.org/zap v1.27.0 gonum.org/v1/gonum v0.14.0 ) @@ -50,46 +51,41 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/providers/confmap v0.1.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect + github.com/knadh/koanf/v2 v2.1.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/prometheus/procfs v0.10.1 // indirect - github.com/prometheus/statsd_exporter v0.22.7 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - go.opentelemetry.io/contrib/zpages v0.44.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + go.opentelemetry.io/contrib/zpages v0.49.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -122,3 +118,5 @@ replace go.opentelemetry.io/collector/receiver => ../receiver replace go.opentelemetry.io/collector/featuregate => ../featuregate replace go.opentelemetry.io/collector/config/confignet => ../config/confignet + +replace go.opentelemetry.io/collector/config/configretry => ../config/configretry diff --git a/service/go.sum b/service/go.sum index 693484f860c..a888ca2c937 100644 --- a/service/go.sum +++ b/service/go.sum @@ -1,60 +1,12 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -64,462 +16,210 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= +github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= -github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= +github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= -go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ= -go.opentelemetry.io/contrib/zpages v0.44.0 h1:9J/cxTTWhM6kzgdaBt6NiXS2HUreXn/eW2M+vzHgDAQ= -go.opentelemetry.io/contrib/zpages v0.44.0/go.mod h1:G3eNCGhodjn2wIdM+i6GneZb1Cqg6dNRBlm1cpNEElg= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/bridge/opencensus v0.41.0 h1:VBpeaTbrvLFHvRtsyCJXjsTaicBNrAFdmctiN1k6WNI= -go.opentelemetry.io/otel/bridge/opencensus v0.41.0/go.mod h1:yCQB5IKRhgjlbTLc91+ixcZc2/8BncGGJ+CS3dZJwtY= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 h1:k0k7hFNDd8K4iOMJXj7s8sHaC4mhTlAeppRmZXLgZ6k= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 h1:HgbDTD8pioFdY3NRc/YCvsWjqQPtweGyXxa32LgnTOw= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0/go.mod h1:tmvt/yK5Es5d6lHYWerLSOna8lCEfrBVX/a9M0ggqss= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.41.0 h1:iV3BOgW4fry1Riw9dwypigqlIYWXvSRVT2RJmblzo40= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.41.0/go.mod h1:7PGzqlKrxIRmbj5tlNW0nTkYZ5fHXDgk6Fy8/KjR0CI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.18.0 h1:6pu8ttx76BxHf+xz/H77AUZkPF3cwWzXqAUsXhVKI18= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.18.0/go.mod h1:IOmXxPrxoxFMXdNy7lfDmE8MzE61YPcurbUm0SMjerI= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 h1:XzjGkawtAXs20Y+s6k1GNDMBsMDOV28TOT8cxmE42qM= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0/go.mod h1:HAomEgjcKZk3VJ+HHdHLnhZXeGqdzPxxNTdKYRopUXY= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.opentelemetry.io/contrib/config v0.4.0 h1:Xb+ncYOqseLroMuBesGNRgVQolXcXOhMj7EhGwJCdHs= +go.opentelemetry.io/contrib/config v0.4.0/go.mod h1:drNk2xRqLWW4/amk6Uh1S+sDAJTc7bcEEN1GfJzj418= +go.opentelemetry.io/contrib/propagators/b3 v1.24.0 h1:n4xwCdTx3pZqZs2CjS/CUZAs03y3dZcGhC/FepKtEUY= +go.opentelemetry.io/contrib/propagators/b3 v1.24.0/go.mod h1:k5wRxKRU2uXx2F8uNJ4TaonuEO/V7/5xoz7kdsDACT8= +go.opentelemetry.io/contrib/zpages v0.49.0 h1:Wk217PkNBxcKWnIQpwtbZZE286K4ZY9uajnM5woSeLU= +go.opentelemetry.io/contrib/zpages v0.49.0/go.mod h1:6alLi5mmkZWbAtZMRPd1ffIgkTcsU9OTHQF2NbSOhrQ= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/bridge/opencensus v1.24.0 h1:Vlhy5ee5k5R0zASpH+9AgHiJH7xnKACI3XopO1tUZfY= +go.opentelemetry.io/otel/bridge/opencensus v1.24.0/go.mod h1:jRjVXV/X38jyrnHtvMGN8+9cejZB21JvXAAvooF2s+Q= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0 h1:f2jriWfOdldanBwS9jNBdeOKAQN7b4ugAMaNu1/1k9g= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0/go.mod h1:B+bcQI1yTY+N0vqMpoZbEN7+XU4tNM0DmUiOwebFJWI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0 h1:mM8nKi6/iFQ0iqst80wDHU2ge198Ye/TfN0WBS5U24Y= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0/go.mod h1:0PrIIzDteLSmNyxqcGYRL4mDIo8OTuBAOI/Bn1URxac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.24.0 h1:JYE2HM7pZbOt5Jhk8ndWZTUWYOVift2cHjXVMkPdmdc= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.24.0/go.mod h1:yMb/8c6hVsnma0RpsBMNo0fEiQKeclawtgaIaOp2MLY= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +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= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -527,77 +227,24 @@ 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= gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -606,37 +253,16 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/service/host.go b/service/host.go index d216ae94adb..870e0bfc446 100644 --- a/service/host.go +++ b/service/host.go @@ -30,13 +30,6 @@ type serviceHost struct { serviceExtensions *extensions.Extensions } -// ReportFatalError is used to report to the host that the receiver encountered -// a fatal error (i.e.: an error that the instance can't recover from) after -// its start function has already returned. -func (host *serviceHost) ReportFatalError(err error) { - host.asyncErrorChannel <- err -} - func (host *serviceHost) GetFactory(kind component.Kind, componentType component.Type) component.Factory { switch kind { case component.KindReceiver: @@ -66,3 +59,10 @@ func (host *serviceHost) GetExtensions() map[component.ID]component.Component { func (host *serviceHost) GetExporters() map[component.DataType]map[component.ID]component.Component { return host.pipelines.GetExporters() } + +func (host *serviceHost) notifyComponentStatusChange(source *component.InstanceID, event *component.StatusEvent) { + host.serviceExtensions.NotifyComponentStatusChange(source, event) + if event.Status() == component.StatusFatalError { + host.asyncErrorChannel <- event.Err() + } +} diff --git a/service/internal/capabilityconsumer/package_test.go b/service/internal/capabilityconsumer/package_test.go new file mode 100644 index 00000000000..3d41da10e31 --- /dev/null +++ b/service/internal/capabilityconsumer/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package capabilityconsumer + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/service/internal/components/components.go b/service/internal/components/components.go deleted file mode 100644 index 5cb52f3e910..00000000000 --- a/service/internal/components/components.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package components // import "go.opentelemetry.io/collector/service/internal/components" - -import ( - "go.uber.org/zap" - - "go.opentelemetry.io/collector/component" -) - -// LogStabilityLevel logs the stability level of a component. The log level is set to info for -// undefined, unmaintained, deprecated and development. The log level is set to debug -// for alpha, beta and stable. -func LogStabilityLevel(logger *zap.Logger, sl component.StabilityLevel) { - if sl >= component.StabilityLevelAlpha { - logger.Debug(sl.LogMessage(), zap.String(zapStabilityKey, sl.String())) - } else { - logger.Info(sl.LogMessage(), zap.String(zapStabilityKey, sl.String())) - } -} diff --git a/service/internal/components/components_test.go b/service/internal/components/components_test.go deleted file mode 100644 index 7fcb98486cb..00000000000 --- a/service/internal/components/components_test.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package components // import "go.opentelemetry.io/collector/service/internal/components" - -import ( - "testing" - - "github.com/stretchr/testify/require" - "go.uber.org/zap" - "go.uber.org/zap/zapcore" - "go.uber.org/zap/zaptest/observer" - - "go.opentelemetry.io/collector/component" -) - -func TestLogStabilityLevel(t *testing.T) { - tests := []struct { - level zapcore.Level - expectedLogs int - }{ - { - level: zapcore.DebugLevel, - expectedLogs: 7, - }, - { - level: zapcore.InfoLevel, - expectedLogs: 4, - }, - } - - for _, tt := range tests { - observed, logs := observer.New(tt.level) - logger := zap.New(observed) - // ensure log levels are set correctly for each stability level - LogStabilityLevel(logger, component.StabilityLevelUndefined) - LogStabilityLevel(logger, component.StabilityLevelUnmaintained) - LogStabilityLevel(logger, component.StabilityLevelDeprecated) - LogStabilityLevel(logger, component.StabilityLevelDevelopment) - LogStabilityLevel(logger, component.StabilityLevelAlpha) - LogStabilityLevel(logger, component.StabilityLevelBeta) - LogStabilityLevel(logger, component.StabilityLevelStable) - require.Equal(t, tt.expectedLogs, logs.Len()) - } -} diff --git a/service/internal/components/host_wrapper.go b/service/internal/components/host_wrapper.go deleted file mode 100644 index 2d386ddad67..00000000000 --- a/service/internal/components/host_wrapper.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package components // import "go.opentelemetry.io/collector/service/internal/components" - -import ( - "net/http" - - "go.uber.org/zap" - - "go.opentelemetry.io/collector/component" -) - -// hostWrapper adds behavior on top of the component.Host being passed when starting the built components. -type hostWrapper struct { - component.Host - *zap.Logger -} - -func NewHostWrapper(host component.Host, logger *zap.Logger) component.Host { - return &hostWrapper{ - host, - logger, - } -} - -func (hw *hostWrapper) ReportFatalError(err error) { - // The logger from the built component already identifies the component. - hw.Logger.Error("Component fatal error", zap.Error(err)) - hw.Host.ReportFatalError(err) -} - -// RegisterZPages is used by zpages extension to register handles from service. -// When the wrapper is passed to the extension it won't be successful when casting -// the interface, for the time being expose the interface here. -// TODO: Find a better way to add the service zpages to the extension. This a temporary fix. -func (hw *hostWrapper) RegisterZPages(mux *http.ServeMux, pathPrefix string) { - if zpagesHost, ok := hw.Host.(interface { - RegisterZPages(mux *http.ServeMux, pathPrefix string) - }); ok { - zpagesHost.RegisterZPages(mux, pathPrefix) - } -} diff --git a/service/internal/components/host_wrapper_test.go b/service/internal/components/host_wrapper_test.go deleted file mode 100644 index 62b7a744681..00000000000 --- a/service/internal/components/host_wrapper_test.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package components - -import ( - "errors" - "testing" - - "go.uber.org/zap" - - "go.opentelemetry.io/collector/component/componenttest" -) - -func Test_newHostWrapper(_ *testing.T) { - hw := NewHostWrapper(componenttest.NewNopHost(), zap.NewNop()) - hw.ReportFatalError(errors.New("test error")) -} diff --git a/service/internal/components/loggers.go b/service/internal/components/loggers.go index 3cb88ae0d44..f4178977b2d 100644 --- a/service/internal/components/loggers.go +++ b/service/internal/components/loggers.go @@ -4,6 +4,8 @@ package components // import "go.opentelemetry.io/collector/service/internal/components" import ( + "strings" + "go.uber.org/zap" "go.opentelemetry.io/collector/component" @@ -11,49 +13,45 @@ import ( const ( zapKindKey = "kind" - zapKindReceiver = "receiver" - zapKindProcessor = "processor" - zapKindExporter = "exporter" - zapKindExtension = "extension" - zapKindPipeline = "pipeline" zapNameKey = "name" zapDataTypeKey = "data_type" zapStabilityKey = "stability" + zapPipelineKey = "pipeline" zapExporterInPipeline = "exporter_in_pipeline" zapReceiverInPipeline = "receiver_in_pipeline" ) func ReceiverLogger(logger *zap.Logger, id component.ID, dt component.DataType) *zap.Logger { return logger.With( - zap.String(zapKindKey, zapKindReceiver), + zap.String(zapKindKey, strings.ToLower(component.KindReceiver.String())), zap.String(zapNameKey, id.String()), - zap.String(zapDataTypeKey, string(dt))) + zap.String(zapDataTypeKey, dt.String())) } func ProcessorLogger(logger *zap.Logger, id component.ID, pipelineID component.ID) *zap.Logger { return logger.With( - zap.String(zapKindKey, zapKindProcessor), + zap.String(zapKindKey, strings.ToLower(component.KindProcessor.String())), zap.String(zapNameKey, id.String()), - zap.String(zapKindPipeline, pipelineID.String())) + zap.String(zapPipelineKey, pipelineID.String())) } func ExporterLogger(logger *zap.Logger, id component.ID, dt component.DataType) *zap.Logger { return logger.With( - zap.String(zapKindKey, zapKindExporter), - zap.String(zapDataTypeKey, string(dt)), + zap.String(zapKindKey, strings.ToLower(component.KindExporter.String())), + zap.String(zapDataTypeKey, dt.String()), zap.String(zapNameKey, id.String())) } func ExtensionLogger(logger *zap.Logger, id component.ID) *zap.Logger { return logger.With( - zap.String(zapKindKey, zapKindExtension), + zap.String(zapKindKey, strings.ToLower(component.KindExtension.String())), zap.String(zapNameKey, id.String())) } func ConnectorLogger(logger *zap.Logger, id component.ID, expDT, rcvDT component.DataType) *zap.Logger { return logger.With( - zap.String(zapKindKey, zapKindExporter), + zap.String(zapKindKey, strings.ToLower(component.KindConnector.String())), zap.String(zapNameKey, id.String()), - zap.String(zapExporterInPipeline, string(expDT)), - zap.String(zapReceiverInPipeline, string(rcvDT))) + zap.String(zapExporterInPipeline, expDT.String()), + zap.String(zapReceiverInPipeline, rcvDT.String())) } diff --git a/service/internal/components/package_test.go b/service/internal/components/package_test.go new file mode 100644 index 00000000000..30b5a82311a --- /dev/null +++ b/service/internal/components/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package components + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/service/internal/graph/graph.go b/service/internal/graph/graph.go index 5b8a404d66f..04643a37526 100644 --- a/service/internal/graph/graph.go +++ b/service/internal/graph/graph.go @@ -22,12 +22,13 @@ import ( "go.opentelemetry.io/collector/processor" "go.opentelemetry.io/collector/receiver" "go.opentelemetry.io/collector/service/internal/capabilityconsumer" + "go.opentelemetry.io/collector/service/internal/servicetelemetry" "go.opentelemetry.io/collector/service/pipelines" ) // Settings holds configuration for building builtPipelines. type Settings struct { - Telemetry component.TelemetrySettings + Telemetry servicetelemetry.TelemetrySettings BuildInfo component.BuildInfo ReceiverBuilder *receiver.Builder @@ -45,12 +46,19 @@ type Graph struct { // Keep track of how nodes relate to pipelines, so we can declare edges in the graph. pipelines map[component.ID]*pipelineNodes + + // Keep track of status source per node + instanceIDs map[int64]*component.InstanceID + + telemetry servicetelemetry.TelemetrySettings } func Build(ctx context.Context, set Settings) (*Graph, error) { pipelines := &Graph{ componentGraph: simple.NewDirectedGraph(), pipelines: make(map[component.ID]*pipelineNodes, len(set.PipelineConfigs)), + instanceIDs: make(map[int64]*component.InstanceID), + telemetry: set.Telemetry, } for pipelineID := range set.PipelineConfigs { pipelines.pipelines[pipelineID] = &pipelineNodes{ @@ -82,14 +90,15 @@ func (g *Graph) createNodes(set Settings) error { connectorsAsReceiver[recvID] = append(connectorsAsReceiver[recvID], pipelineID) continue } - rcvrNode := g.createReceiver(pipelineID.Type(), recvID) + rcvrNode := g.createReceiver(pipelineID, recvID) pipe.receivers[rcvrNode.ID()] = rcvrNode } pipe.capabilitiesNode = newCapabilitiesNode(pipelineID) for _, procID := range pipelineCfg.Processors { - pipe.processors = append(pipe.processors, g.createProcessor(pipelineID, procID)) + procNode := g.createProcessor(pipelineID, procID) + pipe.processors = append(pipe.processors, procNode) } pipe.fanOutNode = newFanOutNode(pipelineID) @@ -100,7 +109,7 @@ func (g *Graph) createNodes(set Settings) error { connectorsAsExporter[exprID] = append(connectorsAsExporter[exprID], pipelineID) continue } - expNode := g.createExporter(pipelineID.Type(), exprID) + expNode := g.createExporter(pipelineID, exprID) pipe.exporters[expNode.ID()] = expNode } } @@ -156,6 +165,7 @@ func (g *Graph) createNodes(set Settings) error { continue } connNode := g.createConnector(eID, rID, connID) + g.pipelines[eID].exporters[connNode.ID()] = connNode g.pipelines[rID].receivers[connNode.ID()] = connNode } @@ -164,36 +174,70 @@ func (g *Graph) createNodes(set Settings) error { return nil } -func (g *Graph) createReceiver(pipelineType component.DataType, recvID component.ID) *receiverNode { - rcvrNode := newReceiverNode(pipelineType, recvID) +func (g *Graph) createReceiver(pipelineID, recvID component.ID) *receiverNode { + rcvrNode := newReceiverNode(pipelineID.Type(), recvID) if node := g.componentGraph.Node(rcvrNode.ID()); node != nil { + g.instanceIDs[node.ID()].PipelineIDs[pipelineID] = struct{}{} return node.(*receiverNode) } g.componentGraph.AddNode(rcvrNode) + g.instanceIDs[rcvrNode.ID()] = &component.InstanceID{ + ID: recvID, + Kind: component.KindReceiver, + PipelineIDs: map[component.ID]struct{}{ + pipelineID: {}, + }, + } return rcvrNode } func (g *Graph) createProcessor(pipelineID, procID component.ID) *processorNode { procNode := newProcessorNode(pipelineID, procID) g.componentGraph.AddNode(procNode) + g.instanceIDs[procNode.ID()] = &component.InstanceID{ + ID: procID, + Kind: component.KindProcessor, + PipelineIDs: map[component.ID]struct{}{ + pipelineID: {}, + }, + } return procNode } -func (g *Graph) createExporter(pipelineType component.DataType, exprID component.ID) *exporterNode { - expNode := newExporterNode(pipelineType, exprID) +func (g *Graph) createExporter(pipelineID, exprID component.ID) *exporterNode { + expNode := newExporterNode(pipelineID.Type(), exprID) if node := g.componentGraph.Node(expNode.ID()); node != nil { + g.instanceIDs[expNode.ID()].PipelineIDs[pipelineID] = struct{}{} return node.(*exporterNode) } g.componentGraph.AddNode(expNode) + g.instanceIDs[expNode.ID()] = &component.InstanceID{ + ID: expNode.componentID, + Kind: component.KindExporter, + PipelineIDs: map[component.ID]struct{}{ + pipelineID: {}, + }, + } return expNode } func (g *Graph) createConnector(exprPipelineID, rcvrPipelineID, connID component.ID) *connectorNode { connNode := newConnectorNode(exprPipelineID.Type(), rcvrPipelineID.Type(), connID) if node := g.componentGraph.Node(connNode.ID()); node != nil { + instanceID := g.instanceIDs[connNode.ID()] + instanceID.PipelineIDs[exprPipelineID] = struct{}{} + instanceID.PipelineIDs[rcvrPipelineID] = struct{}{} return node.(*connectorNode) } g.componentGraph.AddNode(connNode) + g.instanceIDs[connNode.ID()] = &component.InstanceID{ + ID: connNode.componentID, + Kind: component.KindConnector, + PipelineIDs: map[component.ID]struct{}{ + exprPipelineID: {}, + rcvrPipelineID: {}, + }, + } return connNode } @@ -227,17 +271,27 @@ func (g *Graph) buildComponents(ctx context.Context, set Settings) error { for i := len(nodes) - 1; i >= 0; i-- { node := nodes[i] + + // skipped for capabilitiesNodes and fanoutNodes as they are not assigned componentIDs. + var telemetrySettings component.TelemetrySettings + if instanceID, ok := g.instanceIDs[node.ID()]; ok { + telemetrySettings = set.Telemetry.ToComponentTelemetrySettings(instanceID) + } + switch n := node.(type) { case *receiverNode: - err = n.buildComponent(ctx, set.Telemetry, set.BuildInfo, set.ReceiverBuilder, g.nextConsumers(n.ID())) + err = n.buildComponent(ctx, telemetrySettings, set.BuildInfo, set.ReceiverBuilder, g.nextConsumers(n.ID())) case *processorNode: - err = n.buildComponent(ctx, set.Telemetry, set.BuildInfo, set.ProcessorBuilder, g.nextConsumers(n.ID())[0]) + err = n.buildComponent(ctx, telemetrySettings, set.BuildInfo, set.ProcessorBuilder, g.nextConsumers(n.ID())[0]) case *exporterNode: - err = n.buildComponent(ctx, set.Telemetry, set.BuildInfo, set.ExporterBuilder) + err = n.buildComponent(ctx, telemetrySettings, set.BuildInfo, set.ExporterBuilder) case *connectorNode: - err = n.buildComponent(ctx, set.Telemetry, set.BuildInfo, set.ConnectorBuilder, g.nextConsumers(n.ID())) + err = n.buildComponent(ctx, telemetrySettings, set.BuildInfo, set.ConnectorBuilder, g.nextConsumers(n.ID())) case *capabilitiesNode: - capability := consumer.Capabilities{MutatesData: false} + capability := consumer.Capabilities{ + // The fanOutNode represents the aggregate capabilities of the exporters in the pipeline. + MutatesData: g.pipelines[n.pipelineID].fanOutNode.getConsumer().Capabilities().MutatesData, + } for _, proc := range g.pipelines[n.pipelineID].processors { capability.MutatesData = capability.MutatesData || proc.getConsumer().Capabilities().MutatesData } @@ -268,7 +322,6 @@ func (g *Graph) buildComponents(ctx context.Context, set Settings) error { case component.DataTypeMetrics: consumers := make([]consumer.Metrics, 0, len(nexts)) for _, next := range nexts { - consumers = append(consumers, next.(consumer.Metrics)) } n.baseConsumer = fanoutconsumer.NewMetrics(consumers) @@ -326,14 +379,29 @@ func (g *Graph) StartAll(ctx context.Context, host component.Host) error { // are started before upstream components. This ensures that each // component's consumer is ready to consume. for i := len(nodes) - 1; i >= 0; i-- { - comp, ok := nodes[i].(component.Component) + node := nodes[i] + comp, ok := node.(component.Component) + if !ok { // Skip capabilities/fanout nodes continue } + + instanceID := g.instanceIDs[node.ID()] + g.telemetry.Status.ReportStatus( + instanceID, + component.NewStatusEvent(component.StatusStarting), + ) + if compErr := comp.Start(ctx, host); compErr != nil { + g.telemetry.Status.ReportStatus( + instanceID, + component.NewPermanentErrorEvent(compErr), + ) return compErr } + + g.telemetry.Status.ReportOKIfStarting(instanceID) } return nil } @@ -350,12 +418,33 @@ func (g *Graph) ShutdownAll(ctx context.Context) error { // before the consumer is stopped. var errs error for i := 0; i < len(nodes); i++ { - comp, ok := nodes[i].(component.Component) + node := nodes[i] + comp, ok := node.(component.Component) + if !ok { // Skip capabilities/fanout nodes continue } - errs = multierr.Append(errs, comp.Shutdown(ctx)) + + instanceID := g.instanceIDs[node.ID()] + g.telemetry.Status.ReportStatus( + instanceID, + component.NewStatusEvent(component.StatusStopping), + ) + + if compErr := comp.Shutdown(ctx); compErr != nil { + errs = multierr.Append(errs, compErr) + g.telemetry.Status.ReportStatus( + instanceID, + component.NewPermanentErrorEvent(compErr), + ) + continue + } + + g.telemetry.Status.ReportStatus( + instanceID, + component.NewStatusEvent(component.StatusStopped), + ) } return errs } diff --git a/service/internal/graph/graph_test.go b/service/internal/graph/graph_test.go index 1279ff145d5..9ae936b5d05 100644 --- a/service/internal/graph/graph_test.go +++ b/service/internal/graph/graph_test.go @@ -7,6 +7,7 @@ import ( "context" "errors" "fmt" + "strings" "sync" "testing" @@ -27,6 +28,8 @@ import ( "go.opentelemetry.io/collector/processor/processortest" "go.opentelemetry.io/collector/receiver" "go.opentelemetry.io/collector/receiver/receivertest" + "go.opentelemetry.io/collector/service/internal/servicetelemetry" + "go.opentelemetry.io/collector/service/internal/status" "go.opentelemetry.io/collector/service/internal/testcomponents" "go.opentelemetry.io/collector/service/pipelines" ) @@ -87,48 +90,48 @@ func TestGraphStartStop(t *testing.T) { { name: "single", edges: [][2]component.ID{ - {component.NewIDWithName("r", "1"), component.NewIDWithName("p", "1")}, - {component.NewIDWithName("r", "2"), component.NewIDWithName("p", "1")}, - {component.NewIDWithName("p", "1"), component.NewIDWithName("p", "2")}, - {component.NewIDWithName("p", "2"), component.NewIDWithName("e", "1")}, - {component.NewIDWithName("p", "1"), component.NewIDWithName("e", "2")}, + {component.MustNewIDWithName("r", "1"), component.MustNewIDWithName("p", "1")}, + {component.MustNewIDWithName("r", "2"), component.MustNewIDWithName("p", "1")}, + {component.MustNewIDWithName("p", "1"), component.MustNewIDWithName("p", "2")}, + {component.MustNewIDWithName("p", "2"), component.MustNewIDWithName("e", "1")}, + {component.MustNewIDWithName("p", "1"), component.MustNewIDWithName("e", "2")}, }, }, { name: "multi", edges: [][2]component.ID{ // Pipeline 1 - {component.NewIDWithName("r", "1"), component.NewIDWithName("p", "1")}, - {component.NewIDWithName("r", "2"), component.NewIDWithName("p", "1")}, - {component.NewIDWithName("p", "1"), component.NewIDWithName("p", "2")}, - {component.NewIDWithName("p", "2"), component.NewIDWithName("e", "1")}, - {component.NewIDWithName("p", "1"), component.NewIDWithName("e", "2")}, + {component.MustNewIDWithName("r", "1"), component.MustNewIDWithName("p", "1")}, + {component.MustNewIDWithName("r", "2"), component.MustNewIDWithName("p", "1")}, + {component.MustNewIDWithName("p", "1"), component.MustNewIDWithName("p", "2")}, + {component.MustNewIDWithName("p", "2"), component.MustNewIDWithName("e", "1")}, + {component.MustNewIDWithName("p", "1"), component.MustNewIDWithName("e", "2")}, // Pipeline 2, shares r1 and e2 - {component.NewIDWithName("r", "1"), component.NewIDWithName("p", "3")}, - {component.NewIDWithName("p", "3"), component.NewIDWithName("e", "2")}, + {component.MustNewIDWithName("r", "1"), component.MustNewIDWithName("p", "3")}, + {component.MustNewIDWithName("p", "3"), component.MustNewIDWithName("e", "2")}, }, }, { name: "connected", edges: [][2]component.ID{ // Pipeline 1 - {component.NewIDWithName("r", "1"), component.NewIDWithName("p", "1")}, - {component.NewIDWithName("r", "2"), component.NewIDWithName("p", "1")}, - {component.NewIDWithName("p", "1"), component.NewIDWithName("p", "2")}, - {component.NewIDWithName("p", "2"), component.NewIDWithName("e", "1")}, - {component.NewIDWithName("p", "1"), component.NewIDWithName("c", "1")}, + {component.MustNewIDWithName("r", "1"), component.MustNewIDWithName("p", "1")}, + {component.MustNewIDWithName("r", "2"), component.MustNewIDWithName("p", "1")}, + {component.MustNewIDWithName("p", "1"), component.MustNewIDWithName("p", "2")}, + {component.MustNewIDWithName("p", "2"), component.MustNewIDWithName("e", "1")}, + {component.MustNewIDWithName("p", "1"), component.MustNewIDWithName("c", "1")}, // Pipeline 2, shares r1 and c1 - {component.NewIDWithName("r", "1"), component.NewIDWithName("p", "3")}, - {component.NewIDWithName("p", "3"), component.NewIDWithName("c", "1")}, + {component.MustNewIDWithName("r", "1"), component.MustNewIDWithName("p", "3")}, + {component.MustNewIDWithName("p", "3"), component.MustNewIDWithName("c", "1")}, // Pipeline 3, emits to e2 and c2 - {component.NewIDWithName("c", "1"), component.NewIDWithName("e", "2")}, - {component.NewIDWithName("c", "1"), component.NewIDWithName("c", "2")}, + {component.MustNewIDWithName("c", "1"), component.MustNewIDWithName("e", "2")}, + {component.MustNewIDWithName("c", "1"), component.MustNewIDWithName("c", "2")}, // Pipeline 4, also emits to e2 - {component.NewIDWithName("c", "2"), component.NewIDWithName("e", "2")}, + {component.MustNewIDWithName("c", "2"), component.MustNewIDWithName("e", "2")}, }, }, } @@ -141,8 +144,13 @@ func TestGraphStartStop(t *testing.T) { } pg := &Graph{componentGraph: simple.NewDirectedGraph()} + pg.telemetry = servicetelemetry.NewNopTelemetrySettings() + pg.instanceIDs = make(map[int64]*component.InstanceID) + for _, edge := range tt.edges { f, t := &testNode{id: edge[0]}, &testNode{id: edge[1]} + pg.instanceIDs[f.ID()] = &component.InstanceID{} + pg.instanceIDs[t.ID()] = &component.InstanceID{} pg.componentGraph.SetEdge(simple.Edge{F: f, T: t}) } @@ -163,10 +171,17 @@ func TestGraphStartStop(t *testing.T) { func TestGraphStartStopCycle(t *testing.T) { pg := &Graph{componentGraph: simple.NewDirectedGraph()} - r1 := &testNode{id: component.NewIDWithName("r", "1")} - p1 := &testNode{id: component.NewIDWithName("p", "1")} - c1 := &testNode{id: component.NewIDWithName("c", "1")} - e1 := &testNode{id: component.NewIDWithName("e", "1")} + r1 := &testNode{id: component.MustNewIDWithName("r", "1")} + p1 := &testNode{id: component.MustNewIDWithName("p", "1")} + c1 := &testNode{id: component.MustNewIDWithName("c", "1")} + e1 := &testNode{id: component.MustNewIDWithName("e", "1")} + + pg.instanceIDs = map[int64]*component.InstanceID{ + r1.ID(): {}, + p1.ID(): {}, + c1.ID(): {}, + e1.ID(): {}, + } pg.componentGraph.SetEdge(simple.Edge{F: r1, T: p1}) pg.componentGraph.SetEdge(simple.Edge{F: p1, T: c1}) @@ -184,15 +199,22 @@ func TestGraphStartStopCycle(t *testing.T) { func TestGraphStartStopComponentError(t *testing.T) { pg := &Graph{componentGraph: simple.NewDirectedGraph()} + pg.telemetry = servicetelemetry.NewNopTelemetrySettings() + r1 := &testNode{ + id: component.MustNewIDWithName("r", "1"), + startErr: errors.New("foo"), + } + e1 := &testNode{ + id: component.MustNewIDWithName("e", "1"), + shutdownErr: errors.New("bar"), + } + pg.instanceIDs = map[int64]*component.InstanceID{ + r1.ID(): {}, + e1.ID(): {}, + } pg.componentGraph.SetEdge(simple.Edge{ - F: &testNode{ - id: component.NewIDWithName("r", "1"), - startErr: errors.New("foo"), - }, - T: &testNode{ - id: component.NewIDWithName("e", "1"), - shutdownErr: errors.New("bar"), - }, + F: r1, + T: e1, }) assert.EqualError(t, pg.StartAll(context.Background(), componenttest.NewNopHost()), "foo") assert.EqualError(t, pg.ShutdownAll(context.Background()), "bar") @@ -207,20 +229,20 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_simple.yaml", pipelineConfigs: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 1, @@ -228,20 +250,20 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_simple_mutate.yaml", pipelineConfigs: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 1, @@ -249,20 +271,20 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_simple_multi_proc.yaml", pipelineConfigs: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor"), component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor"), component.MustNewIDWithName("exampleprocessor", "mutate")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor"), component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor"), component.MustNewIDWithName("exampleprocessor", "mutate")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor"), component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor"), component.MustNewIDWithName("exampleprocessor", "mutate")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 1, @@ -270,17 +292,17 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_simple_no_proc.yaml", pipelineConfigs: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 1, @@ -288,20 +310,20 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_multi.yaml", pipelineConfigs: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("examplereceiver"), component.NewIDWithName("examplereceiver", "1")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate"), component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter"), component.NewIDWithName("exampleexporter", "1")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("examplereceiver"), component.MustNewIDWithName("examplereceiver", "1")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate"), component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter"), component.MustNewIDWithName("exampleexporter", "1")}, }, - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("examplereceiver"), component.NewIDWithName("examplereceiver", "1")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate"), component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter"), component.NewIDWithName("exampleexporter", "1")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("examplereceiver"), component.MustNewIDWithName("examplereceiver", "1")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate"), component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter"), component.MustNewIDWithName("exampleexporter", "1")}, }, - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("examplereceiver"), component.NewIDWithName("examplereceiver", "1")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate"), component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter"), component.NewIDWithName("exampleexporter", "1")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("examplereceiver"), component.MustNewIDWithName("examplereceiver", "1")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate"), component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter"), component.MustNewIDWithName("exampleexporter", "1")}, }, }, expectedPerExporter: 2, @@ -309,17 +331,17 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_multi_no_proc.yaml", pipelineConfigs: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("examplereceiver"), component.NewIDWithName("examplereceiver", "1")}, - Exporters: []component.ID{component.NewID("exampleexporter"), component.NewIDWithName("exampleexporter", "1")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("examplereceiver"), component.MustNewIDWithName("examplereceiver", "1")}, + Exporters: []component.ID{component.MustNewID("exampleexporter"), component.MustNewIDWithName("exampleexporter", "1")}, }, - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("examplereceiver"), component.NewIDWithName("examplereceiver", "1")}, - Exporters: []component.ID{component.NewID("exampleexporter"), component.NewIDWithName("exampleexporter", "1")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("examplereceiver"), component.MustNewIDWithName("examplereceiver", "1")}, + Exporters: []component.ID{component.MustNewID("exampleexporter"), component.MustNewIDWithName("exampleexporter", "1")}, }, - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("examplereceiver"), component.NewIDWithName("examplereceiver", "1")}, - Exporters: []component.ID{component.NewID("exampleexporter"), component.NewIDWithName("exampleexporter", "1")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("examplereceiver"), component.MustNewIDWithName("examplereceiver", "1")}, + Exporters: []component.ID{component.MustNewID("exampleexporter"), component.MustNewIDWithName("exampleexporter", "1")}, }, }, expectedPerExporter: 2, @@ -327,32 +349,32 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "multi_pipeline_receivers_and_exporters.yaml", pipelineConfigs: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewIDWithName("traces", "1"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("traces", "1"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewIDWithName("metrics", "1"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("metrics", "1"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewIDWithName("logs", "1"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("logs", "1"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 2, @@ -360,15 +382,15 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_conn_simple_traces.yaml", pipelineConfigs: pipelines.Config{ - component.NewIDWithName("traces", "in"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleconnector")}, // wrapped w/ mutates: true + component.MustNewIDWithName("traces", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, }, - component.NewIDWithName("traces", "out"): { - Receivers: []component.ID{component.NewID("exampleconnector")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("traces", "out"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, // mutate propagates upstream to connector + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 1, @@ -376,15 +398,15 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_conn_simple_metrics.yaml", pipelineConfigs: pipelines.Config{ - component.NewIDWithName("metrics", "in"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleconnector")}, // wrapped w/ mutates: true + component.MustNewIDWithName("metrics", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, }, - component.NewIDWithName("metrics", "out"): { - Receivers: []component.ID{component.NewID("exampleconnector")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("metrics", "out"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, // mutate propagates upstream to connector + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 1, @@ -392,15 +414,15 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_conn_simple_logs.yaml", pipelineConfigs: pipelines.Config{ - component.NewIDWithName("logs", "in"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleconnector")}, // wrapped w/ mutates: true + component.MustNewIDWithName("logs", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, }, - component.NewIDWithName("logs", "out"): { - Receivers: []component.ID{component.NewID("exampleconnector")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("logs", "out"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, // mutate propagates upstream to connector + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 1, @@ -408,25 +430,25 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_conn_fork_merge_traces.yaml", pipelineConfigs: pipelines.Config{ - component.NewIDWithName("traces", "in"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewIDWithName("exampleconnector", "fork")}, // wrapped w/ mutates: true + component.MustNewIDWithName("traces", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, }, - component.NewIDWithName("traces", "type0"): { - Receivers: []component.ID{component.NewIDWithName("exampleconnector", "fork")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewIDWithName("exampleconnector", "merge")}, + component.MustNewIDWithName("traces", "type0"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "merge")}, }, - component.NewIDWithName("traces", "type1"): { - Receivers: []component.ID{component.NewIDWithName("exampleconnector", "fork")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewIDWithName("exampleconnector", "merge")}, + component.MustNewIDWithName("traces", "type1"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, // mutate propagates upstream to connector + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "merge")}, }, - component.NewIDWithName("traces", "out"): { - Receivers: []component.ID{component.NewIDWithName("exampleconnector", "merge")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("traces", "out"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "merge")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 2, @@ -434,25 +456,25 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_conn_fork_merge_metrics.yaml", pipelineConfigs: pipelines.Config{ - component.NewIDWithName("metrics", "in"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewIDWithName("exampleconnector", "fork")}, // wrapped w/ mutates: true + component.MustNewIDWithName("metrics", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, }, - component.NewIDWithName("metrics", "type0"): { - Receivers: []component.ID{component.NewIDWithName("exampleconnector", "fork")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewIDWithName("exampleconnector", "merge")}, + component.MustNewIDWithName("metrics", "type0"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "merge")}, }, - component.NewIDWithName("metrics", "type1"): { - Receivers: []component.ID{component.NewIDWithName("exampleconnector", "fork")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewIDWithName("exampleconnector", "merge")}, + component.MustNewIDWithName("metrics", "type1"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, // mutate propagates upstream to connector + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "merge")}, }, - component.NewIDWithName("metrics", "out"): { - Receivers: []component.ID{component.NewIDWithName("exampleconnector", "merge")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("metrics", "out"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "merge")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 2, @@ -460,25 +482,25 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_conn_fork_merge_logs.yaml", pipelineConfigs: pipelines.Config{ - component.NewIDWithName("logs", "in"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewIDWithName("exampleconnector", "fork")}, // wrapped w/ mutates: true + component.MustNewIDWithName("logs", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, }, - component.NewIDWithName("logs", "type0"): { - Receivers: []component.ID{component.NewIDWithName("exampleconnector", "fork")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewIDWithName("exampleconnector", "merge")}, + component.MustNewIDWithName("logs", "type0"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "merge")}, }, - component.NewIDWithName("logs", "type1"): { - Receivers: []component.ID{component.NewIDWithName("exampleconnector", "fork")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewIDWithName("exampleconnector", "merge")}, + component.MustNewIDWithName("logs", "type1"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, // mutate propagates upstream to connector + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "merge")}, }, - component.NewIDWithName("logs", "out"): { - Receivers: []component.ID{component.NewIDWithName("exampleconnector", "merge")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("logs", "out"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "merge")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 2, @@ -486,20 +508,20 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_conn_translate_from_traces.yaml", pipelineConfigs: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleconnector")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleconnector")}, }, - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("exampleconnector")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("exampleconnector")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("exampleconnector")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("exampleconnector")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 1, @@ -507,20 +529,20 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_conn_translate_from_metrics.yaml", pipelineConfigs: pipelines.Config{ - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleconnector")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleconnector")}, }, - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("exampleconnector")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("exampleconnector")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("exampleconnector")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("exampleconnector")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 1, @@ -528,20 +550,20 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_conn_translate_from_logs.yaml", pipelineConfigs: pipelines.Config{ - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleconnector")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleconnector")}, }, - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("exampleconnector")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("exampleconnector")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("exampleconnector")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("exampleconnector")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 1, @@ -549,35 +571,35 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_conn_matrix.yaml", pipelineConfigs: pipelines.Config{ - component.NewIDWithName("traces", "in"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleconnector")}, // wrapped w/ mutates: true + component.MustNewIDWithName("traces", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, }, - component.NewIDWithName("metrics", "in"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleconnector")}, + component.MustNewIDWithName("metrics", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, }, - component.NewIDWithName("logs", "in"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleconnector")}, // wrapped w/ mutates: true + component.MustNewIDWithName("logs", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, }, - component.NewIDWithName("traces", "out"): { - Receivers: []component.ID{component.NewID("exampleconnector")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("traces", "out"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, // mutate propagates upstream to connector + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewIDWithName("metrics", "out"): { - Receivers: []component.ID{component.NewID("exampleconnector")}, - Processors: []component.ID{component.NewID("exampleprocessor")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("metrics", "out"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, // mutate propagates upstream to connector + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewIDWithName("logs", "out"): { - Receivers: []component.ID{component.NewID("exampleconnector")}, - Processors: []component.ID{component.NewIDWithName("exampleprocessor", "mutate")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("logs", "out"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewIDWithName("exampleprocessor", "mutate")}, // mutate propagates upstream to connector + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 3, @@ -585,45 +607,123 @@ func TestConnectorPipelinesGraph(t *testing.T) { { name: "pipelines_conn_lanes.yaml", pipelineConfigs: pipelines.Config{ - component.NewIDWithName("traces", "in"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Exporters: []component.ID{component.NewID("mockforward")}, + component.MustNewIDWithName("traces", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Exporters: []component.ID{component.MustNewID("mockforward")}, }, - component.NewIDWithName("traces", "out"): { - Receivers: []component.ID{component.NewID("mockforward")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("traces", "out"): { + Receivers: []component.ID{component.MustNewID("mockforward")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewIDWithName("metrics", "in"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Exporters: []component.ID{component.NewID("mockforward")}, + component.MustNewIDWithName("metrics", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Exporters: []component.ID{component.MustNewID("mockforward")}, }, - component.NewIDWithName("metrics", "out"): { - Receivers: []component.ID{component.NewID("mockforward")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("metrics", "out"): { + Receivers: []component.ID{component.MustNewID("mockforward")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, - component.NewIDWithName("logs", "in"): { - Receivers: []component.ID{component.NewID("examplereceiver")}, - Exporters: []component.ID{component.NewID("mockforward")}, + component.MustNewIDWithName("logs", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Exporters: []component.ID{component.MustNewID("mockforward")}, }, - component.NewIDWithName("logs", "out"): { - Receivers: []component.ID{component.NewID("mockforward")}, - Exporters: []component.ID{component.NewID("exampleexporter")}, + component.MustNewIDWithName("logs", "out"): { + Receivers: []component.ID{component.MustNewID("mockforward")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, }, }, expectedPerExporter: 1, }, + { + name: "pipelines_conn_mutate_traces.yaml", + pipelineConfigs: pipelines.Config{ + component.MustNewIDWithName("traces", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + }, + component.MustNewIDWithName("traces", "out0"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, + }, + component.MustNewIDWithName("traces", "middle"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "mutate")}, + }, + component.MustNewIDWithName("traces", "out1"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "mutate")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, + }, + }, + expectedPerExporter: 2, + }, + { + name: "pipelines_conn_mutate_metrics.yaml", + pipelineConfigs: pipelines.Config{ + component.MustNewIDWithName("metrics", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + }, + component.MustNewIDWithName("metrics", "out0"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, + }, + component.MustNewIDWithName("metrics", "middle"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "mutate")}, + }, + component.MustNewIDWithName("metrics", "out1"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "mutate")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, + }, + }, + expectedPerExporter: 2, + }, + { + name: "pipelines_conn_mutate_logs.yaml", + pipelineConfigs: pipelines.Config{ + component.MustNewIDWithName("logs", "in"): { + Receivers: []component.ID{component.MustNewID("examplereceiver")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + }, + component.MustNewIDWithName("logs", "out0"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, + }, + component.MustNewIDWithName("logs", "middle"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "inherit_mutate")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewIDWithName("exampleconnector", "mutate")}, + }, + component.MustNewIDWithName("logs", "out1"): { + Receivers: []component.ID{component.MustNewIDWithName("exampleconnector", "mutate")}, + Processors: []component.ID{component.MustNewID("exampleprocessor")}, + Exporters: []component.ID{component.MustNewID("exampleexporter")}, + }, + }, + expectedPerExporter: 2, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { // Build the pipeline set := Settings{ - Telemetry: componenttest.NewNopTelemetrySettings(), + Telemetry: servicetelemetry.NewNopTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo(), ReceiverBuilder: receiver.NewBuilder( map[component.ID]component.Config{ - component.NewID("examplereceiver"): testcomponents.ExampleReceiverFactory.CreateDefaultConfig(), - component.NewIDWithName("examplereceiver", "1"): testcomponents.ExampleReceiverFactory.CreateDefaultConfig(), + component.MustNewID("examplereceiver"): testcomponents.ExampleReceiverFactory.CreateDefaultConfig(), + component.MustNewIDWithName("examplereceiver", "1"): testcomponents.ExampleReceiverFactory.CreateDefaultConfig(), }, map[component.Type]receiver.Factory{ testcomponents.ExampleReceiverFactory.Type(): testcomponents.ExampleReceiverFactory, @@ -631,8 +731,8 @@ func TestConnectorPipelinesGraph(t *testing.T) { ), ProcessorBuilder: processor.NewBuilder( map[component.ID]component.Config{ - component.NewID("exampleprocessor"): testcomponents.ExampleProcessorFactory.CreateDefaultConfig(), - component.NewIDWithName("exampleprocessor", "mutate"): testcomponents.ExampleProcessorFactory.CreateDefaultConfig(), + component.MustNewID("exampleprocessor"): testcomponents.ExampleProcessorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("exampleprocessor", "mutate"): testcomponents.ExampleProcessorFactory.CreateDefaultConfig(), }, map[component.Type]processor.Factory{ testcomponents.ExampleProcessorFactory.Type(): testcomponents.ExampleProcessorFactory, @@ -640,8 +740,8 @@ func TestConnectorPipelinesGraph(t *testing.T) { ), ExporterBuilder: exporter.NewBuilder( map[component.ID]component.Config{ - component.NewID("exampleexporter"): testcomponents.ExampleExporterFactory.CreateDefaultConfig(), - component.NewIDWithName("exampleexporter", "1"): testcomponents.ExampleExporterFactory.CreateDefaultConfig(), + component.MustNewID("exampleexporter"): testcomponents.ExampleExporterFactory.CreateDefaultConfig(), + component.MustNewIDWithName("exampleexporter", "1"): testcomponents.ExampleExporterFactory.CreateDefaultConfig(), }, map[component.Type]exporter.Factory{ testcomponents.ExampleExporterFactory.Type(): testcomponents.ExampleExporterFactory, @@ -649,10 +749,11 @@ func TestConnectorPipelinesGraph(t *testing.T) { ), ConnectorBuilder: connector.NewBuilder( map[component.ID]component.Config{ - component.NewID("exampleconnector"): testcomponents.ExampleConnectorFactory.CreateDefaultConfig(), - component.NewIDWithName("exampleconnector", "fork"): testcomponents.ExampleConnectorFactory.CreateDefaultConfig(), - component.NewIDWithName("exampleconnector", "merge"): testcomponents.ExampleConnectorFactory.CreateDefaultConfig(), - component.NewID("mockforward"): testcomponents.MockForwardConnectorFactory.CreateDefaultConfig(), + component.MustNewID("exampleconnector"): testcomponents.ExampleConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("exampleconnector", "merge"): testcomponents.ExampleConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("exampleconnector", "mutate"): testcomponents.ExampleConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("exampleconnector", "inherit_mutate"): testcomponents.ExampleConnectorFactory.CreateDefaultConfig(), + component.MustNewID("mockforward"): testcomponents.MockForwardConnectorFactory.CreateDefaultConfig(), }, map[component.Type]connector.Factory{ testcomponents.ExampleConnectorFactory.Type(): testcomponents.ExampleConnectorFactory, @@ -679,6 +780,11 @@ func TestConnectorPipelinesGraph(t *testing.T) { // Determine independently if the capabilities node should report MutateData as true var expectMutatesData bool + for _, expr := range pipelineCfg.Exporters { + if strings.Contains(expr.Name(), "mutate") { + expectMutatesData = true + } + } for _, proc := range pipelineCfg.Processors { if proc.Name() == "mutate" { expectMutatesData = true @@ -746,6 +852,9 @@ func TestConnectorPipelinesGraph(t *testing.T) { if !ok { continue } + if expConn.getConsumer().Capabilities().MutatesData { + continue + } // find all the pipelines of the same type where this connector is a receiver var inheritMutatesData bool for recPipelineID, recPipeline := range pg.pipelines { @@ -840,22 +949,34 @@ func TestConnectorPipelinesGraph(t *testing.T) { for _, e := range allExporters[component.DataTypeTraces] { tracesExporter := e.(*testcomponents.ExampleExporter) assert.Equal(t, test.expectedPerExporter, len(tracesExporter.Traces)) + expected := testdata.GenerateTraces(1) + if len(allExporters[component.DataTypeTraces]) > 1 { + expected.MarkReadOnly() // multiple read-only exporters should get read-only pdata + } for i := 0; i < test.expectedPerExporter; i++ { - assert.EqualValues(t, testdata.GenerateTraces(1), tracesExporter.Traces[0]) + assert.EqualValues(t, expected, tracesExporter.Traces[0]) } } for _, e := range allExporters[component.DataTypeMetrics] { metricsExporter := e.(*testcomponents.ExampleExporter) assert.Equal(t, test.expectedPerExporter, len(metricsExporter.Metrics)) + expected := testdata.GenerateMetrics(1) + if len(allExporters[component.DataTypeMetrics]) > 1 { + expected.MarkReadOnly() // multiple read-only exporters should get read-only pdata + } for i := 0; i < test.expectedPerExporter; i++ { - assert.EqualValues(t, testdata.GenerateMetrics(1), metricsExporter.Metrics[0]) + assert.EqualValues(t, expected, metricsExporter.Metrics[0]) } } for _, e := range allExporters[component.DataTypeLogs] { logsExporter := e.(*testcomponents.ExampleExporter) assert.Equal(t, test.expectedPerExporter, len(logsExporter.Logs)) + expected := testdata.GenerateLogs(1) + if len(allExporters[component.DataTypeLogs]) > 1 { + expected.MarkReadOnly() // multiple read-only exporters should get read-only pdata + } for i := 0; i < test.expectedPerExporter; i++ { - assert.EqualValues(t, testdata.GenerateLogs(1), logsExporter.Logs[0]) + assert.EqualValues(t, expected, logsExporter.Logs[0]) } } }) @@ -863,28 +984,28 @@ func TestConnectorPipelinesGraph(t *testing.T) { } func TestConnectorRouter(t *testing.T) { - rcvrID := component.NewID("examplereceiver") - routeTracesID := component.NewIDWithName("examplerouter", "traces") - routeMetricsID := component.NewIDWithName("examplerouter", "metrics") - routeLogsID := component.NewIDWithName("examplerouter", "logs") - expRightID := component.NewIDWithName("exampleexporter", "right") - expLeftID := component.NewIDWithName("exampleexporter", "left") + rcvrID := component.MustNewID("examplereceiver") + routeTracesID := component.MustNewIDWithName("examplerouter", "traces") + routeMetricsID := component.MustNewIDWithName("examplerouter", "metrics") + routeLogsID := component.MustNewIDWithName("examplerouter", "logs") + expRightID := component.MustNewIDWithName("exampleexporter", "right") + expLeftID := component.MustNewIDWithName("exampleexporter", "left") - tracesInID := component.NewIDWithName("traces", "in") - tracesRightID := component.NewIDWithName("traces", "right") - tracesLeftID := component.NewIDWithName("traces", "left") + tracesInID := component.MustNewIDWithName("traces", "in") + tracesRightID := component.MustNewIDWithName("traces", "right") + tracesLeftID := component.MustNewIDWithName("traces", "left") - metricsInID := component.NewIDWithName("metrics", "in") - metricsRightID := component.NewIDWithName("metrics", "right") - metricsLeftID := component.NewIDWithName("metrics", "left") + metricsInID := component.MustNewIDWithName("metrics", "in") + metricsRightID := component.MustNewIDWithName("metrics", "right") + metricsLeftID := component.MustNewIDWithName("metrics", "left") - logsInID := component.NewIDWithName("logs", "in") - logsRightID := component.NewIDWithName("logs", "right") - logsLeftID := component.NewIDWithName("logs", "left") + logsInID := component.MustNewIDWithName("logs", "in") + logsRightID := component.MustNewIDWithName("logs", "right") + logsLeftID := component.MustNewIDWithName("logs", "left") ctx := context.Background() set := Settings{ - Telemetry: componenttest.NewNopTelemetrySettings(), + Telemetry: servicetelemetry.NewNopTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo(), ReceiverBuilder: receiver.NewBuilder( map[component.ID]component.Config{ @@ -1067,15 +1188,15 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_exporter_logs", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("bf"): badExporterFactory.CreateDefaultConfig(), + component.MustNewID("bf"): badExporterFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("bf")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("bf")}, }, }, expected: "failed to create \"bf\" exporter for data type \"logs\": telemetry type is not supported", @@ -1083,15 +1204,15 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_exporter_metrics", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("bf"): badExporterFactory.CreateDefaultConfig(), + component.MustNewID("bf"): badExporterFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("bf")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("bf")}, }, }, expected: "failed to create \"bf\" exporter for data type \"metrics\": telemetry type is not supported", @@ -1099,15 +1220,15 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_exporter_traces", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("bf"): badExporterFactory.CreateDefaultConfig(), + component.MustNewID("bf"): badExporterFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("bf")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("bf")}, }, }, expected: "failed to create \"bf\" exporter for data type \"traces\": telemetry type is not supported", @@ -1115,19 +1236,19 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_processor_logs", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, processorCfgs: map[component.ID]component.Config{ - component.NewID("bf"): badProcessorFactory.CreateDefaultConfig(), + component.MustNewID("bf"): badProcessorFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "failed to create \"bf\" processor, in pipeline \"logs\": telemetry type is not supported", @@ -1135,19 +1256,19 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_processor_metrics", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, processorCfgs: map[component.ID]component.Config{ - component.NewID("bf"): badProcessorFactory.CreateDefaultConfig(), + component.MustNewID("bf"): badProcessorFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "failed to create \"bf\" processor, in pipeline \"metrics\": telemetry type is not supported", @@ -1155,19 +1276,19 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_processor_traces", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, processorCfgs: map[component.ID]component.Config{ - component.NewID("bf"): badProcessorFactory.CreateDefaultConfig(), + component.MustNewID("bf"): badProcessorFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "failed to create \"bf\" processor, in pipeline \"traces\": telemetry type is not supported", @@ -1175,15 +1296,15 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_receiver_logs", receiverCfgs: map[component.ID]component.Config{ - component.NewID("bf"): badReceiverFactory.CreateDefaultConfig(), + component.MustNewID("bf"): badReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "failed to create \"bf\" receiver for data type \"logs\": telemetry type is not supported", @@ -1191,15 +1312,15 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_receiver_metrics", receiverCfgs: map[component.ID]component.Config{ - component.NewID("bf"): badReceiverFactory.CreateDefaultConfig(), + component.MustNewID("bf"): badReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "failed to create \"bf\" receiver for data type \"metrics\": telemetry type is not supported", @@ -1207,15 +1328,15 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_receiver_traces", receiverCfgs: map[component.ID]component.Config{ - component.NewID("bf"): badReceiverFactory.CreateDefaultConfig(), + component.MustNewID("bf"): badReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "failed to create \"bf\" receiver for data type \"traces\": telemetry type is not supported", @@ -1223,22 +1344,22 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_connector_traces_traces.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewID("bf"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewID("bf"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("traces", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("bf")}, + component.MustNewIDWithName("traces", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("bf")}, }, - component.NewIDWithName("traces", "out"): { - Receivers: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("traces", "out"): { + Receivers: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "connector \"bf\" used as exporter in traces pipeline but not used in any supported receiver pipeline", @@ -1246,22 +1367,22 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_connector_traces_metrics.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewID("bf"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewID("bf"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("traces", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("bf")}, + component.MustNewIDWithName("traces", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("bf")}, }, - component.NewIDWithName("metrics", "out"): { - Receivers: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("metrics", "out"): { + Receivers: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "connector \"bf\" used as exporter in traces pipeline but not used in any supported receiver pipeline", @@ -1269,22 +1390,22 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_connector_traces_logs.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewID("bf"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewID("bf"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("traces", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("bf")}, + component.MustNewIDWithName("traces", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("bf")}, }, - component.NewIDWithName("logs", "out"): { - Receivers: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("logs", "out"): { + Receivers: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "connector \"bf\" used as exporter in traces pipeline but not used in any supported receiver pipeline", @@ -1292,22 +1413,22 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_connector_metrics_traces.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewID("bf"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewID("bf"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("metrics", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("bf")}, + component.MustNewIDWithName("metrics", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("bf")}, }, - component.NewIDWithName("traces", "out"): { - Receivers: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("traces", "out"): { + Receivers: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "connector \"bf\" used as exporter in metrics pipeline but not used in any supported receiver pipeline", @@ -1315,22 +1436,22 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_connector_metrics_metrics.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewID("bf"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewID("bf"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("metrics", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("bf")}, + component.MustNewIDWithName("metrics", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("bf")}, }, - component.NewIDWithName("metrics", "out"): { - Receivers: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("metrics", "out"): { + Receivers: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "connector \"bf\" used as exporter in metrics pipeline but not used in any supported receiver pipeline", @@ -1338,22 +1459,22 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_connector_metrics_logs.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewID("bf"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewID("bf"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("metrics", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("bf")}, + component.MustNewIDWithName("metrics", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("bf")}, }, - component.NewIDWithName("logs", "out"): { - Receivers: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("logs", "out"): { + Receivers: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "connector \"bf\" used as exporter in metrics pipeline but not used in any supported receiver pipeline", @@ -1361,22 +1482,22 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_connector_logs_traces.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewID("bf"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewID("bf"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("logs", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("bf")}, + component.MustNewIDWithName("logs", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("bf")}, }, - component.NewIDWithName("traces", "out"): { - Receivers: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("traces", "out"): { + Receivers: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "connector \"bf\" used as exporter in logs pipeline but not used in any supported receiver pipeline", @@ -1384,22 +1505,22 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_connector_logs_metrics.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewID("bf"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewID("bf"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("logs", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("bf")}, + component.MustNewIDWithName("logs", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("bf")}, }, - component.NewIDWithName("metrics", "out"): { - Receivers: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("metrics", "out"): { + Receivers: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "connector \"bf\" used as exporter in logs pipeline but not used in any supported receiver pipeline", @@ -1407,22 +1528,22 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_supported_connector_logs_logs.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewID("bf"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewID("bf"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("logs", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("bf")}, + component.MustNewIDWithName("logs", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("bf")}, }, - component.NewIDWithName("logs", "out"): { - Receivers: []component.ID{component.NewID("bf")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("logs", "out"): { + Receivers: []component.ID{component.MustNewID("bf")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "connector \"bf\" used as exporter in logs pipeline but not used in any supported receiver pipeline", @@ -1430,18 +1551,18 @@ func TestGraphBuildErrors(t *testing.T) { { name: "orphaned-connector-use-as-exporter", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("metrics", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "conn")}, + component.MustNewIDWithName("metrics", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "conn")}, }, }, expected: `connector "nop/conn" used as exporter in metrics pipeline but not used in any supported receiver pipeline`, @@ -1449,18 +1570,18 @@ func TestGraphBuildErrors(t *testing.T) { { name: "orphaned-connector-use-as-receiver", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("traces", "out"): { - Receivers: []component.ID{component.NewIDWithName("nop", "conn")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("traces", "out"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "conn")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: `connector "nop/conn" used as receiver in traces pipeline but not used in any supported exporter pipeline`, @@ -1468,26 +1589,26 @@ func TestGraphBuildErrors(t *testing.T) { { name: "partially-orphaned-connector-use-as-exporter", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewID("mockforward"): mfConnectorFactory.CreateDefaultConfig(), + component.MustNewID("mockforward"): mfConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("traces", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("mockforward")}, + component.MustNewIDWithName("traces", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("mockforward")}, }, - component.NewIDWithName("traces", "out"): { - Receivers: []component.ID{component.NewID("mockforward")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("traces", "out"): { + Receivers: []component.ID{component.MustNewID("mockforward")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, - component.NewIDWithName("metrics", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("mockforward")}, + component.MustNewIDWithName("metrics", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("mockforward")}, }, }, expected: `connector "mockforward" used as exporter in metrics pipeline but not used in any supported receiver pipeline`, @@ -1495,26 +1616,26 @@ func TestGraphBuildErrors(t *testing.T) { { name: "partially-orphaned-connector-use-as-receiver", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewID("mockforward"): mfConnectorFactory.CreateDefaultConfig(), + component.MustNewID("mockforward"): mfConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("metrics", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("mockforward")}, + component.MustNewIDWithName("metrics", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("mockforward")}, }, - component.NewIDWithName("metrics", "out"): { - Receivers: []component.ID{component.NewID("mockforward")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("metrics", "out"): { + Receivers: []component.ID{component.MustNewID("mockforward")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, - component.NewIDWithName("traces", "out"): { - Receivers: []component.ID{component.NewID("mockforward")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("traces", "out"): { + Receivers: []component.ID{component.MustNewID("mockforward")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: `connector "mockforward" used as receiver in traces pipeline but not used in any supported exporter pipeline`, @@ -1522,22 +1643,22 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_allowed_simple_cycle_traces.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, processorCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopProcessorFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopProcessorFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewIDWithName("nop", "conn")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "conn")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "conn")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "conn")}, }, }, expected: `cycle detected: ` + @@ -1548,22 +1669,22 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_allowed_simple_cycle_metrics.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, processorCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopProcessorFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopProcessorFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("metrics"): { - Receivers: []component.ID{component.NewIDWithName("nop", "conn")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "conn")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "conn")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "conn")}, }, }, expected: `cycle detected: ` + @@ -1574,22 +1695,22 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_allowed_simple_cycle_logs.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, processorCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopProcessorFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopProcessorFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("logs"): { - Receivers: []component.ID{component.NewIDWithName("nop", "conn")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "conn")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "conn")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "conn")}, }, }, expected: `cycle detected: ` + @@ -1600,39 +1721,39 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_allowed_deep_cycle_traces.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, processorCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopProcessorFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopProcessorFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), - component.NewIDWithName("nop", "conn1"): nopConnectorFactory.CreateDefaultConfig(), - component.NewIDWithName("nop", "conn2"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "conn1"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "conn2"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("traces", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "conn")}, + component.MustNewIDWithName("traces", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "conn")}, }, - component.NewIDWithName("traces", "1"): { - Receivers: []component.ID{component.NewIDWithName("nop", "conn")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "conn1")}, + component.MustNewIDWithName("traces", "1"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "conn")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "conn1")}, }, - component.NewIDWithName("traces", "2"): { - Receivers: []component.ID{component.NewIDWithName("nop", "conn1")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "conn2"), component.NewIDWithName("nop", "conn")}, + component.MustNewIDWithName("traces", "2"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "conn1")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "conn2"), component.MustNewIDWithName("nop", "conn")}, }, - component.NewIDWithName("traces", "out"): { - Receivers: []component.ID{component.NewIDWithName("nop", "conn2")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("traces", "out"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "conn2")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: `cycle detected: ` + @@ -1645,39 +1766,39 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_allowed_deep_cycle_metrics.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, processorCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopProcessorFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopProcessorFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), - component.NewIDWithName("nop", "conn1"): nopConnectorFactory.CreateDefaultConfig(), - component.NewIDWithName("nop", "conn2"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "conn1"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "conn2"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("metrics", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "conn")}, + component.MustNewIDWithName("metrics", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "conn")}, }, - component.NewIDWithName("metrics", "1"): { - Receivers: []component.ID{component.NewIDWithName("nop", "conn")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "conn1")}, + component.MustNewIDWithName("metrics", "1"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "conn")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "conn1")}, }, - component.NewIDWithName("metrics", "2"): { - Receivers: []component.ID{component.NewIDWithName("nop", "conn1")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "conn2"), component.NewIDWithName("nop", "conn")}, + component.MustNewIDWithName("metrics", "2"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "conn1")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "conn2"), component.MustNewIDWithName("nop", "conn")}, }, - component.NewIDWithName("metrics", "out"): { - Receivers: []component.ID{component.NewIDWithName("nop", "conn2")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("metrics", "out"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "conn2")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: `cycle detected: ` + @@ -1690,39 +1811,39 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_allowed_deep_cycle_logs.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, processorCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopProcessorFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopProcessorFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), - component.NewIDWithName("nop", "conn1"): nopConnectorFactory.CreateDefaultConfig(), - component.NewIDWithName("nop", "conn2"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "conn"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "conn1"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "conn2"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("logs", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "conn")}, + component.MustNewIDWithName("logs", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "conn")}, }, - component.NewIDWithName("logs", "1"): { - Receivers: []component.ID{component.NewIDWithName("nop", "conn")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "conn1")}, + component.MustNewIDWithName("logs", "1"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "conn")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "conn1")}, }, - component.NewIDWithName("logs", "2"): { - Receivers: []component.ID{component.NewIDWithName("nop", "conn1")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "conn2"), component.NewIDWithName("nop", "conn")}, + component.MustNewIDWithName("logs", "2"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "conn1")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "conn2"), component.MustNewIDWithName("nop", "conn")}, }, - component.NewIDWithName("logs", "out"): { - Receivers: []component.ID{component.NewIDWithName("nop", "conn2")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("logs", "out"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "conn2")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: `cycle detected: ` + @@ -1735,55 +1856,55 @@ func TestGraphBuildErrors(t *testing.T) { { name: "not_allowed_deep_cycle_multi_signal.yaml", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, processorCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopProcessorFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopProcessorFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopExporterFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopExporterFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewIDWithName("nop", "fork"): nopConnectorFactory.CreateDefaultConfig(), - component.NewIDWithName("nop", "count"): nopConnectorFactory.CreateDefaultConfig(), - component.NewIDWithName("nop", "forkagain"): nopConnectorFactory.CreateDefaultConfig(), - component.NewIDWithName("nop", "rawlog"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "fork"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "count"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "forkagain"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewIDWithName("nop", "rawlog"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("traces", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "fork")}, - }, - component.NewIDWithName("traces", "copy1"): { - Receivers: []component.ID{component.NewIDWithName("nop", "fork")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "count")}, - }, - component.NewIDWithName("traces", "copy2"): { - Receivers: []component.ID{component.NewIDWithName("nop", "fork")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "forkagain")}, - }, - component.NewIDWithName("traces", "copy2a"): { - Receivers: []component.ID{component.NewIDWithName("nop", "forkagain")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "count")}, - }, - component.NewIDWithName("traces", "copy2b"): { - Receivers: []component.ID{component.NewIDWithName("nop", "forkagain")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "rawlog")}, - }, - component.NewIDWithName("metrics", "count"): { - Receivers: []component.ID{component.NewIDWithName("nop", "count")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, - }, - component.NewIDWithName("logs", "raw"): { - Receivers: []component.ID{component.NewIDWithName("nop", "rawlog")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewIDWithName("nop", "fork")}, // cannot loop back to "nop/fork" + component.MustNewIDWithName("traces", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "fork")}, + }, + component.MustNewIDWithName("traces", "copy1"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "fork")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "count")}, + }, + component.MustNewIDWithName("traces", "copy2"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "fork")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "forkagain")}, + }, + component.MustNewIDWithName("traces", "copy2a"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "forkagain")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "count")}, + }, + component.MustNewIDWithName("traces", "copy2b"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "forkagain")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "rawlog")}, + }, + component.MustNewIDWithName("metrics", "count"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "count")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop")}, + }, + component.MustNewIDWithName("logs", "raw"): { + Receivers: []component.ID{component.MustNewIDWithName("nop", "rawlog")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewIDWithName("nop", "fork")}, // cannot loop back to "nop/fork" }, }, expected: `cycle detected: ` + @@ -1798,15 +1919,15 @@ func TestGraphBuildErrors(t *testing.T) { { name: "unknown_exporter_config", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop"), component.NewIDWithName("nop", "1")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop"), component.MustNewIDWithName("nop", "1")}, }, }, expected: "failed to create \"nop/1\" exporter for data type \"traces\": exporter \"nop/1\" is not configured", @@ -1814,15 +1935,15 @@ func TestGraphBuildErrors(t *testing.T) { { name: "unknown_exporter_factory", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("unknown"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("unknown"): nopReceiverFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("unknown")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("unknown")}, }, }, expected: "failed to create \"unknown\" exporter for data type \"traces\": exporter factory not available for: \"unknown\"", @@ -1830,19 +1951,19 @@ func TestGraphBuildErrors(t *testing.T) { { name: "unknown_processor_config", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, processorCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopProcessorFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopProcessorFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop"), component.NewIDWithName("nop", "1")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("nop"), component.MustNewIDWithName("nop", "1")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "failed to create \"nop/1\" processor, in pipeline \"metrics\": processor \"nop/1\" is not configured", @@ -1850,19 +1971,19 @@ func TestGraphBuildErrors(t *testing.T) { { name: "unknown_processor_factory", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, processorCfgs: map[component.ID]component.Config{ - component.NewID("unknown"): nopProcessorFactory.CreateDefaultConfig(), + component.MustNewID("unknown"): nopProcessorFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("unknown")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("unknown")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "failed to create \"unknown\" processor, in pipeline \"metrics\": processor factory not available for: \"unknown\"", @@ -1870,15 +1991,15 @@ func TestGraphBuildErrors(t *testing.T) { { name: "unknown_receiver_config", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("nop"), component.NewIDWithName("nop", "1")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("nop"), component.MustNewIDWithName("nop", "1")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "failed to create \"nop/1\" receiver for data type \"logs\": receiver \"nop/1\" is not configured", @@ -1886,15 +2007,15 @@ func TestGraphBuildErrors(t *testing.T) { { name: "unknown_receiver_factory", receiverCfgs: map[component.ID]component.Config{ - component.NewID("unknown"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("unknown"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("unknown")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.MustNewID("unknown")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "failed to create \"unknown\" receiver for data type \"logs\": receiver factory not available for: \"unknown\"", @@ -1902,22 +2023,22 @@ func TestGraphBuildErrors(t *testing.T) { { name: "unknown_connector_factory", receiverCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, exporterCfgs: map[component.ID]component.Config{ - component.NewID("nop"): nopReceiverFactory.CreateDefaultConfig(), + component.MustNewID("nop"): nopReceiverFactory.CreateDefaultConfig(), }, connectorCfgs: map[component.ID]component.Config{ - component.NewID("unknown"): nopConnectorFactory.CreateDefaultConfig(), + component.MustNewID("unknown"): nopConnectorFactory.CreateDefaultConfig(), }, pipelineCfgs: pipelines.Config{ - component.NewIDWithName("traces", "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("unknown")}, + component.MustNewIDWithName("traces", "in"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("unknown")}, }, - component.NewIDWithName("traces", "out"): { - Receivers: []component.ID{component.NewID("unknown")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewIDWithName("traces", "out"): { + Receivers: []component.ID{component.MustNewID("unknown")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, }, expected: "connector factory not available for: \"unknown\"", @@ -1928,7 +2049,7 @@ func TestGraphBuildErrors(t *testing.T) { t.Run(test.name, func(t *testing.T) { set := Settings{ BuildInfo: component.NewDefaultBuildInfo(), - Telemetry: componenttest.NewNopTelemetrySettings(), + Telemetry: servicetelemetry.NewNopTelemetrySettings(), ReceiverBuilder: receiver.NewBuilder( test.receiverCfgs, map[component.Type]receiver.Factory{ @@ -1975,7 +2096,7 @@ func TestGraphFailToStartAndShutdown(t *testing.T) { nopConnectorFactory := connectortest.NewNopFactory() set := Settings{ - Telemetry: componenttest.NewNopTelemetrySettings(), + Telemetry: servicetelemetry.NewNopTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo(), ReceiverBuilder: receiver.NewBuilder( map[component.ID]component.Config{ @@ -2017,12 +2138,12 @@ func TestGraphFailToStartAndShutdown(t *testing.T) { dataTypes := []component.DataType{component.DataTypeTraces, component.DataTypeMetrics, component.DataTypeLogs} for _, dt := range dataTypes { - t.Run(string(dt)+"/receiver", func(t *testing.T) { + t.Run(dt.String()+"/receiver", func(t *testing.T) { set.PipelineConfigs = pipelines.Config{ component.NewID(dt): { - Receivers: []component.ID{component.NewID("nop"), component.NewID("err")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, + Receivers: []component.ID{component.MustNewID("nop"), component.MustNewID("err")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, } pipelines, err := Build(context.Background(), set) @@ -2031,12 +2152,12 @@ func TestGraphFailToStartAndShutdown(t *testing.T) { assert.Error(t, pipelines.ShutdownAll(context.Background())) }) - t.Run(string(dt)+"/processor", func(t *testing.T) { + t.Run(dt.String()+"/processor", func(t *testing.T) { set.PipelineConfigs = pipelines.Config{ component.NewID(dt): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop"), component.NewID("err")}, - Exporters: []component.ID{component.NewID("nop")}, + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("nop"), component.MustNewID("err")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, } pipelines, err := Build(context.Background(), set) @@ -2045,12 +2166,12 @@ func TestGraphFailToStartAndShutdown(t *testing.T) { assert.Error(t, pipelines.ShutdownAll(context.Background())) }) - t.Run(string(dt)+"/exporter", func(t *testing.T) { + t.Run(dt.String()+"/exporter", func(t *testing.T) { set.PipelineConfigs = pipelines.Config{ component.NewID(dt): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop"), component.NewID("err")}, + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop"), component.MustNewID("err")}, }, } pipelines, err := Build(context.Background(), set) @@ -2060,17 +2181,17 @@ func TestGraphFailToStartAndShutdown(t *testing.T) { }) for _, dt2 := range dataTypes { - t.Run(string(dt)+"/"+string(dt2)+"/connector", func(t *testing.T) { + t.Run(dt.String()+"/"+dt2.String()+"/connector", func(t *testing.T) { set.PipelineConfigs = pipelines.Config{ component.NewIDWithName(dt, "in"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop"), component.NewIDWithName("err", "conn")}, + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop"), component.MustNewIDWithName("err", "conn")}, }, component.NewIDWithName(dt2, "out"): { - Receivers: []component.ID{component.NewID("nop"), component.NewIDWithName("err", "conn")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, + Receivers: []component.ID{component.MustNewID("nop"), component.MustNewIDWithName("err", "conn")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, } pipelines, err := Build(context.Background(), set) @@ -2082,6 +2203,160 @@ func TestGraphFailToStartAndShutdown(t *testing.T) { } } +func TestStatusReportedOnStartupShutdown(t *testing.T) { + + rNoErr := &testNode{id: component.MustNewIDWithName("r_no_err", "1")} + rStErr := &testNode{id: component.MustNewIDWithName("r_st_err", "1"), startErr: assert.AnError} + rSdErr := &testNode{id: component.MustNewIDWithName("r_sd_err", "1"), shutdownErr: assert.AnError} + + eNoErr := &testNode{id: component.MustNewIDWithName("e_no_err", "1")} + eStErr := &testNode{id: component.MustNewIDWithName("e_st_err", "1"), startErr: assert.AnError} + eSdErr := &testNode{id: component.MustNewIDWithName("e_sd_err", "1"), shutdownErr: assert.AnError} + + instanceIDs := map[*testNode]*component.InstanceID{ + rNoErr: {ID: rNoErr.id}, + rStErr: {ID: rStErr.id}, + rSdErr: {ID: rSdErr.id}, + eNoErr: {ID: eNoErr.id}, + eStErr: {ID: eStErr.id}, + eSdErr: {ID: eSdErr.id}, + } + + // compare two maps of status events ignoring timestamp + assertEqualStatuses := func(t *testing.T, evMap1, evMap2 map[*component.InstanceID][]*component.StatusEvent) { + assert.Equal(t, len(evMap1), len(evMap2)) + for id, evts1 := range evMap1 { + evts2 := evMap2[id] + assert.Equal(t, len(evts1), len(evts2)) + for i := 0; i < len(evts1); i++ { + ev1 := evts1[i] + ev2 := evts2[i] + assert.Equal(t, ev1.Status(), ev2.Status()) + assert.Equal(t, ev1.Err(), ev2.Err()) + } + } + + } + + for _, tc := range []struct { + name string + edge [2]*testNode + expectedStatuses map[*component.InstanceID][]*component.StatusEvent + startupErr error + shutdownErr error + }{ + { + name: "successful startup/shutdown", + edge: [2]*testNode{rNoErr, eNoErr}, + expectedStatuses: map[*component.InstanceID][]*component.StatusEvent{ + instanceIDs[rNoErr]: { + component.NewStatusEvent(component.StatusStarting), + component.NewStatusEvent(component.StatusOK), + component.NewStatusEvent(component.StatusStopping), + component.NewStatusEvent(component.StatusStopped), + }, + instanceIDs[eNoErr]: { + component.NewStatusEvent(component.StatusStarting), + component.NewStatusEvent(component.StatusOK), + component.NewStatusEvent(component.StatusStopping), + component.NewStatusEvent(component.StatusStopped), + }, + }, + }, + { + name: "early startup error", + edge: [2]*testNode{rNoErr, eStErr}, + expectedStatuses: map[*component.InstanceID][]*component.StatusEvent{ + instanceIDs[eStErr]: { + component.NewStatusEvent(component.StatusStarting), + component.NewPermanentErrorEvent(assert.AnError), + }, + }, + startupErr: assert.AnError, + }, + { + name: "late startup error", + edge: [2]*testNode{rStErr, eNoErr}, + expectedStatuses: map[*component.InstanceID][]*component.StatusEvent{ + instanceIDs[rStErr]: { + component.NewStatusEvent(component.StatusStarting), + component.NewPermanentErrorEvent(assert.AnError), + }, + instanceIDs[eNoErr]: { + component.NewStatusEvent(component.StatusStarting), + component.NewStatusEvent(component.StatusOK), + component.NewStatusEvent(component.StatusStopping), + component.NewStatusEvent(component.StatusStopped), + }, + }, + startupErr: assert.AnError, + }, + { + name: "early shutdown error", + edge: [2]*testNode{rSdErr, eNoErr}, + expectedStatuses: map[*component.InstanceID][]*component.StatusEvent{ + instanceIDs[rSdErr]: { + component.NewStatusEvent(component.StatusStarting), + component.NewStatusEvent(component.StatusOK), + component.NewStatusEvent(component.StatusStopping), + component.NewPermanentErrorEvent(assert.AnError), + }, + instanceIDs[eNoErr]: { + component.NewStatusEvent(component.StatusStarting), + component.NewStatusEvent(component.StatusOK), + component.NewStatusEvent(component.StatusStopping), + component.NewStatusEvent(component.StatusStopped), + }, + }, + shutdownErr: assert.AnError, + }, + { + name: "late shutdown error", + edge: [2]*testNode{rNoErr, eSdErr}, + expectedStatuses: map[*component.InstanceID][]*component.StatusEvent{ + instanceIDs[rNoErr]: { + component.NewStatusEvent(component.StatusStarting), + component.NewStatusEvent(component.StatusOK), + component.NewStatusEvent(component.StatusStopping), + component.NewStatusEvent(component.StatusStopped), + }, + instanceIDs[eSdErr]: { + component.NewStatusEvent(component.StatusStarting), + component.NewStatusEvent(component.StatusOK), + component.NewStatusEvent(component.StatusStopping), + component.NewPermanentErrorEvent(assert.AnError), + }, + }, + shutdownErr: assert.AnError, + }, + } { + t.Run(tc.name, func(t *testing.T) { + pg := &Graph{componentGraph: simple.NewDirectedGraph()} + pg.telemetry = servicetelemetry.NewNopTelemetrySettings() + + actualStatuses := make(map[*component.InstanceID][]*component.StatusEvent) + rep := status.NewReporter(func(id *component.InstanceID, ev *component.StatusEvent) { + actualStatuses[id] = append(actualStatuses[id], ev) + }, func(error) { + }) + + pg.telemetry.Status = rep + rep.Ready() + + e0, e1 := tc.edge[0], tc.edge[1] + pg.instanceIDs = map[int64]*component.InstanceID{ + e0.ID(): instanceIDs[e0], + e1.ID(): instanceIDs[e1], + } + pg.componentGraph.SetEdge(simple.Edge{F: e0, T: e1}) + + assert.Equal(t, tc.startupErr, pg.StartAll(context.Background(), componenttest.NewNopHost())) + assert.Equal(t, tc.shutdownErr, pg.ShutdownAll(context.Background())) + assertEqualStatuses(t, tc.expectedStatuses, actualStatuses) + }) + } +} + func (g *Graph) getReceivers() map[component.DataType]map[component.ID]component.Component { receiversMap := make(map[component.DataType]map[component.ID]component.Component) receiversMap[component.DataTypeTraces] = make(map[component.ID]component.Component) @@ -2115,9 +2390,10 @@ func (g *Graph) getReceivers() map[component.DataType]map[component.ID]component // - E instances of the connector as a receiver. // - R instances of the connector as an exporter. func expectedInstances(m pipelines.Config, pID component.ID) (int, int) { + exConnectorType := component.MustNewType("exampleconnector") var r, e int for _, rID := range m[pID].Receivers { - if rID.Type() != "exampleconnector" { + if rID.Type() != exConnectorType { r++ continue } @@ -2134,7 +2410,7 @@ func expectedInstances(m pipelines.Config, pID component.ID) (int, int) { r += len(typeMap) } for _, eID := range m[pID].Exporters { - if eID.Type() != "exampleconnector" { + if eID.Type() != exConnectorType { e++ continue } @@ -2154,31 +2430,31 @@ func expectedInstances(m pipelines.Config, pID component.ID) (int, int) { } func newBadReceiverFactory() receiver.Factory { - return receiver.NewFactory("bf", func() component.Config { + return receiver.NewFactory(component.MustNewType("bf"), func() component.Config { return &struct{}{} }) } func newBadProcessorFactory() processor.Factory { - return processor.NewFactory("bf", func() component.Config { + return processor.NewFactory(component.MustNewType("bf"), func() component.Config { return &struct{}{} }) } func newBadExporterFactory() exporter.Factory { - return exporter.NewFactory("bf", func() component.Config { + return exporter.NewFactory(component.MustNewType("bf"), func() component.Config { return &struct{}{} }) } func newBadConnectorFactory() connector.Factory { - return connector.NewFactory("bf", func() component.Config { + return connector.NewFactory(component.MustNewType("bf"), func() component.Config { return &struct{}{} }) } func newErrReceiverFactory() receiver.Factory { - return receiver.NewFactory("err", + return receiver.NewFactory(component.MustNewType("err"), func() component.Config { return &struct{}{} }, receiver.WithTraces(func(context.Context, receiver.CreateSettings, component.Config, consumer.Traces) (receiver.Traces, error) { return &errComponent{}, nil @@ -2193,7 +2469,7 @@ func newErrReceiverFactory() receiver.Factory { } func newErrProcessorFactory() processor.Factory { - return processor.NewFactory("err", + return processor.NewFactory(component.MustNewType("err"), func() component.Config { return &struct{}{} }, processor.WithTraces(func(context.Context, processor.CreateSettings, component.Config, consumer.Traces) (processor.Traces, error) { return &errComponent{}, nil @@ -2208,7 +2484,7 @@ func newErrProcessorFactory() processor.Factory { } func newErrExporterFactory() exporter.Factory { - return exporter.NewFactory("err", + return exporter.NewFactory(component.MustNewType("err"), func() component.Config { return &struct{}{} }, exporter.WithTraces(func(context.Context, exporter.CreateSettings, component.Config) (exporter.Traces, error) { return &errComponent{}, nil @@ -2223,7 +2499,7 @@ func newErrExporterFactory() exporter.Factory { } func newErrConnectorFactory() connector.Factory { - return connector.NewFactory("err", func() component.Config { + return connector.NewFactory(component.MustNewType("err"), func() component.Config { return &struct{}{} }, connector.WithTracesToTraces(func(context.Context, connector.CreateSettings, component.Config, consumer.Traces) (connector.Traces, error) { diff --git a/service/internal/graph/nodes.go b/service/internal/graph/nodes.go index 7f7fda70f85..13726d1c760 100644 --- a/service/internal/graph/nodes.go +++ b/service/internal/graph/nodes.go @@ -61,7 +61,7 @@ type receiverNode struct { func newReceiverNode(pipelineType component.DataType, recvID component.ID) *receiverNode { return &receiverNode{ - nodeID: newNodeID(receiverSeed, string(pipelineType), recvID.String()), + nodeID: newNodeID(receiverSeed, pipelineType.String(), recvID.String()), componentID: recvID, pipelineType: pipelineType, } @@ -165,7 +165,7 @@ type exporterNode struct { func newExporterNode(pipelineType component.DataType, exprID component.ID) *exporterNode { return &exporterNode{ - nodeID: newNodeID(exporterSeed, string(pipelineType), exprID.String()), + nodeID: newNodeID(exporterSeed, pipelineType.String(), exprID.String()), componentID: exprID, pipelineType: pipelineType, } @@ -215,7 +215,7 @@ type connectorNode struct { func newConnectorNode(exprPipelineType, rcvrPipelineType component.DataType, connID component.ID) *connectorNode { return &connectorNode{ - nodeID: newNodeID(connectorSeed, connID.String(), string(exprPipelineType), string(rcvrPipelineType)), + nodeID: newNodeID(connectorSeed, connID.String(), exprPipelineType.String(), rcvrPipelineType.String()), componentID: connID, exprPipelineType: exprPipelineType, rcvrPipelineType: rcvrPipelineType, @@ -244,7 +244,7 @@ func (n *connectorNode) buildComponent( consumers[next.(*capabilitiesNode).pipelineID] = next.(consumer.Traces) capability.MutatesData = capability.MutatesData || next.Capabilities().MutatesData } - next := fanoutconsumer.NewTracesRouter(consumers) + next := connector.NewTracesRouter(consumers) switch n.exprPipelineType { case component.DataTypeTraces: @@ -255,6 +255,9 @@ func (n *connectorNode) buildComponent( n.Component = conn // When connecting pipelines of the same data type, the connector must // inherit the capabilities of pipelines in which it is acting as a receiver. + // Since the incoming and outgoing data types are the same, we must also consider + // that the connector itself may MutatesData. + capability.MutatesData = capability.MutatesData || conn.Capabilities().MutatesData n.baseConsumer = capabilityconsumer.NewTraces(conn, capability) case component.DataTypeMetrics: conn, err := builder.CreateMetricsToTraces(ctx, set, next) @@ -277,7 +280,7 @@ func (n *connectorNode) buildComponent( consumers[next.(*capabilitiesNode).pipelineID] = next.(consumer.Metrics) capability.MutatesData = capability.MutatesData || next.Capabilities().MutatesData } - next := fanoutconsumer.NewMetricsRouter(consumers) + next := connector.NewMetricsRouter(consumers) switch n.exprPipelineType { case component.DataTypeTraces: @@ -294,6 +297,9 @@ func (n *connectorNode) buildComponent( n.Component = conn // When connecting pipelines of the same data type, the connector must // inherit the capabilities of pipelines in which it is acting as a receiver. + // Since the incoming and outgoing data types are the same, we must also consider + // that the connector itself may MutatesData. + capability.MutatesData = capability.MutatesData || conn.Capabilities().MutatesData n.baseConsumer = capabilityconsumer.NewMetrics(conn, capability) case component.DataTypeLogs: conn, err := builder.CreateLogsToMetrics(ctx, set, next) @@ -309,7 +315,7 @@ func (n *connectorNode) buildComponent( consumers[next.(*capabilitiesNode).pipelineID] = next.(consumer.Logs) capability.MutatesData = capability.MutatesData || next.Capabilities().MutatesData } - next := fanoutconsumer.NewLogsRouter(consumers) + next := connector.NewLogsRouter(consumers) switch n.exprPipelineType { case component.DataTypeTraces: @@ -332,6 +338,9 @@ func (n *connectorNode) buildComponent( n.Component = conn // When connecting pipelines of the same data type, the connector must // inherit the capabilities of pipelines in which it is acting as a receiver. + // Since the incoming and outgoing data types are the same, we must also consider + // that the connector itself may MutatesData. + capability.MutatesData = capability.MutatesData || conn.Capabilities().MutatesData n.baseConsumer = capabilityconsumer.NewLogs(conn, capability) } } diff --git a/service/internal/graph/package_test.go b/service/internal/graph/package_test.go new file mode 100644 index 00000000000..9e6a4a59736 --- /dev/null +++ b/service/internal/graph/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package graph + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/service/internal/graph/zpages.go b/service/internal/graph/zpages.go index 0c7c0829eed..0f2793974e9 100644 --- a/service/internal/graph/zpages.go +++ b/service/internal/graph/zpages.go @@ -55,7 +55,7 @@ func (g *Graph) HandleZPages(w http.ResponseWriter, r *http.Request) { sumData.Rows = append(sumData.Rows, zpages.SummaryPipelinesTableRowData{ FullName: c.String(), - InputType: string(c.Type()), + InputType: c.Type().String(), MutatesData: p.capabilitiesNode.getConsumer().Capabilities().MutatesData, Receivers: recvIDs, Processors: procIDs, diff --git a/service/internal/proctelemetry/config.go b/service/internal/proctelemetry/config.go index 4590b02d481..9d315b48cdb 100644 --- a/service/internal/proctelemetry/config.go +++ b/service/internal/proctelemetry/config.go @@ -16,6 +16,7 @@ import ( "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/bridge/opencensus" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" @@ -32,7 +33,6 @@ import ( "go.opentelemetry.io/collector/processor/processorhelper" semconv "go.opentelemetry.io/collector/semconv/v1.18.0" - "go.opentelemetry.io/collector/service/telemetry" ) const ( @@ -66,12 +66,14 @@ var ( errNoValidSpanExporter = errors.New("no valid span exporter") ) -func InitMetricReader(ctx context.Context, reader telemetry.MetricReader, asyncErrorChannel chan error) (sdkmetric.Reader, *http.Server, error) { +func InitMetricReader(ctx context.Context, reader config.MetricReader, asyncErrorChannel chan error) (sdkmetric.Reader, *http.Server, error) { if reader.Pull != nil { return initPullExporter(reader.Pull.Exporter, asyncErrorChannel) } if reader.Periodic != nil { - opts := []sdkmetric.PeriodicReaderOption{} + opts := []sdkmetric.PeriodicReaderOption{ + sdkmetric.WithProducer(opencensus.NewMetricProducer()), + } if reader.Periodic.Interval != nil { opts = append(opts, sdkmetric.WithInterval(time.Duration(*reader.Periodic.Interval)*time.Millisecond)) } @@ -84,7 +86,7 @@ func InitMetricReader(ctx context.Context, reader telemetry.MetricReader, asyncE return nil, nil, fmt.Errorf("unsupported metric reader type %v", reader) } -func InitSpanProcessor(ctx context.Context, processor telemetry.SpanProcessor) (sdktrace.SpanProcessor, error) { +func InitSpanProcessor(ctx context.Context, processor config.SpanProcessor) (sdktrace.SpanProcessor, error) { if processor.Batch != nil { if processor.Batch.Exporter.Console != nil { exp, err := stdouttrace.New( @@ -95,16 +97,16 @@ func InitSpanProcessor(ctx context.Context, processor telemetry.SpanProcessor) ( } return initBatchSpanProcessor(processor.Batch, exp) } - if processor.Batch.Exporter.Otlp != nil { + if processor.Batch.Exporter.OTLP != nil { var err error var exp sdktrace.SpanExporter - switch processor.Batch.Exporter.Otlp.Protocol { + switch processor.Batch.Exporter.OTLP.Protocol { case protocolProtobufHTTP: - exp, err = initOTLPHTTPSpanExporter(ctx, processor.Batch.Exporter.Otlp) + exp, err = initOTLPHTTPSpanExporter(ctx, processor.Batch.Exporter.OTLP) case protocolProtobufGRPC: - exp, err = initOTLPgRPCSpanExporter(ctx, processor.Batch.Exporter.Otlp) + exp, err = initOTLPgRPCSpanExporter(ctx, processor.Batch.Exporter.OTLP) default: - return nil, fmt.Errorf("unsupported protocol %q", processor.Batch.Exporter.Otlp.Protocol) + return nil, fmt.Errorf("unsupported protocol %q", processor.Batch.Exporter.OTLP.Protocol) } if err != nil { return nil, err @@ -195,7 +197,7 @@ func cardinalityFilter(kvs ...attribute.KeyValue) attribute.Filter { } } -func initPrometheusExporter(prometheusConfig *telemetry.Prometheus, asyncErrorChannel chan error) (sdkmetric.Reader, *http.Server, error) { +func initPrometheusExporter(prometheusConfig *config.Prometheus, asyncErrorChannel chan error) (sdkmetric.Reader, *http.Server, error) { promRegistry := prometheus.NewRegistry() if prometheusConfig.Host == nil { return nil, nil, fmt.Errorf("host must be specified") @@ -203,14 +205,18 @@ func initPrometheusExporter(prometheusConfig *telemetry.Prometheus, asyncErrorCh if prometheusConfig.Port == nil { return nil, nil, fmt.Errorf("port must be specified") } - wrappedRegisterer := prometheus.WrapRegistererWithPrefix("otelcol_", promRegistry) exporter, err := otelprom.New( - otelprom.WithRegisterer(wrappedRegisterer), + 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(), - otelprom.WithProducer(opencensus.NewMetricProducer())) + otelprom.WithProducer(opencensus.NewMetricProducer()), + // This allows us to produce metrics that are backwards compatible w/ opencensus + otelprom.WithoutCounterSuffixes(), + otelprom.WithNamespace("otelcol"), + otelprom.WithResourceAsConstantLabels(attribute.NewDenyKeysFilter()), + ) if err != nil { return nil, nil, fmt.Errorf("error creating otel prometheus exporter: %w", err) } @@ -218,14 +224,14 @@ func initPrometheusExporter(prometheusConfig *telemetry.Prometheus, asyncErrorCh return exporter, InitPrometheusServer(promRegistry, fmt.Sprintf("%s:%d", *prometheusConfig.Host, *prometheusConfig.Port), asyncErrorChannel), nil } -func initPullExporter(exporter telemetry.MetricExporter, asyncErrorChannel chan error) (sdkmetric.Reader, *http.Server, error) { +func initPullExporter(exporter config.MetricExporter, asyncErrorChannel chan error) (sdkmetric.Reader, *http.Server, error) { if exporter.Prometheus != nil { return initPrometheusExporter(exporter.Prometheus, asyncErrorChannel) } return nil, nil, errNoValidMetricExporter } -func initPeriodicExporter(ctx context.Context, exporter telemetry.MetricExporter, opts ...sdkmetric.PeriodicReaderOption) (sdkmetric.Reader, *http.Server, error) { +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("", " ") @@ -238,16 +244,16 @@ func initPeriodicExporter(ctx context.Context, exporter telemetry.MetricExporter } return sdkmetric.NewPeriodicReader(exp, opts...), nil, nil } - if exporter.Otlp != nil { + if exporter.OTLP != nil { var err error var exp sdkmetric.Exporter - switch exporter.Otlp.Protocol { + switch exporter.OTLP.Protocol { case protocolProtobufHTTP: - exp, err = initOTLPHTTPExporter(ctx, exporter.Otlp) + exp, err = initOTLPHTTPExporter(ctx, exporter.OTLP) case protocolProtobufGRPC: - exp, err = initOTLPgRPCExporter(ctx, exporter.Otlp) + exp, err = initOTLPgRPCExporter(ctx, exporter.OTLP) default: - return nil, nil, fmt.Errorf("unsupported protocol %s", exporter.Otlp.Protocol) + return nil, nil, fmt.Errorf("unsupported protocol %s", exporter.OTLP.Protocol) } if err != nil { return nil, nil, err @@ -264,7 +270,7 @@ func normalizeEndpoint(endpoint string) string { return endpoint } -func initOTLPgRPCExporter(ctx context.Context, otlpConfig *telemetry.OtlpMetric) (sdkmetric.Exporter, error) { +func initOTLPgRPCExporter(ctx context.Context, otlpConfig *config.OTLPMetric) (sdkmetric.Exporter, error) { opts := []otlpmetricgrpc.Option{} if len(otlpConfig.Endpoint) > 0 { @@ -298,7 +304,7 @@ func initOTLPgRPCExporter(ctx context.Context, otlpConfig *telemetry.OtlpMetric) return otlpmetricgrpc.New(ctx, opts...) } -func initOTLPHTTPExporter(ctx context.Context, otlpConfig *telemetry.OtlpMetric) (sdkmetric.Exporter, error) { +func initOTLPHTTPExporter(ctx context.Context, otlpConfig *config.OTLPMetric) (sdkmetric.Exporter, error) { opts := []otlpmetrichttp.Option{} if len(otlpConfig.Endpoint) > 0 { @@ -335,7 +341,7 @@ func initOTLPHTTPExporter(ctx context.Context, otlpConfig *telemetry.OtlpMetric) return otlpmetrichttp.New(ctx, opts...) } -func initOTLPgRPCSpanExporter(ctx context.Context, otlpConfig *telemetry.Otlp) (sdktrace.SpanExporter, error) { +func initOTLPgRPCSpanExporter(ctx context.Context, otlpConfig *config.OTLP) (sdktrace.SpanExporter, error) { opts := []otlptracegrpc.Option{} if len(otlpConfig.Endpoint) > 0 { @@ -369,7 +375,7 @@ func initOTLPgRPCSpanExporter(ctx context.Context, otlpConfig *telemetry.Otlp) ( return otlptracegrpc.New(ctx, opts...) } -func initOTLPHTTPSpanExporter(ctx context.Context, otlpConfig *telemetry.Otlp) (sdktrace.SpanExporter, error) { +func initOTLPHTTPSpanExporter(ctx context.Context, otlpConfig *config.OTLP) (sdktrace.SpanExporter, error) { opts := []otlptracehttp.Option{} if len(otlpConfig.Endpoint) > 0 { @@ -406,7 +412,7 @@ func initOTLPHTTPSpanExporter(ctx context.Context, otlpConfig *telemetry.Otlp) ( return otlptracehttp.New(ctx, opts...) } -func initBatchSpanProcessor(bsp *telemetry.BatchSpanProcessor, exp sdktrace.SpanExporter) (sdktrace.SpanProcessor, error) { +func initBatchSpanProcessor(bsp *config.BatchSpanProcessor, exp sdktrace.SpanExporter) (sdktrace.SpanProcessor, error) { opts := []sdktrace.BatchSpanProcessorOption{} if bsp.ExportTimeout != nil { if *bsp.ExportTimeout < 0 { diff --git a/service/internal/proctelemetry/config_test.go b/service/internal/proctelemetry/config_test.go index cb09754e52c..6f7bbc16dfe 100644 --- a/service/internal/proctelemetry/config_test.go +++ b/service/internal/proctelemetry/config_test.go @@ -10,8 +10,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - - "go.opentelemetry.io/collector/service/telemetry" + "go.opentelemetry.io/contrib/config" ) func strPtr(s string) *string { @@ -25,7 +24,7 @@ func intPtr(i int) *int { func TestMetricReader(t *testing.T) { testCases := []struct { name string - reader telemetry.MetricReader + reader config.MetricReader args any err error }{ @@ -35,10 +34,10 @@ func TestMetricReader(t *testing.T) { }, { name: "pull prometheus invalid exporter", - reader: telemetry.MetricReader{ - Pull: &telemetry.PullMetricReader{ - Exporter: telemetry.MetricExporter{ - Otlp: &telemetry.OtlpMetric{}, + reader: config.MetricReader{ + Pull: &config.PullMetricReader{ + Exporter: config.MetricExporter{ + OTLP: &config.OTLPMetric{}, }, }, }, @@ -46,10 +45,10 @@ func TestMetricReader(t *testing.T) { }, { name: "pull/prometheus-invalid-config-no-host", - reader: telemetry.MetricReader{ - Pull: &telemetry.PullMetricReader{ - Exporter: telemetry.MetricExporter{ - Prometheus: &telemetry.Prometheus{}, + reader: config.MetricReader{ + Pull: &config.PullMetricReader{ + Exporter: config.MetricExporter{ + Prometheus: &config.Prometheus{}, }, }, }, @@ -57,10 +56,10 @@ func TestMetricReader(t *testing.T) { }, { name: "pull/prometheus-invalid-config-no-port", - reader: telemetry.MetricReader{ - Pull: &telemetry.PullMetricReader{ - Exporter: telemetry.MetricExporter{ - Prometheus: &telemetry.Prometheus{ + reader: config.MetricReader{ + Pull: &config.PullMetricReader{ + Exporter: config.MetricExporter{ + Prometheus: &config.Prometheus{ Host: strPtr("locahost"), }, }, @@ -70,10 +69,10 @@ func TestMetricReader(t *testing.T) { }, { name: "pull/prometheus-invalid-config-no-port", - reader: telemetry.MetricReader{ - Pull: &telemetry.PullMetricReader{ - Exporter: telemetry.MetricExporter{ - Prometheus: &telemetry.Prometheus{ + reader: config.MetricReader{ + Pull: &config.PullMetricReader{ + Exporter: config.MetricExporter{ + Prometheus: &config.Prometheus{ Host: strPtr("locahost"), Port: intPtr(8080), }, @@ -83,10 +82,10 @@ func TestMetricReader(t *testing.T) { }, { name: "periodic/invalid-exporter", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ - Exporter: telemetry.MetricExporter{ - Prometheus: &telemetry.Prometheus{ + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ + Exporter: config.MetricExporter{ + Prometheus: &config.Prometheus{ Host: strPtr("locahost"), Port: intPtr(8080), }, @@ -97,39 +96,39 @@ func TestMetricReader(t *testing.T) { }, { name: "periodic/no-exporter", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{}, + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{}, }, err: errNoValidMetricExporter, }, { name: "periodic/console-exporter", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ - Exporter: telemetry.MetricExporter{ - Console: telemetry.Console{}, + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ + Exporter: config.MetricExporter{ + Console: config.Console{}, }, }, }, }, { name: "periodic/console-exporter-with-timeout-interval", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ Interval: intPtr(10), Timeout: intPtr(5), - Exporter: telemetry.MetricExporter{ - Console: telemetry.Console{}, + Exporter: config.MetricExporter{ + Console: config.Console{}, }, }, }, }, { name: "periodic/otlp-exporter-invalid-protocol", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ - Exporter: telemetry.MetricExporter{ - Otlp: &telemetry.OtlpMetric{ + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ + Exporter: config.MetricExporter{ + OTLP: &config.OTLPMetric{ Protocol: *strPtr("http/invalid"), }, }, @@ -139,10 +138,10 @@ func TestMetricReader(t *testing.T) { }, { name: "periodic/otlp-grpc-exporter-no-endpoint", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ - Exporter: telemetry.MetricExporter{ - Otlp: &telemetry.OtlpMetric{ + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ + Exporter: config.MetricExporter{ + OTLP: &config.OTLPMetric{ Protocol: "grpc/protobuf", Compression: strPtr("gzip"), Timeout: intPtr(1000), @@ -156,10 +155,10 @@ func TestMetricReader(t *testing.T) { }, { name: "periodic/otlp-grpc-exporter", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ - Exporter: telemetry.MetricExporter{ - Otlp: &telemetry.OtlpMetric{ + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ + Exporter: config.MetricExporter{ + OTLP: &config.OTLPMetric{ Protocol: "grpc/protobuf", Endpoint: "http://localhost:4317", Compression: strPtr("none"), @@ -174,10 +173,10 @@ func TestMetricReader(t *testing.T) { }, { name: "periodic/otlp-grpc-exporter-no-scheme", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ - Exporter: telemetry.MetricExporter{ - Otlp: &telemetry.OtlpMetric{ + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ + Exporter: config.MetricExporter{ + OTLP: &config.OTLPMetric{ Protocol: "grpc/protobuf", Endpoint: "localhost:4317", Compression: strPtr("gzip"), @@ -192,10 +191,10 @@ func TestMetricReader(t *testing.T) { }, { name: "periodic/otlp-grpc-invalid-endpoint", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ - Exporter: telemetry.MetricExporter{ - Otlp: &telemetry.OtlpMetric{ + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ + Exporter: config.MetricExporter{ + OTLP: &config.OTLPMetric{ Protocol: "grpc/protobuf", Endpoint: " ", Compression: strPtr("gzip"), @@ -211,10 +210,10 @@ func TestMetricReader(t *testing.T) { }, { name: "periodic/otlp-grpc-invalid-compression", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ - Exporter: telemetry.MetricExporter{ - Otlp: &telemetry.OtlpMetric{ + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ + Exporter: config.MetricExporter{ + OTLP: &config.OTLPMetric{ Protocol: "grpc/protobuf", Endpoint: "localhost:4317", Compression: strPtr("invalid"), @@ -230,10 +229,10 @@ func TestMetricReader(t *testing.T) { }, { name: "periodic/otlp-http-exporter", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ - Exporter: telemetry.MetricExporter{ - Otlp: &telemetry.OtlpMetric{ + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ + Exporter: config.MetricExporter{ + OTLP: &config.OTLPMetric{ Protocol: "http/protobuf", Endpoint: "http://localhost:4318", Compression: strPtr("gzip"), @@ -248,10 +247,10 @@ func TestMetricReader(t *testing.T) { }, { name: "periodic/otlp-http-exporter-with-path", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ - Exporter: telemetry.MetricExporter{ - Otlp: &telemetry.OtlpMetric{ + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ + Exporter: config.MetricExporter{ + OTLP: &config.OTLPMetric{ Protocol: "http/protobuf", Endpoint: "http://localhost:4318/path/123", Compression: strPtr("none"), @@ -266,10 +265,10 @@ func TestMetricReader(t *testing.T) { }, { name: "periodic/otlp-http-exporter-no-endpoint", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ - Exporter: telemetry.MetricExporter{ - Otlp: &telemetry.OtlpMetric{ + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ + Exporter: config.MetricExporter{ + OTLP: &config.OTLPMetric{ Protocol: "http/protobuf", Compression: strPtr("gzip"), Timeout: intPtr(1000), @@ -283,10 +282,10 @@ func TestMetricReader(t *testing.T) { }, { name: "periodic/otlp-http-exporter-no-scheme", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ - Exporter: telemetry.MetricExporter{ - Otlp: &telemetry.OtlpMetric{ + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ + Exporter: config.MetricExporter{ + OTLP: &config.OTLPMetric{ Protocol: "http/protobuf", Endpoint: "localhost:4318", Compression: strPtr("gzip"), @@ -301,10 +300,10 @@ func TestMetricReader(t *testing.T) { }, { name: "periodic/otlp-http-invalid-endpoint", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ - Exporter: telemetry.MetricExporter{ - Otlp: &telemetry.OtlpMetric{ + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ + Exporter: config.MetricExporter{ + OTLP: &config.OTLPMetric{ Protocol: "http/protobuf", Endpoint: " ", Compression: strPtr("gzip"), @@ -320,10 +319,10 @@ func TestMetricReader(t *testing.T) { }, { name: "periodic/otlp-http-invalid-compression", - reader: telemetry.MetricReader{ - Periodic: &telemetry.PeriodicMetricReader{ - Exporter: telemetry.MetricExporter{ - Otlp: &telemetry.OtlpMetric{ + reader: config.MetricReader{ + Periodic: &config.PeriodicMetricReader{ + Exporter: config.MetricExporter{ + OTLP: &config.OTLPMetric{ Protocol: "http/protobuf", Endpoint: "localhost:4318", Compression: strPtr("invalid"), @@ -340,7 +339,15 @@ func TestMetricReader(t *testing.T) { } for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { - _, _, err := InitMetricReader(context.Background(), tt.reader, make(chan error)) + reader, server, err := InitMetricReader(context.Background(), tt.reader, make(chan error)) + defer func() { + if reader != nil { + assert.NoError(t, reader.Shutdown(context.Background())) + } + if server != nil { + assert.NoError(t, server.Shutdown(context.Background())) + } + }() assert.Equal(t, tt.err, err) }) } @@ -349,7 +356,7 @@ func TestMetricReader(t *testing.T) { func TestSpanProcessor(t *testing.T) { testCases := []struct { name string - processor telemetry.SpanProcessor + processor config.SpanProcessor args any err error }{ @@ -359,20 +366,20 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch processor invalid exporter", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ - Exporter: telemetry.SpanExporter{}, + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ + Exporter: config.SpanExporter{}, }, }, err: errNoValidSpanExporter, }, { name: "batch processor invalid batch size console exporter", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxExportBatchSize: intPtr(-1), - Exporter: telemetry.SpanExporter{ - Console: telemetry.Console{}, + Exporter: config.SpanExporter{ + Console: config.Console{}, }, }, }, @@ -380,11 +387,11 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch processor invalid export timeout console exporter", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ ExportTimeout: intPtr(-2), - Exporter: telemetry.SpanExporter{ - Console: telemetry.Console{}, + Exporter: config.SpanExporter{ + Console: config.Console{}, }, }, }, @@ -392,11 +399,11 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch processor invalid queue size console exporter", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxQueueSize: intPtr(-3), - Exporter: telemetry.SpanExporter{ - Console: telemetry.Console{}, + Exporter: config.SpanExporter{ + Console: config.Console{}, }, }, }, @@ -404,11 +411,11 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch processor invalid schedule delay console exporter", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ ScheduleDelay: intPtr(-4), - Exporter: telemetry.SpanExporter{ - Console: telemetry.Console{}, + Exporter: config.SpanExporter{ + Console: config.Console{}, }, }, }, @@ -416,28 +423,28 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch processor console exporter", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxExportBatchSize: intPtr(0), ExportTimeout: intPtr(0), MaxQueueSize: intPtr(0), ScheduleDelay: intPtr(0), - Exporter: telemetry.SpanExporter{ - Console: telemetry.Console{}, + Exporter: config.SpanExporter{ + Console: config.Console{}, }, }, }, }, { name: "batch/otlp-exporter-invalid-protocol", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxExportBatchSize: intPtr(0), ExportTimeout: intPtr(0), MaxQueueSize: intPtr(0), ScheduleDelay: intPtr(0), - Exporter: telemetry.SpanExporter{ - Otlp: &telemetry.Otlp{ + Exporter: config.SpanExporter{ + OTLP: &config.OTLP{ Protocol: *strPtr("http/invalid"), }, }, @@ -447,14 +454,14 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch/otlp-grpc-exporter-no-endpoint", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxExportBatchSize: intPtr(0), ExportTimeout: intPtr(0), MaxQueueSize: intPtr(0), ScheduleDelay: intPtr(0), - Exporter: telemetry.SpanExporter{ - Otlp: &telemetry.Otlp{ + Exporter: config.SpanExporter{ + OTLP: &config.OTLP{ Protocol: "grpc/protobuf", Compression: strPtr("gzip"), Timeout: intPtr(1000), @@ -468,14 +475,14 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch/otlp-grpc-exporter", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxExportBatchSize: intPtr(0), ExportTimeout: intPtr(0), MaxQueueSize: intPtr(0), ScheduleDelay: intPtr(0), - Exporter: telemetry.SpanExporter{ - Otlp: &telemetry.Otlp{ + Exporter: config.SpanExporter{ + OTLP: &config.OTLP{ Protocol: "grpc/protobuf", Endpoint: "http://localhost:4317", Compression: strPtr("gzip"), @@ -490,14 +497,14 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch/otlp-grpc-exporter-no-scheme", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxExportBatchSize: intPtr(0), ExportTimeout: intPtr(0), MaxQueueSize: intPtr(0), ScheduleDelay: intPtr(0), - Exporter: telemetry.SpanExporter{ - Otlp: &telemetry.Otlp{ + Exporter: config.SpanExporter{ + OTLP: &config.OTLP{ Protocol: "grpc/protobuf", Endpoint: "localhost:4317", Compression: strPtr("gzip"), @@ -512,14 +519,14 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch/otlp-grpc-invalid-endpoint", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxExportBatchSize: intPtr(0), ExportTimeout: intPtr(0), MaxQueueSize: intPtr(0), ScheduleDelay: intPtr(0), - Exporter: telemetry.SpanExporter{ - Otlp: &telemetry.Otlp{ + Exporter: config.SpanExporter{ + OTLP: &config.OTLP{ Protocol: "grpc/protobuf", Endpoint: " ", Compression: strPtr("gzip"), @@ -535,14 +542,14 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch/otlp-grpc-invalid-compression", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxExportBatchSize: intPtr(0), ExportTimeout: intPtr(0), MaxQueueSize: intPtr(0), ScheduleDelay: intPtr(0), - Exporter: telemetry.SpanExporter{ - Otlp: &telemetry.Otlp{ + Exporter: config.SpanExporter{ + OTLP: &config.OTLP{ Protocol: "grpc/protobuf", Endpoint: "localhost:4317", Compression: strPtr("invalid"), @@ -558,14 +565,14 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch/otlp-http-exporter", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxExportBatchSize: intPtr(0), ExportTimeout: intPtr(0), MaxQueueSize: intPtr(0), ScheduleDelay: intPtr(0), - Exporter: telemetry.SpanExporter{ - Otlp: &telemetry.Otlp{ + Exporter: config.SpanExporter{ + OTLP: &config.OTLP{ Protocol: "http/protobuf", Endpoint: "http://localhost:4318", Compression: strPtr("gzip"), @@ -580,14 +587,14 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch/otlp-http-exporter-with-path", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxExportBatchSize: intPtr(0), ExportTimeout: intPtr(0), MaxQueueSize: intPtr(0), ScheduleDelay: intPtr(0), - Exporter: telemetry.SpanExporter{ - Otlp: &telemetry.Otlp{ + Exporter: config.SpanExporter{ + OTLP: &config.OTLP{ Protocol: "http/protobuf", Endpoint: "http://localhost:4318/path/123", Compression: strPtr("none"), @@ -602,14 +609,14 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch/otlp-http-exporter-no-endpoint", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxExportBatchSize: intPtr(0), ExportTimeout: intPtr(0), MaxQueueSize: intPtr(0), ScheduleDelay: intPtr(0), - Exporter: telemetry.SpanExporter{ - Otlp: &telemetry.Otlp{ + Exporter: config.SpanExporter{ + OTLP: &config.OTLP{ Protocol: "http/protobuf", Compression: strPtr("gzip"), Timeout: intPtr(1000), @@ -623,14 +630,14 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch/otlp-http-exporter-no-scheme", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxExportBatchSize: intPtr(0), ExportTimeout: intPtr(0), MaxQueueSize: intPtr(0), ScheduleDelay: intPtr(0), - Exporter: telemetry.SpanExporter{ - Otlp: &telemetry.Otlp{ + Exporter: config.SpanExporter{ + OTLP: &config.OTLP{ Protocol: "http/protobuf", Endpoint: "localhost:4318", Compression: strPtr("gzip"), @@ -645,14 +652,14 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch/otlp-http-invalid-endpoint", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxExportBatchSize: intPtr(0), ExportTimeout: intPtr(0), MaxQueueSize: intPtr(0), ScheduleDelay: intPtr(0), - Exporter: telemetry.SpanExporter{ - Otlp: &telemetry.Otlp{ + Exporter: config.SpanExporter{ + OTLP: &config.OTLP{ Protocol: "http/protobuf", Endpoint: " ", Compression: strPtr("gzip"), @@ -668,14 +675,14 @@ func TestSpanProcessor(t *testing.T) { }, { name: "batch/otlp-http-invalid-compression", - processor: telemetry.SpanProcessor{ - Batch: &telemetry.BatchSpanProcessor{ + processor: config.SpanProcessor{ + Batch: &config.BatchSpanProcessor{ MaxExportBatchSize: intPtr(0), ExportTimeout: intPtr(0), MaxQueueSize: intPtr(0), ScheduleDelay: intPtr(0), - Exporter: telemetry.SpanExporter{ - Otlp: &telemetry.Otlp{ + Exporter: config.SpanExporter{ + OTLP: &config.OTLP{ Protocol: "http/protobuf", Endpoint: "localhost:4318", Compression: strPtr("invalid"), @@ -692,7 +699,12 @@ func TestSpanProcessor(t *testing.T) { } for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { - _, err := InitSpanProcessor(context.Background(), tt.processor) + processor, err := InitSpanProcessor(context.Background(), tt.processor) + defer func() { + if processor != nil { + assert.NoError(t, processor.Shutdown(context.Background())) + } + }() assert.Equal(t, tt.err, err) }) } diff --git a/service/internal/proctelemetry/process_telemetry.go b/service/internal/proctelemetry/process_telemetry.go index a5e80443fcd..991897f8b1b 100644 --- a/service/internal/proctelemetry/process_telemetry.go +++ b/service/internal/proctelemetry/process_telemetry.go @@ -5,7 +5,6 @@ package proctelemetry // import "go.opentelemetry.io/collector/service/internal/ import ( "context" - "errors" "os" "runtime" "sync" @@ -13,10 +12,7 @@ import ( "github.com/shirou/gopsutil/v3/common" "github.com/shirou/gopsutil/v3/process" - "go.opencensus.io/metric" - "go.opencensus.io/stats" otelmetric "go.opentelemetry.io/otel/metric" - sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.uber.org/multierr" ) @@ -32,14 +28,6 @@ type processMetrics struct { proc *process.Process context context.Context - processUptime *metric.Float64DerivedCumulative - allocMem *metric.Int64DerivedGauge - totalAllocMem *metric.Int64DerivedCumulative - sysMem *metric.Int64DerivedGauge - cpuSeconds *metric.Float64DerivedCumulative - rssMemory *metric.Int64DerivedGauge - - // otel metrics otelProcessUptime otelmetric.Float64ObservableCounter otelAllocMem otelmetric.Int64ObservableGauge otelTotalAllocMem otelmetric.Int64ObservableCounter @@ -76,7 +64,7 @@ func WithHostProc(hostProc string) RegisterOption { // RegisterProcessMetrics creates a new set of processMetrics (mem, cpu) that can be used to measure // basic information about this process. -func RegisterProcessMetrics(ocRegistry *metric.Registry, mp otelmetric.MeterProvider, useOtel bool, ballastSizeBytes uint64, opts ...RegisterOption) error { +func RegisterProcessMetrics(mp otelmetric.MeterProvider, ballastSizeBytes uint64, opts ...RegisterOption) error { set := registerOption{} for _, opt := range opts { opt.apply(&set) @@ -98,85 +86,10 @@ func RegisterProcessMetrics(ocRegistry *metric.Registry, mp otelmetric.MeterProv return err } - if useOtel { - // ignore instrument name error as per workaround in https://github.com/open-telemetry/opentelemetry-collector/issues/8346 - if err = pm.recordWithOtel(mp.Meter(scopeName)); err != nil && !errors.Is(err, sdkmetric.ErrInstrumentName) { - return err - } - return nil - } - return pm.recordWithOC(ocRegistry) -} - -func (pm *processMetrics) recordWithOC(ocRegistry *metric.Registry) error { - var err error - - pm.processUptime, err = ocRegistry.AddFloat64DerivedCumulative( - "process/uptime", - metric.WithDescription("Uptime of the process"), - metric.WithUnit(stats.UnitSeconds)) - if err != nil { - return err - } - if err = pm.processUptime.UpsertEntry(pm.updateProcessUptime); err != nil { - return err - } - - pm.allocMem, err = ocRegistry.AddInt64DerivedGauge( - "process/runtime/heap_alloc_bytes", - metric.WithDescription("Bytes of allocated heap objects (see 'go doc runtime.MemStats.HeapAlloc')"), - metric.WithUnit(stats.UnitBytes)) - if err != nil { - return err - } - if err = pm.allocMem.UpsertEntry(pm.updateAllocMem); err != nil { - return err - } - - pm.totalAllocMem, err = ocRegistry.AddInt64DerivedCumulative( - "process/runtime/total_alloc_bytes", - metric.WithDescription("Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc')"), - metric.WithUnit(stats.UnitBytes)) - if err != nil { - return err - } - if err = pm.totalAllocMem.UpsertEntry(pm.updateTotalAllocMem); err != nil { - return err - } - - pm.sysMem, err = ocRegistry.AddInt64DerivedGauge( - "process/runtime/total_sys_memory_bytes", - metric.WithDescription("Total bytes of memory obtained from the OS (see 'go doc runtime.MemStats.Sys')"), - metric.WithUnit(stats.UnitBytes)) - if err != nil { - return err - } - if err = pm.sysMem.UpsertEntry(pm.updateSysMem); err != nil { - return err - } - - pm.cpuSeconds, err = ocRegistry.AddFloat64DerivedCumulative( - "process/cpu_seconds", - metric.WithDescription("Total CPU user and system time in seconds"), - metric.WithUnit(stats.UnitSeconds)) - if err != nil { - return err - } - if err = pm.cpuSeconds.UpsertEntry(pm.updateCPUSeconds); err != nil { - return err - } - - pm.rssMemory, err = ocRegistry.AddInt64DerivedGauge( - "process/memory/rss", - metric.WithDescription("Total physical memory (resident set size)"), - metric.WithUnit(stats.UnitBytes)) - if err != nil { - return err - } - return pm.rssMemory.UpsertEntry(pm.updateRSSMemory) + return pm.record(mp.Meter(scopeName)) } -func (pm *processMetrics) recordWithOtel(meter otelmetric.Meter) error { +func (pm *processMetrics) record(meter otelmetric.Meter) error { var errs, err error pm.otelProcessUptime, err = meter.Float64ObservableCounter( diff --git a/service/internal/proctelemetry/process_telemetry_linux_test.go b/service/internal/proctelemetry/process_telemetry_linux_test.go index d42838b2782..1a15f28fc7e 100644 --- a/service/internal/proctelemetry/process_telemetry_linux_test.go +++ b/service/internal/proctelemetry/process_telemetry_linux_test.go @@ -2,52 +2,50 @@ // SPDX-License-Identifier: Apache-2.0 //go:build linux -// +build linux package proctelemetry import ( + "fmt" + "strings" "testing" "time" + io_prometheus_client "github.com/prometheus/client_model/go" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opencensus.io/metric" - "go.opentelemetry.io/otel/metric/noop" ) -func TestOCProcessTelemetryWithHostProc(t *testing.T) { - ocRegistry := metric.NewRegistry() +func TestProcessTelemetryWithHostProc(t *testing.T) { + tel := setupTelemetry(t) // Make the sure the environment variable value is not used. t.Setenv("HOST_PROC", "foo/bar") - require.NoError(t, RegisterProcessMetrics(ocRegistry, noop.NewMeterProvider(), false, 0, WithHostProc("/proc"))) + require.NoError(t, RegisterProcessMetrics(tel.MeterProvider, 0, WithHostProc("/proc"))) // Check that the metrics are actually filled. time.Sleep(200 * time.Millisecond) - metrics := ocRegistry.Read() + mp, err := fetchPrometheusMetrics(tel.promHandler) + require.NoError(t, err) for _, metricName := range expectedMetrics { - m := findMetric(metrics, metricName) - require.NotNil(t, m) - require.Len(t, m.TimeSeries, 1) - ts := m.TimeSeries[0] - assert.Len(t, ts.LabelValues, 0) - require.Len(t, ts.Points, 1) - - var value float64 - if metricName == "process/uptime" || metricName == "process/cpu_seconds" { - value = ts.Points[0].Value.(float64) + metric, ok := mp[metricName] + require.True(t, ok) + require.True(t, len(metric.Metric) == 1) + var metricValue float64 + if metric.GetType() == io_prometheus_client.MetricType_COUNTER { + metricValue = metric.Metric[0].GetCounter().GetValue() } else { - value = float64(ts.Points[0].Value.(int64)) + metricValue = metric.Metric[0].GetGauge().GetValue() } - - if metricName == "process/uptime" || metricName == "process/cpu_seconds" { + if strings.HasPrefix(metricName, "process_uptime") || strings.HasPrefix(metricName, "process_cpu_seconds") { // This likely will still be zero when running the test. - assert.GreaterOrEqual(t, value, float64(0), metricName) + assert.GreaterOrEqual(t, metricValue, float64(0), metricName) continue } - assert.Greater(t, value, float64(0), metricName) + + fmt.Println(metricName) + assert.Greater(t, metricValue, float64(0), metricName) } } diff --git a/service/internal/proctelemetry/process_telemetry_test.go b/service/internal/proctelemetry/process_telemetry_test.go index 5caa96417bd..40d0f54ef27 100644 --- a/service/internal/proctelemetry/process_telemetry_test.go +++ b/service/internal/proctelemetry/process_telemetry_test.go @@ -9,7 +9,6 @@ import ( "net/http/httptest" "strings" "testing" - "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -17,42 +16,22 @@ import ( "github.com/prometheus/common/expfmt" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opencensus.io/metric" - "go.opencensus.io/metric/metricdata" - "go.opencensus.io/stats/view" otelprom "go.opentelemetry.io/otel/exporters/prometheus" - "go.opentelemetry.io/otel/metric/noop" sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/config/configtelemetry" - "go.opentelemetry.io/collector/internal/obsreportconfig" ) type testTelemetry struct { component.TelemetrySettings - views []*view.View - promHandler http.Handler - meterProvider *sdkmetric.MeterProvider - expectedMetrics []string + promHandler http.Handler + meterProvider *sdkmetric.MeterProvider } var expectedMetrics = []string{ - // Changing a metric name is a breaking change. - // Adding new metrics is ok as long it follows the conventions described at - // https://pkg.go.dev/go.opentelemetry.io/collector/obsreport?tab=doc#hdr-Naming_Convention_for_New_Metrics - "process/uptime", - "process/runtime/heap_alloc_bytes", - "process/runtime/total_alloc_bytes", - "process/runtime/total_sys_memory_bytes", - "process/cpu_seconds", - "process/memory/rss", -} - -var otelExpectedMetrics = []string{ - // OTel Go adds `_total` suffix "process_uptime", "process_runtime_heap_alloc_bytes", "process_runtime_total_alloc_bytes", @@ -64,16 +43,11 @@ var otelExpectedMetrics = []string{ func setupTelemetry(t *testing.T) testTelemetry { settings := testTelemetry{ TelemetrySettings: componenttest.NewNopTelemetrySettings(), - expectedMetrics: otelExpectedMetrics, } settings.TelemetrySettings.MetricsLevel = configtelemetry.LevelNormal - settings.views = obsreportconfig.AllViews(configtelemetry.LevelNormal) - err := view.Register(settings.views...) - require.NoError(t, err) - promReg := prometheus.NewRegistry() - exporter, err := otelprom.New(otelprom.WithRegisterer(promReg), otelprom.WithoutUnits()) + exporter, err := otelprom.New(otelprom.WithRegisterer(promReg), otelprom.WithoutUnits(), otelprom.WithoutCounterSuffixes()) require.NoError(t, err) settings.meterProvider = sdkmetric.NewMeterProvider( @@ -102,20 +76,16 @@ func fetchPrometheusMetrics(handler http.Handler) (map[string]*io_prometheus_cli return parser.TextToMetricFamilies(rr.Body) } -func TestOtelProcessTelemetry(t *testing.T) { +func TestProcessTelemetry(t *testing.T) { tel := setupTelemetry(t) - require.NoError(t, RegisterProcessMetrics(nil, tel.MeterProvider, true, 0)) + require.NoError(t, RegisterProcessMetrics(tel.MeterProvider, 0)) mp, err := fetchPrometheusMetrics(tel.promHandler) require.NoError(t, err) - for _, metricName := range tel.expectedMetrics { + for _, metricName := range expectedMetrics { metric, ok := mp[metricName] - if !ok { - withSuffix := metricName + "_total" - metric, ok = mp[withSuffix] - } require.True(t, ok) require.True(t, len(metric.Metric) == 1) var metricValue float64 @@ -133,58 +103,3 @@ func TestOtelProcessTelemetry(t *testing.T) { assert.Greater(t, metricValue, float64(0), metricName) } } - -func TestOCProcessTelemetry(t *testing.T) { - ocRegistry := metric.NewRegistry() - - require.NoError(t, RegisterProcessMetrics(ocRegistry, noop.NewMeterProvider(), false, 0)) - - // Check that the metrics are actually filled. - <-time.After(200 * time.Millisecond) - - metrics := ocRegistry.Read() - - for _, metricName := range expectedMetrics { - m := findMetric(metrics, metricName) - require.NotNil(t, m) - require.Len(t, m.TimeSeries, 1) - ts := m.TimeSeries[0] - assert.Len(t, ts.LabelValues, 0) - require.Len(t, ts.Points, 1) - - var value float64 - if metricName == "process/uptime" || metricName == "process/cpu_seconds" { - value = ts.Points[0].Value.(float64) - } else { - value = float64(ts.Points[0].Value.(int64)) - } - - if metricName == "process/uptime" || metricName == "process/cpu_seconds" { - // This likely will still be zero when running the test. - assert.GreaterOrEqual(t, value, float64(0), metricName) - continue - } - - assert.Greater(t, value, float64(0), metricName) - } -} - -func TestProcessTelemetryFailToRegister(t *testing.T) { - for _, metricName := range expectedMetrics { - t.Run(metricName, func(t *testing.T) { - ocRegistry := metric.NewRegistry() - _, err := ocRegistry.AddFloat64Gauge(metricName) - require.NoError(t, err) - assert.Error(t, RegisterProcessMetrics(ocRegistry, noop.NewMeterProvider(), false, 0)) - }) - } -} - -func findMetric(metrics []*metricdata.Metric, name string) *metricdata.Metric { - for _, m := range metrics { - if m.Descriptor.Name == name { - return m - } - } - return nil -} diff --git a/service/internal/resource/config.go b/service/internal/resource/config.go new file mode 100644 index 00000000000..1f233ddde97 --- /dev/null +++ b/service/internal/resource/config.go @@ -0,0 +1,44 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package resource // import "go.opentelemetry.io/collector/service/internal/resource" + +import ( + "github.com/google/uuid" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/resource" + + "go.opentelemetry.io/collector/component" + semconv "go.opentelemetry.io/collector/semconv/v1.18.0" +) + +// New resource from telemetry configuration. +func New(buildInfo component.BuildInfo, resourceCfg map[string]*string) *resource.Resource { + var telAttrs []attribute.KeyValue + + for k, v := range resourceCfg { + // nil value indicates that the attribute should not be included in the telemetry. + if v != nil { + telAttrs = append(telAttrs, attribute.String(k, *v)) + } + } + + if _, ok := resourceCfg[semconv.AttributeServiceName]; !ok { + // AttributeServiceName is not specified in the config. Use the default service name. + telAttrs = append(telAttrs, attribute.String(semconv.AttributeServiceName, buildInfo.Command)) + } + + if _, ok := resourceCfg[semconv.AttributeServiceInstanceID]; !ok { + // AttributeServiceInstanceID is not specified in the config. Auto-generate one. + instanceUUID, _ := uuid.NewRandom() + instanceID := instanceUUID.String() + telAttrs = append(telAttrs, attribute.String(semconv.AttributeServiceInstanceID, instanceID)) + } + + if _, ok := resourceCfg[semconv.AttributeServiceVersion]; !ok { + // AttributeServiceVersion is not specified in the config. Use the actual + // build version. + telAttrs = append(telAttrs, attribute.String(semconv.AttributeServiceVersion, buildInfo.Version)) + } + return resource.NewWithAttributes(semconv.SchemaURL, telAttrs...) +} diff --git a/service/internal/resource/config_test.go b/service/internal/resource/config_test.go new file mode 100644 index 00000000000..ab8f8e816c3 --- /dev/null +++ b/service/internal/resource/config_test.go @@ -0,0 +1,103 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package resource + +import ( + "testing" + + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/component" +) + +const ( + randomUUIDSpecialValue = "random-uuid" +) + +var buildInfo = component.BuildInfo{ + Command: "otelcol", + Version: "1.0.0", +} + +func ptr[T any](v T) *T { + return &v +} + +func TestNew(t *testing.T) { + tests := []struct { + name string + resourceCfg map[string]*string + want map[string]string + }{ + { + name: "empty", + resourceCfg: map[string]*string{}, + want: map[string]string{ + "service.name": "otelcol", + "service.version": "1.0.0", + "service.instance.id": randomUUIDSpecialValue, + }, + }, + { + name: "overwrite", + resourceCfg: map[string]*string{ + "service.name": ptr("my-service"), + "service.version": ptr("1.2.3"), + "service.instance.id": ptr("123"), + }, + want: map[string]string{ + "service.name": "my-service", + "service.version": "1.2.3", + "service.instance.id": "123", + }, + }, + { + name: "remove", + resourceCfg: map[string]*string{ + "service.name": nil, + "service.version": nil, + "service.instance.id": nil, + }, + want: map[string]string{}, + }, + { + name: "add", + resourceCfg: map[string]*string{ + "host.name": ptr("my-host"), + }, + want: map[string]string{ + "service.name": "otelcol", + "service.version": "1.0.0", + "service.instance.id": randomUUIDSpecialValue, + "host.name": "my-host", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := New(buildInfo, tt.resourceCfg) + got := make(map[string]string) + for _, attr := range res.Attributes() { + got[string(attr.Key)] = attr.Value.Emit() + } + + if tt.want["service.instance.id"] == randomUUIDSpecialValue { + assert.Contains(t, got, "service.instance.id") + + // Check that the value is a valid UUID. + _, err := uuid.Parse(got["service.instance.id"]) + assert.NoError(t, err) + + // Remove so that we can compare the rest of the map. + delete(got, "service.instance.id") + delete(tt.want, "service.instance.id") + } + + assert.EqualValues(t, tt.want, got) + }) + } + +} diff --git a/service/internal/servicetelemetry/nop_telemetry_settings.go b/service/internal/servicetelemetry/nop_telemetry_settings.go new file mode 100644 index 00000000000..116554a51f8 --- /dev/null +++ b/service/internal/servicetelemetry/nop_telemetry_settings.go @@ -0,0 +1,27 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package servicetelemetry // import "go.opentelemetry.io/collector/service/internal/servicetelemetry" + +import ( + noopmetric "go.opentelemetry.io/otel/metric/noop" + nooptrace "go.opentelemetry.io/otel/trace/noop" + "go.uber.org/zap" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/configtelemetry" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/service/internal/status" +) + +// NewNopTelemetrySettings returns a new nop settings for Create* functions. +func NewNopTelemetrySettings() TelemetrySettings { + return TelemetrySettings{ + Logger: zap.NewNop(), + TracerProvider: nooptrace.NewTracerProvider(), + MeterProvider: noopmetric.NewMeterProvider(), + MetricsLevel: configtelemetry.LevelNone, + Resource: pcommon.NewResource(), + Status: status.NewReporter(func(*component.InstanceID, *component.StatusEvent) {}, func(error) {}), + } +} diff --git a/service/internal/servicetelemetry/nop_telemetry_settings_test.go b/service/internal/servicetelemetry/nop_telemetry_settings_test.go new file mode 100644 index 00000000000..8c4a401e0f0 --- /dev/null +++ b/service/internal/servicetelemetry/nop_telemetry_settings_test.go @@ -0,0 +1,35 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package servicetelemetry + +import ( + "testing" + + "github.com/stretchr/testify/require" + noopmetric "go.opentelemetry.io/otel/metric/noop" + nooptrace "go.opentelemetry.io/otel/trace/noop" + "go.uber.org/zap" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/configtelemetry" + "go.opentelemetry.io/collector/pdata/pcommon" +) + +func TestNewNopSettings(t *testing.T) { + set := NewNopTelemetrySettings() + set.Status.Ready() + require.NotNil(t, set) + require.IsType(t, TelemetrySettings{}, set) + require.Equal(t, zap.NewNop(), set.Logger) + require.Equal(t, nooptrace.NewTracerProvider(), set.TracerProvider) + require.Equal(t, noopmetric.NewMeterProvider(), set.MeterProvider) + require.Equal(t, configtelemetry.LevelNone, set.MetricsLevel) + require.Equal(t, pcommon.NewResource(), set.Resource) + set.Status.ReportStatus( + &component.InstanceID{}, + component.NewStatusEvent(component.StatusStarting), + ) + set.Status.ReportOKIfStarting(&component.InstanceID{}) + +} diff --git a/service/internal/servicetelemetry/package_test.go b/service/internal/servicetelemetry/package_test.go new file mode 100644 index 00000000000..0c9a1bc67a6 --- /dev/null +++ b/service/internal/servicetelemetry/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package servicetelemetry + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/service/internal/servicetelemetry/telemetry_settings.go b/service/internal/servicetelemetry/telemetry_settings.go new file mode 100644 index 00000000000..55c6b9f3962 --- /dev/null +++ b/service/internal/servicetelemetry/telemetry_settings.go @@ -0,0 +1,55 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package servicetelemetry // import "go.opentelemetry.io/collector/service/internal/servicetelemetry" + +import ( + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + "go.uber.org/zap" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/configtelemetry" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/service/internal/status" +) + +// TelemetrySettings mirrors component.TelemetrySettings except for the mechanism for reporting +// status. Service-level status reporting has additional methods which can report status for +// components by their InstanceID whereas the component versions are tied to a specific component. +type TelemetrySettings struct { + // Logger that the factory can use during creation and can pass to the created + // component to be used later as well. + Logger *zap.Logger + + // TracerProvider that the factory can pass to other instrumented third-party libraries. + TracerProvider trace.TracerProvider + + // MeterProvider that the factory can pass to other instrumented third-party libraries. + MeterProvider metric.MeterProvider + + // MetricsLevel controls the level of detail for metrics emitted by the collector. + // Experimental: *NOTE* this field is experimental and may be changed or removed. + MetricsLevel configtelemetry.Level + + // Resource contains the resource attributes for the collector's telemetry. + Resource pcommon.Resource + + // Status contains a Reporter that allows the service to report status on behalf of a + // component. + Status *status.Reporter +} + +// ToComponentTelemetrySettings returns a TelemetrySettings for a specific component derived from +// this service level Settings object. +func (s TelemetrySettings) ToComponentTelemetrySettings(id *component.InstanceID) component.TelemetrySettings { + statusFunc := status.NewReportStatusFunc(id, s.Status.ReportStatus) + return component.TelemetrySettings{ + Logger: s.Logger, + TracerProvider: s.TracerProvider, + MeterProvider: s.MeterProvider, + MetricsLevel: s.MetricsLevel, + Resource: s.Resource, + ReportStatus: statusFunc, + } +} diff --git a/service/internal/servicetelemetry/telemetry_settings_test.go b/service/internal/servicetelemetry/telemetry_settings_test.go new file mode 100644 index 00000000000..5aad2c6c2b6 --- /dev/null +++ b/service/internal/servicetelemetry/telemetry_settings_test.go @@ -0,0 +1,40 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package servicetelemetry + +import ( + "testing" + + "github.com/stretchr/testify/require" + noopmetric "go.opentelemetry.io/otel/metric/noop" + nooptrace "go.opentelemetry.io/otel/trace/noop" + "go.uber.org/zap" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/configtelemetry" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/service/internal/status" +) + +func TestSettings(t *testing.T) { + set := TelemetrySettings{ + Logger: zap.NewNop(), + TracerProvider: nooptrace.NewTracerProvider(), + MeterProvider: noopmetric.NewMeterProvider(), + MetricsLevel: configtelemetry.LevelNone, + Resource: pcommon.NewResource(), + Status: status.NewReporter( + func(*component.InstanceID, *component.StatusEvent) {}, + func(err error) { require.NoError(t, err) }), + } + set.Status.Ready() + set.Status.ReportStatus( + &component.InstanceID{}, + component.NewStatusEvent(component.StatusStarting), + ) + set.Status.ReportOKIfStarting(&component.InstanceID{}) + + compSet := set.ToComponentTelemetrySettings(&component.InstanceID{}) + compSet.ReportStatus(component.NewStatusEvent(component.StatusStarting)) +} diff --git a/service/internal/status/package_test.go b/service/internal/status/package_test.go new file mode 100644 index 00000000000..a49dda2ff11 --- /dev/null +++ b/service/internal/status/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package status + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/service/internal/status/status.go b/service/internal/status/status.go new file mode 100644 index 00000000000..21790b1061f --- /dev/null +++ b/service/internal/status/status.go @@ -0,0 +1,193 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package status // import "go.opentelemetry.io/collector/service/internal/status" + +import ( + "errors" + "fmt" + "sync" + + "go.opentelemetry.io/collector/component" +) + +// onTransitionFunc receives a component.StatusEvent on a successful state transition +type onTransitionFunc func(*component.StatusEvent) + +// errInvalidStateTransition is returned for invalid state transitions +var errInvalidStateTransition = errors.New("invalid state transition") + +// fsm is a finite state machine that models transitions for component status +type fsm struct { + current *component.StatusEvent + transitions map[component.Status]map[component.Status]struct{} + onTransition onTransitionFunc +} + +// transition will attempt to execute a state transition. If it's successful, it calls the +// onTransitionFunc with a StatusEvent representing the new state. Returns an error if the arguments +// result in an invalid status, or if the state transition is not valid. +func (m *fsm) transition(ev *component.StatusEvent) error { + if _, ok := m.transitions[m.current.Status()][ev.Status()]; !ok { + return fmt.Errorf( + "cannot transition from %s to %s: %w", + m.current.Status(), + ev.Status(), + errInvalidStateTransition, + ) + } + m.current = ev + m.onTransition(ev) + return nil +} + +// newFSM creates a state machine with all valid transitions for component.Status. +// The initial state is set to component.StatusNone. +func newFSM(onTransition onTransitionFunc) *fsm { + return &fsm{ + current: component.NewStatusEvent(component.StatusNone), + onTransition: onTransition, + transitions: map[component.Status]map[component.Status]struct{}{ + component.StatusNone: { + component.StatusStarting: {}, + }, + component.StatusStarting: { + component.StatusOK: {}, + component.StatusRecoverableError: {}, + component.StatusPermanentError: {}, + component.StatusFatalError: {}, + component.StatusStopping: {}, + }, + component.StatusOK: { + component.StatusRecoverableError: {}, + component.StatusPermanentError: {}, + component.StatusFatalError: {}, + component.StatusStopping: {}, + }, + component.StatusRecoverableError: { + component.StatusOK: {}, + component.StatusPermanentError: {}, + component.StatusFatalError: {}, + component.StatusStopping: {}, + }, + component.StatusPermanentError: {}, + component.StatusFatalError: {}, + component.StatusStopping: { + component.StatusRecoverableError: {}, + component.StatusPermanentError: {}, + component.StatusFatalError: {}, + component.StatusStopped: {}, + }, + component.StatusStopped: {}, + }, + } +} + +// NotifyStatusFunc is the receiver of status events after successful state transitions +type NotifyStatusFunc func(*component.InstanceID, *component.StatusEvent) + +// InvalidTransitionFunc is the receiver of invalid transition errors +type InvalidTransitionFunc func(error) + +// ServiceStatusFunc is the expected type of ReportStatus for servicetelemetry.Settings +type ServiceStatusFunc func(*component.InstanceID, *component.StatusEvent) + +// ErrStatusNotReady is returned when trying to report status before service start +var ErrStatusNotReady = errors.New("report component status is not ready until service start") + +// Reporter handles component status reporting +type Reporter struct { + mu sync.Mutex + ready bool + fsmMap map[*component.InstanceID]*fsm + onStatusChange NotifyStatusFunc + onInvalidTransition InvalidTransitionFunc +} + +// NewReporter returns a reporter that will invoke the NotifyStatusFunc when a component's status +// has changed. +func NewReporter(onStatusChange NotifyStatusFunc, onInvalidTransition InvalidTransitionFunc) *Reporter { + return &Reporter{ + fsmMap: make(map[*component.InstanceID]*fsm), + onStatusChange: onStatusChange, + onInvalidTransition: onInvalidTransition, + } +} + +// Ready enables status reporting +func (r *Reporter) Ready() { + r.mu.Lock() + defer r.mu.Unlock() + r.ready = true +} + +// ReportComponentStatus reports status for the given InstanceID +// Deprecated: [v0.92.0] This function will be removed in a future release. +// Use ReportStatus instead. +func (r *Reporter) ReportComponentStatus( + id *component.InstanceID, + ev *component.StatusEvent, +) error { + r.ReportStatus(id, ev) + return nil +} + +// ReportStatus reports status for the given InstanceID +func (r *Reporter) ReportStatus( + id *component.InstanceID, + ev *component.StatusEvent, +) { + r.mu.Lock() + defer r.mu.Unlock() + if !r.ready { + r.onInvalidTransition(ErrStatusNotReady) + } else { + if err := r.componentFSM(id).transition(ev); err != nil { + r.onInvalidTransition(err) + } + } +} + +// ReportComponentOkIfStarting reports StatusOK if the component's current status is Starting +// Deprecated: [v0.92.0] This function will be removed in a future release. +// Use ReportOKIfStarting instead. +func (r *Reporter) ReportComponentOKIfStarting(id *component.InstanceID) error { + r.ReportOKIfStarting(id) + return nil +} + +func (r *Reporter) ReportOKIfStarting(id *component.InstanceID) { + r.mu.Lock() + defer r.mu.Unlock() + if !r.ready { + r.onInvalidTransition(ErrStatusNotReady) + } + fsm := r.componentFSM(id) + if fsm.current.Status() == component.StatusStarting { + if err := fsm.transition(component.NewStatusEvent(component.StatusOK)); err != nil { + r.onInvalidTransition(err) + } + } +} + +// Note: a lock must be acquired before calling this method. +func (r *Reporter) componentFSM(id *component.InstanceID) *fsm { + fsm, ok := r.fsmMap[id] + if !ok { + fsm = newFSM(func(ev *component.StatusEvent) { r.onStatusChange(id, ev) }) + r.fsmMap[id] = fsm + } + return fsm +} + +// NewReportStatusFunc returns a function to be used as ReportStatus for +// component.TelemetrySettings, which differs from servicetelemetry.Settings in that +// the component version is tied to specific component instance. +func NewReportStatusFunc( + id *component.InstanceID, + srvStatus ServiceStatusFunc, +) func(*component.StatusEvent) { + return func(ev *component.StatusEvent) { + srvStatus(id, ev) + } +} diff --git a/service/internal/status/status_test.go b/service/internal/status/status_test.go new file mode 100644 index 00000000000..c31c649e496 --- /dev/null +++ b/service/internal/status/status_test.go @@ -0,0 +1,353 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package status + +import ( + "fmt" + "sync" + "testing" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" +) + +func TestStatusFSM(t *testing.T) { + for _, tc := range []struct { + name string + reportedStatuses []component.Status + expectedStatuses []component.Status + expectedErrorCount int + }{ + { + name: "successful startup and shutdown", + reportedStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusStopping, + component.StatusStopped, + }, + expectedStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusStopping, + component.StatusStopped, + }, + }, + { + name: "component recovered", + reportedStatuses: []component.Status{ + component.StatusStarting, + component.StatusRecoverableError, + component.StatusOK, + component.StatusStopping, + component.StatusStopped, + }, + expectedStatuses: []component.Status{ + component.StatusStarting, + component.StatusRecoverableError, + component.StatusOK, + component.StatusStopping, + component.StatusStopped, + }, + }, + { + name: "repeated events are errors", + reportedStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusRecoverableError, + component.StatusRecoverableError, + component.StatusRecoverableError, + component.StatusOK, + component.StatusStopping, + component.StatusStopped, + }, + expectedStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusRecoverableError, + component.StatusOK, + component.StatusStopping, + component.StatusStopped, + }, + expectedErrorCount: 2, + }, + { + name: "PermanentError is terminal", + reportedStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusPermanentError, + component.StatusOK, + }, + expectedStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusPermanentError, + }, + expectedErrorCount: 1, + }, + { + name: "FatalError is terminal", + reportedStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusFatalError, + component.StatusOK, + }, + expectedStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusFatalError, + }, + expectedErrorCount: 1, + }, + { + name: "Stopped is terminal", + reportedStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusStopping, + component.StatusStopped, + component.StatusOK, + }, + expectedStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusStopping, + component.StatusStopped, + }, + expectedErrorCount: 1, + }, + } { + t.Run(tc.name, func(t *testing.T) { + var receivedStatuses []component.Status + fsm := newFSM( + func(ev *component.StatusEvent) { + receivedStatuses = append(receivedStatuses, ev.Status()) + }, + ) + + errorCount := 0 + for _, status := range tc.reportedStatuses { + if err := fsm.transition(component.NewStatusEvent(status)); err != nil { + errorCount++ + require.ErrorIs(t, err, errInvalidStateTransition) + } + } + + require.Equal(t, tc.expectedErrorCount, errorCount) + require.Equal(t, tc.expectedStatuses, receivedStatuses) + }) + } +} + +func TestValidSeqsToStopped(t *testing.T) { + events := []*component.StatusEvent{ + component.NewStatusEvent(component.StatusStarting), + component.NewStatusEvent(component.StatusOK), + component.NewStatusEvent(component.StatusRecoverableError), + component.NewStatusEvent(component.StatusPermanentError), + component.NewStatusEvent(component.StatusFatalError), + } + + for _, ev := range events { + name := fmt.Sprintf("transition from: %s to: %s invalid", ev.Status(), component.StatusStopped) + t.Run(name, func(t *testing.T) { + fsm := newFSM(func(*component.StatusEvent) {}) + if ev.Status() != component.StatusStarting { + require.NoError(t, fsm.transition(component.NewStatusEvent(component.StatusStarting))) + } + require.NoError(t, fsm.transition(ev)) + // skipping to stopped is not allowed + err := fsm.transition(component.NewStatusEvent(component.StatusStopped)) + require.ErrorIs(t, err, errInvalidStateTransition) + + // stopping -> stopped is allowed for non-fatal, non-permanent errors + err = fsm.transition(component.NewStatusEvent(component.StatusStopping)) + if ev.Status() == component.StatusPermanentError || ev.Status() == component.StatusFatalError { + require.ErrorIs(t, err, errInvalidStateTransition) + } else { + require.NoError(t, err) + require.NoError(t, fsm.transition(component.NewStatusEvent(component.StatusStopped))) + } + }) + } + +} + +func TestStatusFuncs(t *testing.T) { + id1 := &component.InstanceID{} + id2 := &component.InstanceID{} + + actualStatuses := make(map[*component.InstanceID][]component.Status) + statusFunc := func(id *component.InstanceID, ev *component.StatusEvent) { + actualStatuses[id] = append(actualStatuses[id], ev.Status()) + } + + statuses1 := []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusStopping, + component.StatusStopped, + } + + statuses2 := []component.Status{ + component.StatusStarting, + component.StatusOK, + component.StatusRecoverableError, + component.StatusOK, + component.StatusStopping, + component.StatusStopped, + } + + expectedStatuses := map[*component.InstanceID][]component.Status{ + id1: statuses1, + id2: statuses2, + } + + rep := NewReporter(statusFunc, + func(err error) { + require.NoError(t, err) + }) + comp1Func := NewReportStatusFunc(id1, rep.ReportStatus) + comp2Func := NewReportStatusFunc(id2, rep.ReportStatus) + rep.Ready() + + for _, st := range statuses1 { + comp1Func(component.NewStatusEvent(st)) + } + + for _, st := range statuses2 { + comp2Func(component.NewStatusEvent(st)) + } + + require.Equal(t, expectedStatuses, actualStatuses) +} + +func TestStatusFuncsConcurrent(t *testing.T) { + ids := []*component.InstanceID{{}, {}, {}, {}} + count := 0 + statusFunc := func(*component.InstanceID, *component.StatusEvent) { + count++ + } + rep := NewReporter(statusFunc, + func(err error) { + require.NoError(t, err) + }) + rep.Ready() + + wg := sync.WaitGroup{} + wg.Add(len(ids)) + + for _, id := range ids { + id := id + go func() { + compFn := NewReportStatusFunc(id, rep.ReportStatus) + compFn(component.NewStatusEvent(component.StatusStarting)) + for i := 0; i < 1000; i++ { + compFn(component.NewStatusEvent(component.StatusRecoverableError)) + compFn(component.NewStatusEvent(component.StatusOK)) + } + wg.Done() + }() + } + + wg.Wait() + require.Equal(t, 8004, count) +} + +func TestReporterReady(t *testing.T) { + statusFunc := func(*component.InstanceID, *component.StatusEvent) {} + var err error + rep := NewReporter(statusFunc, + func(e error) { + err = e + }) + id := &component.InstanceID{} + + rep.ReportStatus(id, component.NewStatusEvent(component.StatusStarting)) + require.ErrorIs(t, err, ErrStatusNotReady) + rep.Ready() + + err = nil + rep.ReportStatus(id, component.NewStatusEvent(component.StatusStarting)) + require.NoError(t, err) +} + +func TestReportComponentOKIfStarting(t *testing.T) { + for _, tc := range []struct { + name string + initialStatuses []component.Status + expectedStatuses []component.Status + }{ + { + name: "matching condition: StatusStarting", + initialStatuses: []component.Status{ + component.StatusStarting, + }, + expectedStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + }, + }, + { + name: "non-matching condition StatusOK", + initialStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + }, + expectedStatuses: []component.Status{ + component.StatusStarting, + component.StatusOK, + }, + }, + { + name: "non-matching condition RecoverableError", + initialStatuses: []component.Status{ + component.StatusStarting, + component.StatusRecoverableError, + }, + expectedStatuses: []component.Status{ + component.StatusStarting, + component.StatusRecoverableError, + }, + }, + { + name: "non-matching condition PermanentError", + initialStatuses: []component.Status{ + component.StatusStarting, + component.StatusPermanentError, + }, + expectedStatuses: []component.Status{ + component.StatusStarting, + component.StatusPermanentError, + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + var receivedStatuses []component.Status + + rep := NewReporter( + func(_ *component.InstanceID, ev *component.StatusEvent) { + receivedStatuses = append(receivedStatuses, ev.Status()) + }, + func(err error) { + require.NoError(t, err) + }, + ) + rep.Ready() + + id := &component.InstanceID{} + for _, status := range tc.initialStatuses { + rep.ReportStatus(id, component.NewStatusEvent(status)) + } + + rep.ReportOKIfStarting(id) + + require.Equal(t, tc.expectedStatuses, receivedStatuses) + }) + } +} diff --git a/service/internal/testcomponents/example_connector.go b/service/internal/testcomponents/example_connector.go index ccf6d678d28..75c5145cf7b 100644 --- a/service/internal/testcomponents/example_connector.go +++ b/service/internal/testcomponents/example_connector.go @@ -15,7 +15,7 @@ import ( "go.opentelemetry.io/collector/pdata/ptrace" ) -const connType = "exampleconnector" +var connType = component.MustNewType("exampleconnector") // ExampleConnectorFactory is factory for ExampleConnector. var ExampleConnectorFactory = connector.NewFactory( @@ -36,7 +36,7 @@ var ExampleConnectorFactory = connector.NewFactory( ) var MockForwardConnectorFactory = connector.NewFactory( - "mockforward", + component.MustNewType("mockforward"), createExampleConnectorDefaultConfig, connector.WithTracesToTraces(createExampleTracesToTraces, component.StabilityLevelDevelopment), connector.WithMetricsToMetrics(createExampleMetricsToMetrics, component.StabilityLevelDevelopment), @@ -47,69 +47,78 @@ func createExampleConnectorDefaultConfig() component.Config { return &struct{}{} } -func createExampleTracesToTraces(_ context.Context, _ connector.CreateSettings, _ component.Config, traces consumer.Traces) (connector.Traces, error) { +func createExampleTracesToTraces(_ context.Context, set connector.CreateSettings, _ component.Config, traces consumer.Traces) (connector.Traces, error) { return &ExampleConnector{ ConsumeTracesFunc: traces.ConsumeTraces, + mutatesData: set.ID.Name() == "mutate", }, nil } -func createExampleTracesToMetrics(_ context.Context, _ connector.CreateSettings, _ component.Config, metrics consumer.Metrics) (connector.Traces, error) { +func createExampleTracesToMetrics(_ context.Context, set connector.CreateSettings, _ component.Config, metrics consumer.Metrics) (connector.Traces, error) { return &ExampleConnector{ ConsumeTracesFunc: func(ctx context.Context, td ptrace.Traces) error { return metrics.ConsumeMetrics(ctx, testdata.GenerateMetrics(td.SpanCount())) }, + mutatesData: set.ID.Name() == "mutate", }, nil } -func createExampleTracesToLogs(_ context.Context, _ connector.CreateSettings, _ component.Config, logs consumer.Logs) (connector.Traces, error) { +func createExampleTracesToLogs(_ context.Context, set connector.CreateSettings, _ component.Config, logs consumer.Logs) (connector.Traces, error) { return &ExampleConnector{ ConsumeTracesFunc: func(ctx context.Context, td ptrace.Traces) error { return logs.ConsumeLogs(ctx, testdata.GenerateLogs(td.SpanCount())) }, + mutatesData: set.ID.Name() == "mutate", }, nil } -func createExampleMetricsToTraces(_ context.Context, _ connector.CreateSettings, _ component.Config, traces consumer.Traces) (connector.Metrics, error) { +func createExampleMetricsToTraces(_ context.Context, set connector.CreateSettings, _ component.Config, traces consumer.Traces) (connector.Metrics, error) { return &ExampleConnector{ ConsumeMetricsFunc: func(ctx context.Context, md pmetric.Metrics) error { return traces.ConsumeTraces(ctx, testdata.GenerateTraces(md.MetricCount())) }, + mutatesData: set.ID.Name() == "mutate", }, nil } -func createExampleMetricsToMetrics(_ context.Context, _ connector.CreateSettings, _ component.Config, metrics consumer.Metrics) (connector.Metrics, error) { +func createExampleMetricsToMetrics(_ context.Context, set connector.CreateSettings, _ component.Config, metrics consumer.Metrics) (connector.Metrics, error) { return &ExampleConnector{ ConsumeMetricsFunc: metrics.ConsumeMetrics, + mutatesData: set.ID.Name() == "mutate", }, nil } -func createExampleMetricsToLogs(_ context.Context, _ connector.CreateSettings, _ component.Config, logs consumer.Logs) (connector.Metrics, error) { +func createExampleMetricsToLogs(_ context.Context, set connector.CreateSettings, _ component.Config, logs consumer.Logs) (connector.Metrics, error) { return &ExampleConnector{ ConsumeMetricsFunc: func(ctx context.Context, md pmetric.Metrics) error { return logs.ConsumeLogs(ctx, testdata.GenerateLogs(md.MetricCount())) }, + mutatesData: set.ID.Name() == "mutate", }, nil } -func createExampleLogsToTraces(_ context.Context, _ connector.CreateSettings, _ component.Config, traces consumer.Traces) (connector.Logs, error) { +func createExampleLogsToTraces(_ context.Context, set connector.CreateSettings, _ component.Config, traces consumer.Traces) (connector.Logs, error) { return &ExampleConnector{ ConsumeLogsFunc: func(ctx context.Context, ld plog.Logs) error { return traces.ConsumeTraces(ctx, testdata.GenerateTraces(ld.LogRecordCount())) }, + mutatesData: set.ID.Name() == "mutate", }, nil } -func createExampleLogsToMetrics(_ context.Context, _ connector.CreateSettings, _ component.Config, metrics consumer.Metrics) (connector.Logs, error) { +func createExampleLogsToMetrics(_ context.Context, set connector.CreateSettings, _ component.Config, metrics consumer.Metrics) (connector.Logs, error) { return &ExampleConnector{ ConsumeLogsFunc: func(ctx context.Context, ld plog.Logs) error { return metrics.ConsumeMetrics(ctx, testdata.GenerateMetrics(ld.LogRecordCount())) }, + mutatesData: set.ID.Name() == "mutate", }, nil } -func createExampleLogsToLogs(_ context.Context, _ connector.CreateSettings, _ component.Config, logs consumer.Logs) (connector.Logs, error) { +func createExampleLogsToLogs(_ context.Context, set connector.CreateSettings, _ component.Config, logs consumer.Logs) (connector.Logs, error) { return &ExampleConnector{ ConsumeLogsFunc: logs.ConsumeLogs, + mutatesData: set.ID.Name() == "mutate", }, nil } @@ -118,8 +127,9 @@ type ExampleConnector struct { consumer.ConsumeTracesFunc consumer.ConsumeMetricsFunc consumer.ConsumeLogsFunc + mutatesData bool } func (c *ExampleConnector) Capabilities() consumer.Capabilities { - return consumer.Capabilities{MutatesData: false} + return consumer.Capabilities{MutatesData: c.mutatesData} } diff --git a/service/internal/testcomponents/example_exporter.go b/service/internal/testcomponents/example_exporter.go index 7c5f512d361..653a2ad4a47 100644 --- a/service/internal/testcomponents/example_exporter.go +++ b/service/internal/testcomponents/example_exporter.go @@ -14,14 +14,13 @@ import ( "go.opentelemetry.io/collector/pdata/ptrace" ) -const ( - typeStr = "exampleexporter" - stability = component.StabilityLevelDevelopment -) +var testType = component.MustNewType("exampleexporter") + +const stability = component.StabilityLevelDevelopment // ExampleExporterFactory is factory for ExampleExporter. var ExampleExporterFactory = exporter.NewFactory( - typeStr, + testType, createExporterDefaultConfig, exporter.WithTraces(createTracesExporter, stability), exporter.WithMetrics(createMetricsExporter, stability), diff --git a/service/internal/testcomponents/example_processor.go b/service/internal/testcomponents/example_processor.go index 8189264b5c3..9f73611853b 100644 --- a/service/internal/testcomponents/example_processor.go +++ b/service/internal/testcomponents/example_processor.go @@ -11,7 +11,7 @@ import ( "go.opentelemetry.io/collector/processor" ) -const procType = "exampleprocessor" +var procType = component.MustNewType("exampleprocessor") // ExampleProcessorFactory is factory for ExampleProcessor. var ExampleProcessorFactory = processor.NewFactory( diff --git a/service/internal/testcomponents/example_receiver.go b/service/internal/testcomponents/example_receiver.go index e59d9cb67bb..34b0372b03b 100644 --- a/service/internal/testcomponents/example_receiver.go +++ b/service/internal/testcomponents/example_receiver.go @@ -11,7 +11,7 @@ import ( "go.opentelemetry.io/collector/receiver" ) -const receiverType = component.Type("examplereceiver") +var receiverType = component.MustNewType("examplereceiver") // ExampleReceiverFactory is factory for ExampleReceiver. var ExampleReceiverFactory = receiver.NewFactory( diff --git a/service/internal/testcomponents/example_router.go b/service/internal/testcomponents/example_router.go index 67d97dbebcb..3eafbf13cb6 100644 --- a/service/internal/testcomponents/example_router.go +++ b/service/internal/testcomponents/example_router.go @@ -14,7 +14,7 @@ import ( "go.opentelemetry.io/collector/pdata/ptrace" ) -const routerType = "examplerouter" +var routerType = component.MustNewType("examplerouter") // ExampleRouterFactory is factory for ExampleRouter. var ExampleRouterFactory = connector.NewFactory( @@ -42,7 +42,7 @@ func createExampleRouterDefaultConfig() component.Config { func createExampleTracesRouter(_ context.Context, _ connector.CreateSettings, cfg component.Config, traces consumer.Traces) (connector.Traces, error) { c := cfg.(ExampleRouterConfig) - r := traces.(connector.TracesRouter) + r := traces.(connector.TracesRouterAndConsumer) left, _ := r.Consumer(c.Traces.Left) right, _ := r.Consumer(c.Traces.Right) return &ExampleRouter{ @@ -53,7 +53,7 @@ func createExampleTracesRouter(_ context.Context, _ connector.CreateSettings, cf func createExampleMetricsRouter(_ context.Context, _ connector.CreateSettings, cfg component.Config, metrics consumer.Metrics) (connector.Metrics, error) { c := cfg.(ExampleRouterConfig) - r := metrics.(connector.MetricsRouter) + r := metrics.(connector.MetricsRouterAndConsumer) left, _ := r.Consumer(c.Metrics.Left) right, _ := r.Consumer(c.Metrics.Right) return &ExampleRouter{ @@ -64,7 +64,7 @@ func createExampleMetricsRouter(_ context.Context, _ connector.CreateSettings, c func createExampleLogsRouter(_ context.Context, _ connector.CreateSettings, cfg component.Config, logs consumer.Logs) (connector.Logs, error) { c := cfg.(ExampleRouterConfig) - r := logs.(connector.LogsRouter) + r := logs.(connector.LogsRouterAndConsumer) left, _ := r.Consumer(c.Logs.Left) right, _ := r.Consumer(c.Logs.Right) return &ExampleRouter{ diff --git a/service/internal/testcomponents/example_router_test.go b/service/internal/testcomponents/example_router_test.go index bcf4f5b97b4..23f94854b2a 100644 --- a/service/internal/testcomponents/example_router_test.go +++ b/service/internal/testcomponents/example_router_test.go @@ -11,10 +11,10 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/connector" "go.opentelemetry.io/collector/connector/connectortest" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" - "go.opentelemetry.io/collector/internal/fanoutconsumer" "go.opentelemetry.io/collector/internal/testdata" ) @@ -31,8 +31,8 @@ func TestExampleRouter(t *testing.T) { } func TestTracesRouter(t *testing.T) { - leftID := component.NewIDWithName("sink", "left") - rightID := component.NewIDWithName("sink", "right") + leftID := component.MustNewIDWithName("sink", "left") + rightID := component.MustNewIDWithName("sink", "right") sinkLeft := new(consumertest.TracesSink) sinkRight := new(consumertest.TracesSink) @@ -40,7 +40,7 @@ func TestTracesRouter(t *testing.T) { // The service will build a router to give to every connector. // Many connectors will just call router.ConsumeTraces, // but some implementation will call RouteTraces instead. - router := fanoutconsumer.NewTracesRouter( + router := connector.NewTracesRouter( map[component.ID]consumer.Traces{ leftID: sinkLeft, rightID: sinkRight, @@ -70,8 +70,8 @@ func TestTracesRouter(t *testing.T) { } func TestMetricsRouter(t *testing.T) { - leftID := component.NewIDWithName("sink", "left") - rightID := component.NewIDWithName("sink", "right") + leftID := component.MustNewIDWithName("sink", "left") + rightID := component.MustNewIDWithName("sink", "right") sinkLeft := new(consumertest.MetricsSink) sinkRight := new(consumertest.MetricsSink) @@ -79,7 +79,7 @@ func TestMetricsRouter(t *testing.T) { // The service will build a router to give to every connector. // Many connectors will just call router.ConsumeMetrics, // but some implementation will call RouteMetrics instead. - router := fanoutconsumer.NewMetricsRouter( + router := connector.NewMetricsRouter( map[component.ID]consumer.Metrics{ leftID: sinkLeft, rightID: sinkRight, @@ -109,8 +109,8 @@ func TestMetricsRouter(t *testing.T) { } func TestLogsRouter(t *testing.T) { - leftID := component.NewIDWithName("sink", "left") - rightID := component.NewIDWithName("sink", "right") + leftID := component.MustNewIDWithName("sink", "left") + rightID := component.MustNewIDWithName("sink", "right") sinkLeft := new(consumertest.LogsSink) sinkRight := new(consumertest.LogsSink) @@ -118,7 +118,7 @@ func TestLogsRouter(t *testing.T) { // The service will build a router to give to every connector. // Many connectors will just call router.ConsumeLogs, // but some implementation will call RouteLogs instead. - router := fanoutconsumer.NewLogsRouter( + router := connector.NewLogsRouter( map[component.ID]consumer.Logs{ leftID: sinkLeft, rightID: sinkRight, diff --git a/service/internal/testcomponents/package_test.go b/service/internal/testcomponents/package_test.go new file mode 100644 index 00000000000..5bdec34a7bd --- /dev/null +++ b/service/internal/testcomponents/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package testcomponents + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/service/internal/testcomponents/stateful_component.go b/service/internal/testcomponents/stateful_component.go index ea05b947526..85c8db869dd 100644 --- a/service/internal/testcomponents/stateful_component.go +++ b/service/internal/testcomponents/stateful_component.go @@ -22,12 +22,12 @@ func (cs *componentState) Stopped() bool { return cs.stopped } -func (cs *componentState) Start(_ context.Context, _ component.Host) error { +func (cs *componentState) Start(context.Context, component.Host) error { cs.started = true return nil } -func (cs *componentState) Shutdown(_ context.Context) error { +func (cs *componentState) Shutdown(context.Context) error { cs.stopped = true return nil } diff --git a/service/internal/zpages/package_test.go b/service/internal/zpages/package_test.go new file mode 100644 index 00000000000..5e3b5178ec5 --- /dev/null +++ b/service/internal/zpages/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package zpages + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/service/pipelines/config_test.go b/service/pipelines/config_test.go index e08dff3741a..7ad94d5ab3f 100644 --- a/service/pipelines/config_test.go +++ b/service/pipelines/config_test.go @@ -28,7 +28,7 @@ func TestConfigValidate(t *testing.T) { name: "duplicate-processor-reference", cfgFn: func() Config { cfg := generateConfig() - pipe := cfg[component.NewID("traces")] + pipe := cfg[component.MustNewID("traces")] pipe.Processors = append(pipe.Processors, pipe.Processors...) return cfg }, @@ -38,7 +38,7 @@ func TestConfigValidate(t *testing.T) { name: "missing-pipeline-receivers", cfgFn: func() Config { cfg := generateConfig() - cfg[component.NewID("traces")].Receivers = nil + cfg[component.MustNewID("traces")].Receivers = nil return cfg }, expected: fmt.Errorf(`pipeline "traces": %w`, errMissingServicePipelineReceivers), @@ -47,7 +47,7 @@ func TestConfigValidate(t *testing.T) { name: "missing-pipeline-exporters", cfgFn: func() Config { cfg := generateConfig() - cfg[component.NewID("traces")].Exporters = nil + cfg[component.MustNewID("traces")].Exporters = nil return cfg }, expected: fmt.Errorf(`pipeline "traces": %w`, errMissingServicePipelineExporters), @@ -63,10 +63,10 @@ func TestConfigValidate(t *testing.T) { name: "invalid-service-pipeline-type", cfgFn: func() Config { cfg := generateConfig() - cfg[component.NewID("wrongtype")] = &PipelineConfig{ - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, + cfg[component.MustNewID("wrongtype")] = &PipelineConfig{ + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop")}, } return cfg }, @@ -84,10 +84,10 @@ func TestConfigValidate(t *testing.T) { func generateConfig() Config { return map[component.ID]*PipelineConfig{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.MustNewID("nop")}, + Processors: []component.ID{component.MustNewID("nop")}, + Exporters: []component.ID{component.MustNewID("nop")}, }, } } diff --git a/service/pipelines/package_test.go b/service/pipelines/package_test.go new file mode 100644 index 00000000000..6ae41a8bb59 --- /dev/null +++ b/service/pipelines/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package pipelines + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/service/service.go b/service/service.go index ed9540ec948..febff396417 100644 --- a/service/service.go +++ b/service/service.go @@ -5,13 +5,11 @@ package service // import "go.opentelemetry.io/collector/service" import ( "context" + "errors" "fmt" "runtime" - "github.com/google/uuid" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric/noop" - "go.opentelemetry.io/otel/sdk/resource" + sdkresource "go.opentelemetry.io/otel/sdk/resource" "go.uber.org/multierr" "go.uber.org/zap" @@ -21,14 +19,17 @@ import ( "go.opentelemetry.io/collector/connector" "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/extension" + "go.opentelemetry.io/collector/internal/localhostgate" "go.opentelemetry.io/collector/internal/obsreportconfig" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/processor" "go.opentelemetry.io/collector/receiver" - semconv "go.opentelemetry.io/collector/semconv/v1.18.0" "go.opentelemetry.io/collector/service/extensions" "go.opentelemetry.io/collector/service/internal/graph" "go.opentelemetry.io/collector/service/internal/proctelemetry" + "go.opentelemetry.io/collector/service/internal/resource" + "go.opentelemetry.io/collector/service/internal/servicetelemetry" + "go.opentelemetry.io/collector/service/internal/status" "go.opentelemetry.io/collector/service/telemetry" ) @@ -60,26 +61,17 @@ type Settings struct { // LoggingOptions provides a way to change behavior of zap logging. LoggingOptions []zap.Option - - // For testing purpose only. - useOtel *bool } // Service represents the implementation of a component.Host. type Service struct { - buildInfo component.BuildInfo - telemetry *telemetry.Telemetry - telemetrySettings component.TelemetrySettings - host *serviceHost - telemetryInitializer *telemetryInitializer - collectorConf *confmap.Conf + buildInfo component.BuildInfo + telemetrySettings servicetelemetry.TelemetrySettings + host *serviceHost + collectorConf *confmap.Conf } func New(ctx context.Context, set Settings, cfg Config) (*Service, error) { - useOtel := obsreportconfig.UseOtelForInternalMetricsfeatureGate.IsEnabled() - if set.useOtel != nil { - useOtel = *set.useOtel - } disableHighCard := obsreportconfig.DisableHighCardinalityMetricsfeatureGate.IsEnabled() extendedConfig := obsreportconfig.UseOtelWithSDKConfigurationForInternalTelemetryFeatureGate.IsEnabled() srv := &Service{ @@ -93,40 +85,48 @@ func New(ctx context.Context, set Settings, cfg Config) (*Service, error) { buildInfo: set.BuildInfo, asyncErrorChannel: set.AsyncErrorChannel, }, - telemetryInitializer: newColTelemetry(useOtel, disableHighCard, extendedConfig), - collectorConf: set.CollectorConf, + collectorConf: set.CollectorConf, } - var err error - srv.telemetry, err = telemetry.New(ctx, telemetry.Settings{ZapOptions: set.LoggingOptions}, cfg.Telemetry) + tel, err := telemetry.New(ctx, telemetry.Settings{BuildInfo: set.BuildInfo, ZapOptions: set.LoggingOptions}, cfg.Telemetry) if err != nil { return nil, fmt.Errorf("failed to get logger: %w", err) } - res := buildResource(set.BuildInfo, cfg.Telemetry) + res := resource.New(set.BuildInfo, cfg.Telemetry.Resource) pcommonRes := pdataFromSdk(res) - srv.telemetrySettings = component.TelemetrySettings{ - Logger: srv.telemetry.Logger(), - TracerProvider: srv.telemetry.TracerProvider(), - MeterProvider: noop.NewMeterProvider(), + logger := tel.Logger() + mp, err := newMeterProvider( + meterProviderSettings{ + res: res, + logger: logger, + cfg: cfg.Telemetry.Metrics, + asyncErrorChannel: set.AsyncErrorChannel, + }, + disableHighCard, + extendedConfig, + ) + if err != nil { + return nil, fmt.Errorf("failed to create metric provider: %w", err) + } + srv.telemetrySettings = servicetelemetry.TelemetrySettings{ + Logger: logger, + MeterProvider: mp, + TracerProvider: tel.TracerProvider(), MetricsLevel: cfg.Telemetry.Metrics.Level, - // Construct telemetry attributes from build info and config's resource attributes. Resource: pcommonRes, + Status: status.NewReporter(srv.host.notifyComponentStatusChange, func(err error) { + if errors.Is(err, status.ErrStatusNotReady) { + logger.Warn("Invalid transition", zap.Error(err)) + } + // ignore other errors as they represent invalid state transitions and are considered benign. + }), } - if err = srv.telemetryInitializer.init(res, srv.telemetrySettings, cfg.Telemetry, set.AsyncErrorChannel); err != nil { - return nil, fmt.Errorf("failed to initialize telemetry: %w", err) - } - srv.telemetrySettings.MeterProvider = srv.telemetryInitializer.mp - srv.telemetrySettings.TracerProvider = srv.telemetryInitializer.tp - // process the configuration and initialize the pipeline if err = srv.initExtensionsAndPipeline(ctx, set, cfg); err != nil { - // If pipeline initialization fails then shut down the telemetry server - if shutdownErr := srv.telemetryInitializer.shutdown(); shutdownErr != nil { - err = multierr.Append(err, fmt.Errorf("failed to shutdown collector telemetry: %w", shutdownErr)) - } - + // If pipeline initialization fails then shut down telemetry + err = multierr.Append(err, srv.shutdownTelemetry(ctx)) return nil, err } @@ -134,12 +134,20 @@ func New(ctx context.Context, set Settings, cfg Config) (*Service, error) { } // Start starts the extensions and pipelines. If Start fails Shutdown should be called to ensure a clean state. +// Start does the following steps in order: +// 1. Start all extensions. +// 2. Notify extensions about Collector configuration +// 3. Start all pipelines. +// 4. Notify extensions that the pipeline is ready. func (srv *Service) Start(ctx context.Context) error { srv.telemetrySettings.Logger.Info("Starting "+srv.buildInfo.Command+"...", zap.String("Version", srv.buildInfo.Version), zap.Int("NumCPU", runtime.NumCPU()), ) + // enable status reporting + srv.telemetrySettings.Status.Ready() + if err := srv.host.serviceExtensions.Start(ctx, srv.host); err != nil { return fmt.Errorf("failed to start extensions: %w", err) } @@ -159,9 +167,37 @@ func (srv *Service) Start(ctx context.Context) error { } srv.telemetrySettings.Logger.Info("Everything is ready. Begin running and processing data.") + localhostgate.LogAboutUseLocalHostAsDefault(srv.telemetrySettings.Logger) return nil } +func (srv *Service) shutdownTelemetry(ctx context.Context) error { + // The metric.MeterProvider and trace.TracerProvider interfaces do not have a Shutdown method. + // To shutdown the providers we try to cast to this interface, which matches the type signature used in the SDK. + type shutdownable interface { + Shutdown(context.Context) error + } + + var err error + if prov, ok := srv.telemetrySettings.MeterProvider.(shutdownable); ok { + if shutdownErr := prov.Shutdown(ctx); shutdownErr != nil { + err = multierr.Append(err, fmt.Errorf("failed to shutdown meter provider: %w", shutdownErr)) + } + } + + if prov, ok := srv.telemetrySettings.TracerProvider.(shutdownable); ok { + if shutdownErr := prov.Shutdown(ctx); shutdownErr != nil { + err = multierr.Append(err, fmt.Errorf("failed to shutdown tracer provider: %w", shutdownErr)) + } + } + return err +} + +// Shutdown the service. Shutdown will do the following steps in order: +// 1. Notify extensions that the pipeline is shutting down. +// 2. Shutdown all pipelines. +// 3. Shutdown all extensions. +// 4. Shutdown telemetry. func (srv *Service) Shutdown(ctx context.Context) error { // Accumulate errors and proceed with shutting down remaining components. var errs error @@ -183,13 +219,8 @@ func (srv *Service) Shutdown(ctx context.Context) error { srv.telemetrySettings.Logger.Info("Shutdown complete.") - if err := srv.telemetry.Shutdown(ctx); err != nil { - errs = multierr.Append(errs, fmt.Errorf("failed to shutdown telemetry: %w", err)) - } + errs = multierr.Append(errs, srv.shutdownTelemetry(ctx)) - if err := srv.telemetryInitializer.shutdown(); err != nil { - errs = multierr.Append(errs, fmt.Errorf("failed to shutdown collector telemetry: %w", err)) - } return errs } @@ -220,7 +251,7 @@ func (srv *Service) initExtensionsAndPipeline(ctx context.Context, set Settings, if cfg.Telemetry.Metrics.Level != configtelemetry.LevelNone && cfg.Telemetry.Metrics.Address != "" { // The process telemetry initialization requires the ballast size, which is available after the extensions are initialized. - if err = proctelemetry.RegisterProcessMetrics(srv.telemetryInitializer.ocRegistry, srv.telemetryInitializer.mp, obsreportconfig.UseOtelForInternalMetricsfeatureGate.IsEnabled(), getBallastSize(srv.host)); err != nil { + if err = proctelemetry.RegisterProcessMetrics(srv.telemetrySettings.MeterProvider, getBallastSize(srv.host)); err != nil { return fmt.Errorf("failed to register process metrics: %w", err) } } @@ -243,37 +274,7 @@ func getBallastSize(host component.Host) uint64 { return 0 } -func buildResource(buildInfo component.BuildInfo, cfg telemetry.Config) *resource.Resource { - var telAttrs []attribute.KeyValue - - for k, v := range cfg.Resource { - // nil value indicates that the attribute should not be included in the telemetry. - if v != nil { - telAttrs = append(telAttrs, attribute.String(k, *v)) - } - } - - if _, ok := cfg.Resource[semconv.AttributeServiceName]; !ok { - // AttributeServiceName is not specified in the config. Use the default service name. - telAttrs = append(telAttrs, attribute.String(semconv.AttributeServiceName, buildInfo.Command)) - } - - if _, ok := cfg.Resource[semconv.AttributeServiceInstanceID]; !ok { - // AttributeServiceInstanceID is not specified in the config. Auto-generate one. - instanceUUID, _ := uuid.NewRandom() - instanceID := instanceUUID.String() - telAttrs = append(telAttrs, attribute.String(semconv.AttributeServiceInstanceID, instanceID)) - } - - if _, ok := cfg.Resource[semconv.AttributeServiceVersion]; !ok { - // AttributeServiceVersion is not specified in the config. Use the actual - // build version. - telAttrs = append(telAttrs, attribute.String(semconv.AttributeServiceVersion, buildInfo.Version)) - } - return resource.NewWithAttributes(semconv.SchemaURL, telAttrs...) -} - -func pdataFromSdk(res *resource.Resource) pcommon.Resource { +func pdataFromSdk(res *sdkresource.Resource) pcommon.Resource { // pcommon.NewResource is the best way to generate a new resource currently and is safe to use outside of tests. // Because the resource is signal agnostic, and we need a net new resource, not an existing one, this is the only // method of creating it without exposing internal packages. diff --git a/service/service_test.go b/service/service_test.go index 2a3ec346d65..c538dc0027e 100644 --- a/service/service_test.go +++ b/service/service_test.go @@ -168,6 +168,11 @@ func ownMetricsTestCases() []ownMetricsTestCase { }} } +var ( + nopType = component.MustNewType("nop") + wrongType = component.MustNewType("wrong") +) + func TestServiceGetFactory(t *testing.T) { set := newNopSettings() srv, err := New(context.Background(), set, newNopConfig()) @@ -178,23 +183,23 @@ func TestServiceGetFactory(t *testing.T) { assert.NoError(t, srv.Shutdown(context.Background())) }) - assert.Nil(t, srv.host.GetFactory(component.KindReceiver, "wrongtype")) - assert.Equal(t, set.Receivers.Factory("nop"), srv.host.GetFactory(component.KindReceiver, "nop")) + assert.Nil(t, srv.host.GetFactory(component.KindReceiver, wrongType)) + assert.Equal(t, set.Receivers.Factory(nopType), srv.host.GetFactory(component.KindReceiver, nopType)) - assert.Nil(t, srv.host.GetFactory(component.KindProcessor, "wrongtype")) - assert.Equal(t, set.Processors.Factory("nop"), srv.host.GetFactory(component.KindProcessor, "nop")) + assert.Nil(t, srv.host.GetFactory(component.KindProcessor, wrongType)) + assert.Equal(t, set.Processors.Factory(nopType), srv.host.GetFactory(component.KindProcessor, nopType)) - assert.Nil(t, srv.host.GetFactory(component.KindExporter, "wrongtype")) - assert.Equal(t, set.Exporters.Factory("nop"), srv.host.GetFactory(component.KindExporter, "nop")) + assert.Nil(t, srv.host.GetFactory(component.KindExporter, wrongType)) + assert.Equal(t, set.Exporters.Factory(nopType), srv.host.GetFactory(component.KindExporter, nopType)) - assert.Nil(t, srv.host.GetFactory(component.KindConnector, "wrongtype")) - assert.Equal(t, set.Connectors.Factory("nop"), srv.host.GetFactory(component.KindConnector, "nop")) + assert.Nil(t, srv.host.GetFactory(component.KindConnector, wrongType)) + assert.Equal(t, set.Connectors.Factory(nopType), srv.host.GetFactory(component.KindConnector, nopType)) - assert.Nil(t, srv.host.GetFactory(component.KindExtension, "wrongtype")) - assert.Equal(t, set.Extensions.Factory("nop"), srv.host.GetFactory(component.KindExtension, "nop")) + assert.Nil(t, srv.host.GetFactory(component.KindExtension, wrongType)) + assert.Equal(t, set.Extensions.Factory(nopType), srv.host.GetFactory(component.KindExtension, nopType)) // Try retrieve non existing component.Kind. - assert.Nil(t, srv.host.GetFactory(42, "nop")) + assert.Nil(t, srv.host.GetFactory(42, nopType)) } func TestServiceGetExtensions(t *testing.T) { @@ -209,7 +214,7 @@ func TestServiceGetExtensions(t *testing.T) { extMap := srv.host.GetExtensions() assert.Len(t, extMap, 1) - assert.Contains(t, extMap, component.NewID("nop")) + assert.Contains(t, extMap, component.NewID(nopType)) } func TestServiceGetExporters(t *testing.T) { @@ -224,18 +229,18 @@ func TestServiceGetExporters(t *testing.T) { expMap := srv.host.GetExporters() assert.Len(t, expMap, 3) assert.Len(t, expMap[component.DataTypeTraces], 1) - assert.Contains(t, expMap[component.DataTypeTraces], component.NewID("nop")) + assert.Contains(t, expMap[component.DataTypeTraces], component.NewID(nopType)) assert.Len(t, expMap[component.DataTypeMetrics], 1) - assert.Contains(t, expMap[component.DataTypeMetrics], component.NewID("nop")) + assert.Contains(t, expMap[component.DataTypeMetrics], component.NewID(nopType)) assert.Len(t, expMap[component.DataTypeLogs], 1) - assert.Contains(t, expMap[component.DataTypeLogs], component.NewID("nop")) + assert.Contains(t, expMap[component.DataTypeLogs], component.NewID(nopType)) } // TestServiceTelemetryCleanupOnError tests that if newService errors due to an invalid config telemetry is cleaned up // and another service with a valid config can be started right after. func TestServiceTelemetryCleanupOnError(t *testing.T) { invalidCfg := newNopConfig() - invalidCfg.Pipelines[component.NewID("traces")].Processors[0] = component.NewID("invalid") + invalidCfg.Pipelines[component.MustNewID("traces")].Processors[0] = component.MustNewID("invalid") // Create a service with an invalid config and expect an error _, err := New(context.Background(), newNopSettings(), invalidCfg) require.Error(t, err) @@ -246,26 +251,18 @@ func TestServiceTelemetryCleanupOnError(t *testing.T) { assert.NoError(t, srv.Shutdown(context.Background())) } -func TestServiceTelemetryWithOpenCensusMetrics(t *testing.T) { +func TestServiceTelemetry(t *testing.T) { for _, tc := range ownMetricsTestCases() { t.Run(tc.name, func(t *testing.T) { - testCollectorStartHelper(t, false, tc) + testCollectorStartHelper(t, tc) }) } } -func TestServiceTelemetryWithOpenTelemetryMetrics(t *testing.T) { - for _, tc := range ownMetricsTestCases() { - t.Run(tc.name, func(t *testing.T) { - testCollectorStartHelper(t, true, tc) - }) - } -} - -func testCollectorStartHelper(t *testing.T, useOtel bool, tc ownMetricsTestCase) { +func testCollectorStartHelper(t *testing.T, tc ownMetricsTestCase) { var once sync.Once loggingHookCalled := false - hook := func(entry zapcore.Entry) error { + hook := func(zapcore.Entry) error { once.Do(func() { loggingHookCalled = true }) @@ -278,13 +275,12 @@ func testCollectorStartHelper(t *testing.T, useOtel bool, tc ownMetricsTestCase) set := newNopSettings() set.BuildInfo = component.BuildInfo{Version: "test version", Command: otelCommand} set.Extensions = extension.NewBuilder( - map[component.ID]component.Config{component.NewID("zpages"): &zpagesextension.Config{TCPAddr: confignet.TCPAddr{Endpoint: zpagesAddr}}}, - map[component.Type]extension.Factory{"zpages": zpagesextension.NewFactory()}) + map[component.ID]component.Config{component.MustNewID("zpages"): &zpagesextension.Config{TCPAddr: confignet.TCPAddrConfig{Endpoint: zpagesAddr}}}, + map[component.Type]extension.Factory{component.MustNewType("zpages"): zpagesextension.NewFactory()}) set.LoggingOptions = []zap.Option{zap.Hooks(hook)} - set.useOtel = &useOtel cfg := newNopConfig() - cfg.Extensions = []component.ID{component.NewID("zpages")} + cfg.Extensions = []component.ID{component.MustNewID("zpages")} cfg.Telemetry.Metrics.Address = metricsAddr cfg.Telemetry.Resource = make(map[string]*string) // Include resource attributes under the service::telemetry::resource key. @@ -303,9 +299,7 @@ func testCollectorStartHelper(t *testing.T, useOtel bool, tc ownMetricsTestCase) assert.True(t, loggingHookCalled) assertResourceLabels(t, srv.telemetrySettings.Resource, tc.expectedLabels) - if !useOtel { - assertMetrics(t, metricsAddr, tc.expectedLabels) - } + assertMetrics(t, metricsAddr, tc.expectedLabels) assertZPages(t, zpagesAddr) require.NoError(t, srv.Shutdown(context.Background())) } @@ -362,7 +356,7 @@ func TestExtensionNotificationFailure(t *testing.T) { set := newNopSettings() cfg := newNopConfig() - var extName component.Type = "configWatcher" + var extName = component.MustNewType("configWatcher") configWatcherExtensionFactory := newConfigWatcherExtensionFactory(extName) set.Extensions = extension.NewBuilder( map[component.ID]component.Config{component.NewID(extName): configWatcherExtensionFactory.CreateDefaultConfig()}, @@ -385,7 +379,7 @@ func TestNilCollectorEffectiveConfig(t *testing.T) { set.CollectorConf = nil cfg := newNopConfig() - var extName component.Type = "configWatcher" + var extName = component.MustNewType("configWatcher") configWatcherExtensionFactory := newConfigWatcherExtensionFactory(extName) set.Extensions = extension.NewBuilder( map[component.ID]component.Config{component.NewID(extName): configWatcherExtensionFactory.CreateDefaultConfig()}, @@ -403,6 +397,39 @@ func TestNilCollectorEffectiveConfig(t *testing.T) { require.NoError(t, srv.Shutdown(context.Background())) } +func TestServiceTelemetryLogger(t *testing.T) { + srv, err := New(context.Background(), newNopSettings(), newNopConfig()) + require.NoError(t, err) + + assert.NoError(t, srv.Start(context.Background())) + t.Cleanup(func() { + assert.NoError(t, srv.Shutdown(context.Background())) + }) + assert.NotNil(t, srv.telemetrySettings.Logger) +} + +func TestServiceFatalError(t *testing.T) { + set := newNopSettings() + set.AsyncErrorChannel = make(chan error) + + srv, err := New(context.Background(), set, newNopConfig()) + require.NoError(t, err) + + assert.NoError(t, srv.Start(context.Background())) + t.Cleanup(func() { + assert.NoError(t, srv.Shutdown(context.Background())) + }) + + go func() { + ev := component.NewFatalErrorEvent(assert.AnError) + srv.host.notifyComponentStatusChange(&component.InstanceID{}, ev) + }() + + err = <-srv.host.asyncErrorChannel + + require.ErrorIs(t, err, assert.AnError) +} + func assertResourceLabels(t *testing.T, res pcommon.Resource, expectedLabels map[string]labelValue) { for key, labelValue := range expectedLabels { lookupKey, ok := prometheusToOtelConv[key] @@ -437,13 +464,15 @@ func assertMetrics(t *testing.T, metricsAddr string, expectedLabels map[string]l prefix := "otelcol" for metricName, metricFamily := range parsed { - // require is used here so test fails with a single message. - require.True( - t, - strings.HasPrefix(metricName, prefix), - "expected prefix %q but string starts with %q", - prefix, - metricName[:len(prefix)+1]+"...") + if metricName != "target_info" { + // require is used here so test fails with a single message. + require.True( + t, + strings.HasPrefix(metricName, prefix), + "expected prefix %q but string starts with %q", + prefix, + metricName[:len(prefix)+1]+"...") + } for _, metric := range metricFamily.Metric { labelMap := map[string]string{} @@ -469,8 +498,6 @@ func assertMetrics(t *testing.T, metricsAddr string, expectedLabels map[string]l func assertZPages(t *testing.T, zpagesAddr string) { paths := []string{ "/debug/tracez", - // TODO: enable this when otel-metrics is used and this page is available. - // "/debug/rpcz", "/debug/pipelinez", "/debug/servicez", "/debug/extensionz", @@ -505,27 +532,27 @@ func newNopSettings() Settings { func newNopConfig() Config { return newNopConfigPipelineConfigs(pipelines.Config{ - component.NewID("traces"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("traces"): { + Receivers: []component.ID{component.NewID(nopType)}, + Processors: []component.ID{component.NewID(nopType)}, + Exporters: []component.ID{component.NewID(nopType)}, }, - component.NewID("metrics"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("metrics"): { + Receivers: []component.ID{component.NewID(nopType)}, + Processors: []component.ID{component.NewID(nopType)}, + Exporters: []component.ID{component.NewID(nopType)}, }, - component.NewID("logs"): { - Receivers: []component.ID{component.NewID("nop")}, - Processors: []component.ID{component.NewID("nop")}, - Exporters: []component.ID{component.NewID("nop")}, + component.MustNewID("logs"): { + Receivers: []component.ID{component.NewID(nopType)}, + Processors: []component.ID{component.NewID(nopType)}, + Exporters: []component.ID{component.NewID(nopType)}, }, }) } func newNopConfigPipelineConfigs(pipelineCfgs pipelines.Config) Config { return Config{ - Extensions: extensions.Config{component.NewID("nop")}, + Extensions: extensions.Config{component.NewID(nopType)}, Pipelines: pipelineCfgs, Telemetry: telemetry.Config{ Logs: telemetry.LogsConfig{ @@ -533,6 +560,8 @@ func newNopConfigPipelineConfigs(pipelineCfgs pipelines.Config) Config { Development: false, Encoding: "console", Sampling: &telemetry.LogsSamplingConfig{ + Enabled: true, + Tick: 10 * time.Second, Initial: 100, Thereafter: 100, }, @@ -552,15 +581,15 @@ func newNopConfigPipelineConfigs(pipelineCfgs pipelines.Config) Config { type configWatcherExtension struct{} -func (comp *configWatcherExtension) Start(_ context.Context, _ component.Host) error { +func (comp *configWatcherExtension) Start(context.Context, component.Host) error { return nil } -func (comp *configWatcherExtension) Shutdown(_ context.Context) error { +func (comp *configWatcherExtension) Shutdown(context.Context) error { return nil } -func (comp *configWatcherExtension) NotifyConfig(_ context.Context, _ *confmap.Conf) error { +func (comp *configWatcherExtension) NotifyConfig(context.Context, *confmap.Conf) error { return errors.New("Failed to resolve config") } @@ -570,7 +599,7 @@ func newConfigWatcherExtensionFactory(name component.Type) extension.Factory { func() component.Config { return &struct{}{} }, - func(ctx context.Context, set extension.CreateSettings, extension component.Config) (extension.Extension, error) { + func(context.Context, extension.CreateSettings, component.Config) (extension.Extension, error) { return &configWatcherExtension{}, nil }, component.StabilityLevelDevelopment, diff --git a/service/telemetry.go b/service/telemetry.go index 70fe22bc637..c7aab098747 100644 --- a/service/telemetry.go +++ b/service/telemetry.go @@ -5,33 +5,21 @@ package service // import "go.opentelemetry.io/collector/service" import ( "context" - "errors" "net" "net/http" "strconv" - "strings" - "unicode" - ocprom "contrib.go.opencensus.io/exporter/prometheus" - "github.com/prometheus/client_golang/prometheus" ocmetric "go.opencensus.io/metric" "go.opencensus.io/metric/metricproducer" - "go.opencensus.io/stats/view" - "go.opentelemetry.io/contrib/propagators/b3" - "go.opentelemetry.io/otel" + "go.opentelemetry.io/contrib/config" "go.opentelemetry.io/otel/metric" noopmetric "go.opentelemetry.io/otel/metric/noop" - "go.opentelemetry.io/otel/propagation" sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" - sdktrace "go.opentelemetry.io/otel/sdk/trace" - "go.opentelemetry.io/otel/trace" "go.uber.org/multierr" "go.uber.org/zap" - "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configtelemetry" - "go.opentelemetry.io/collector/internal/obsreportconfig" "go.opentelemetry.io/collector/service/internal/proctelemetry" "go.opentelemetry.io/collector/service/telemetry" ) @@ -39,103 +27,51 @@ import ( const ( zapKeyTelemetryAddress = "address" zapKeyTelemetryLevel = "level" - - // supported trace propagators - traceContextPropagator = "tracecontext" - b3Propagator = "b3" -) - -var ( - errUnsupportedPropagator = errors.New("unsupported trace propagator") ) -type telemetryInitializer struct { - views []*view.View +type meterProvider struct { + *sdkmetric.MeterProvider ocRegistry *ocmetric.Registry - mp metric.MeterProvider - tp trace.TracerProvider servers []*http.Server - - useOtel bool - disableHighCardinality bool - extendedConfig bool } -func newColTelemetry(useOtel bool, disableHighCardinality bool, extendedConfig bool) *telemetryInitializer { - return &telemetryInitializer{ - mp: noopmetric.NewMeterProvider(), - tp: trace.NewNoopTracerProvider(), - useOtel: useOtel, - disableHighCardinality: disableHighCardinality, - extendedConfig: extendedConfig, - } +type meterProviderSettings struct { + res *resource.Resource + logger *zap.Logger + cfg telemetry.MetricsConfig + asyncErrorChannel chan error } -func (tel *telemetryInitializer) init(res *resource.Resource, settings component.TelemetrySettings, cfg telemetry.Config, asyncErrorChannel chan error) error { - if cfg.Metrics.Level == configtelemetry.LevelNone || (cfg.Metrics.Address == "" && len(cfg.Metrics.Readers) == 0) { - settings.Logger.Info( +func newMeterProvider(set meterProviderSettings, disableHighCardinality bool, extendedConfig bool) (metric.MeterProvider, error) { + if set.cfg.Level == configtelemetry.LevelNone || (set.cfg.Address == "" && len(set.cfg.Readers) == 0) { + set.logger.Info( "Skipping telemetry setup.", - zap.String(zapKeyTelemetryAddress, cfg.Metrics.Address), - zap.String(zapKeyTelemetryLevel, cfg.Metrics.Level.String()), + zap.String(zapKeyTelemetryAddress, set.cfg.Address), + zap.String(zapKeyTelemetryLevel, set.cfg.Level.String()), ) - return nil - } - - settings.Logger.Info("Setting up own telemetry...") - - if tp, err := tel.initTraces(res, cfg); err == nil { - tel.tp = tp - } else { - return err - } - - if tp, err := textMapPropagatorFromConfig(cfg.Traces.Propagators); err == nil { - otel.SetTextMapPropagator(tp) - } else { - return err + return noopmetric.NewMeterProvider(), nil } - return tel.initMetrics(res, settings.Logger, cfg, asyncErrorChannel) -} - -func (tel *telemetryInitializer) initTraces(res *resource.Resource, cfg telemetry.Config) (trace.TracerProvider, error) { - opts := []sdktrace.TracerProviderOption{} - for _, processor := range cfg.Traces.Processors { - sp, err := proctelemetry.InitSpanProcessor(context.Background(), processor) - if err != nil { - return nil, err + set.logger.Info("Setting up own telemetry...") + if len(set.cfg.Address) != 0 { + if extendedConfig { + set.logger.Warn("service::telemetry::metrics::address is being deprecated in favor of service::telemetry::metrics::readers") } - opts = append(opts, sdktrace.WithSpanProcessor(sp)) - } - return proctelemetry.InitTracerProvider(res, opts) -} - -func (tel *telemetryInitializer) initMetrics(res *resource.Resource, logger *zap.Logger, cfg telemetry.Config, asyncErrorChannel chan error) error { - // Initialize the ocRegistry, still used by the process metrics. - tel.ocRegistry = ocmetric.NewRegistry() - if !tel.useOtel && !tel.extendedConfig { - return tel.initOpenCensus(res, logger, cfg.Metrics.Address, cfg.Metrics.Level, asyncErrorChannel) - } - - if len(cfg.Metrics.Address) != 0 { - if tel.extendedConfig { - logger.Warn("service::telemetry::metrics::address is being deprecated in favor of service::telemetry::metrics::readers") - } - host, port, err := net.SplitHostPort(cfg.Metrics.Address) + host, port, err := net.SplitHostPort(set.cfg.Address) if err != nil { - return err + return nil, err } portInt, err := strconv.Atoi(port) if err != nil { - return err + return nil, err } - if cfg.Metrics.Readers == nil { - cfg.Metrics.Readers = []telemetry.MetricReader{} + if set.cfg.Readers == nil { + set.cfg.Readers = []config.MetricReader{} } - cfg.Metrics.Readers = append(cfg.Metrics.Readers, telemetry.MetricReader{ - Pull: &telemetry.PullMetricReader{ - Exporter: telemetry.MetricExporter{ - Prometheus: &telemetry.Prometheus{ + set.cfg.Readers = append(set.cfg.Readers, config.MetricReader{ + Pull: &config.PullMetricReader{ + Exporter: config.MetricExporter{ + Prometheus: &config.Prometheus{ Host: &host, Port: &portInt, }, @@ -144,103 +80,47 @@ func (tel *telemetryInitializer) initMetrics(res *resource.Resource, logger *zap }) } - metricproducer.GlobalManager().AddProducer(tel.ocRegistry) + mp := &meterProvider{ + // Initialize the ocRegistry, still used by the process metrics. + ocRegistry: ocmetric.NewRegistry(), + } + metricproducer.GlobalManager().AddProducer(mp.ocRegistry) opts := []sdkmetric.Option{} - for _, reader := range cfg.Metrics.Readers { + for _, reader := range set.cfg.Readers { // https://github.com/open-telemetry/opentelemetry-collector/issues/8045 - r, server, err := proctelemetry.InitMetricReader(context.Background(), reader, asyncErrorChannel) + r, server, err := proctelemetry.InitMetricReader(context.Background(), reader, set.asyncErrorChannel) if err != nil { - return err + return nil, err } if server != nil { - tel.servers = append(tel.servers, server) - logger.Info( + mp.servers = append(mp.servers, server) + set.logger.Info( "Serving metrics", zap.String(zapKeyTelemetryAddress, server.Addr), - zap.String(zapKeyTelemetryLevel, cfg.Metrics.Level.String()), + zap.String(zapKeyTelemetryLevel, set.cfg.Level.String()), ) } opts = append(opts, sdkmetric.WithReader(r)) } - mp, err := proctelemetry.InitOpenTelemetry(res, opts, tel.disableHighCardinality) - if err != nil { - return err - } - tel.mp = mp - return nil -} - -func (tel *telemetryInitializer) initOpenCensus(res *resource.Resource, logger *zap.Logger, address string, level configtelemetry.Level, asyncErrorChannel chan error) error { - promRegistry := prometheus.NewRegistry() - metricproducer.GlobalManager().AddProducer(tel.ocRegistry) - - tel.views = obsreportconfig.AllViews(level) - if err := view.Register(tel.views...); err != nil { - return err - } - - // Until we can use a generic metrics exporter, default to Prometheus. - opts := ocprom.Options{ - Namespace: "otelcol", - Registry: promRegistry, - } - - opts.ConstLabels = make(map[string]string) - for _, keyValue := range res.Attributes() { - opts.ConstLabels[sanitizePrometheusKey(string(keyValue.Key))] = keyValue.Value.AsString() - } - - pe, err := ocprom.NewExporter(opts) + var err error + mp.MeterProvider, err = proctelemetry.InitOpenTelemetry(set.res, opts, disableHighCardinality) if err != nil { - return err + return nil, err } - - view.RegisterExporter(pe) - - logger.Info( - "Serving Prometheus metrics", - zap.String(zapKeyTelemetryAddress, address), - zap.String(zapKeyTelemetryLevel, level.String()), - ) - tel.servers = append(tel.servers, proctelemetry.InitPrometheusServer(promRegistry, address, asyncErrorChannel)) - return nil + return mp, nil } -func (tel *telemetryInitializer) shutdown() error { - metricproducer.GlobalManager().DeleteProducer(tel.ocRegistry) - view.Unregister(tel.views...) +// 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 { + metricproducer.GlobalManager().DeleteProducer(mp.ocRegistry) var errs error - for _, server := range tel.servers { + for _, server := range mp.servers { if server != nil { errs = multierr.Append(errs, server.Close()) } } - return errs -} - -func sanitizePrometheusKey(str string) string { - runeFilterMap := func(r rune) rune { - if unicode.IsDigit(r) || unicode.IsLetter(r) || r == '_' { - return r - } - return '_' - } - return strings.Map(runeFilterMap, str) -} - -func textMapPropagatorFromConfig(props []string) (propagation.TextMapPropagator, error) { - var textMapPropagators []propagation.TextMapPropagator - for _, prop := range props { - switch prop { - case traceContextPropagator: - textMapPropagators = append(textMapPropagators, propagation.TraceContext{}) - case b3Propagator: - textMapPropagators = append(textMapPropagators, b3.New()) - default: - return nil, errUnsupportedPropagator - } - } - return propagation.NewCompositeTextMapPropagator(textMapPropagators...), nil + return multierr.Append(errs, mp.MeterProvider.Shutdown(ctx)) } diff --git a/service/telemetry/config.go b/service/telemetry/config.go index 514ae03278a..3336fcac578 100644 --- a/service/telemetry/config.go +++ b/service/telemetry/config.go @@ -5,12 +5,12 @@ package telemetry // import "go.opentelemetry.io/collector/service/telemetry" import ( "fmt" + "time" + "go.opentelemetry.io/contrib/config" "go.uber.org/zap/zapcore" "go.opentelemetry.io/collector/config/configtelemetry" - "go.opentelemetry.io/collector/confmap" - "go.opentelemetry.io/collector/internal/obsreportconfig" ) // Config defines the configurable settings for service telemetry. @@ -54,7 +54,14 @@ type LogsConfig struct { // (default = false) DisableStacktrace bool `mapstructure:"disable_stacktrace"` - // Sampling sets a sampling policy. A nil SamplingConfig disables sampling. + // 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. @@ -91,7 +98,14 @@ type LogsConfig struct { // 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 { - Initial int `mapstructure:"initial"` + // 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"` } @@ -110,7 +124,7 @@ type MetricsConfig struct { // Readers allow configuration of metric readers to emit metrics to // any number of supported backends. - Readers []MetricReader `mapstructure:"readers"` + Readers []config.MetricReader `mapstructure:"readers"` } // TracesConfig exposes the common Telemetry configuration for collector's internal spans. @@ -122,7 +136,7 @@ type TracesConfig struct { Propagators []string `mapstructure:"propagators"` // Processors allow configuration of span processors to emit spans to // any number of suported backends. - Processors []SpanProcessor `mapstructure:"processors"` + Processors []config.SpanProcessor `mapstructure:"processors"` } // Validate checks whether the current configuration is valid @@ -134,71 +148,3 @@ func (c *Config) Validate() error { return nil } - -func (sp *SpanProcessor) Unmarshal(conf *confmap.Conf) error { - if !obsreportconfig.UseOtelWithSDKConfigurationForInternalTelemetryFeatureGate.IsEnabled() { - // only unmarshal if feature gate is enabled - return nil - } - - if conf == nil { - return nil - } - - if err := conf.Unmarshal(sp); err != nil { - return fmt.Errorf("invalid span processor configuration: %w", err) - } - - if sp.Batch != nil { - return sp.Batch.Exporter.Validate() - } - return fmt.Errorf("unsupported span processor type %s", conf.AllKeys()) -} - -// Validate checks for valid exporters to be configured for the SpanExporter -func (se *SpanExporter) Validate() error { - if se.Console == nil && se.Otlp == nil { - return fmt.Errorf("invalid exporter configuration") - } - return nil -} - -func (mr *MetricReader) Unmarshal(conf *confmap.Conf) error { - if !obsreportconfig.UseOtelWithSDKConfigurationForInternalTelemetryFeatureGate.IsEnabled() { - // only unmarshal if feature gate is enabled - return nil - } - - if conf == nil { - return nil - } - - if err := conf.Unmarshal(mr); err != nil { - return fmt.Errorf("invalid metric reader configuration: %w", err) - } - - if mr.Pull != nil { - return mr.Pull.Validate() - } - if mr.Periodic != nil { - return mr.Periodic.Validate() - } - - return fmt.Errorf("unsupported metric reader type %s", conf.AllKeys()) -} - -// Validate checks for valid exporters to be configured for the PullMetricReader -func (pmr *PullMetricReader) Validate() error { - if pmr.Exporter.Prometheus == nil { - return fmt.Errorf("invalid exporter configuration") - } - return nil -} - -// Validate checks for valid exporters to be configured for the PeriodicMetricReader -func (pmr *PeriodicMetricReader) Validate() error { - if pmr.Exporter.Otlp == nil && pmr.Exporter.Console == nil { - return fmt.Errorf("invalid exporter configuration") - } - return nil -} diff --git a/service/telemetry/config_test.go b/service/telemetry/config_test.go index 8af1616fb92..5417347c772 100644 --- a/service/telemetry/config_test.go +++ b/service/telemetry/config_test.go @@ -7,12 +7,9 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "go.opentelemetry.io/contrib/config" "go.opentelemetry.io/collector/config/configtelemetry" - "go.opentelemetry.io/collector/confmap" - "go.opentelemetry.io/collector/featuregate" - "go.opentelemetry.io/collector/internal/obsreportconfig" ) func TestLoadConfig(t *testing.T) { @@ -46,8 +43,8 @@ func TestLoadConfig(t *testing.T) { cfg: &Config{ Metrics: MetricsConfig{ Level: configtelemetry.LevelBasic, - Readers: []MetricReader{ - {Pull: &PullMetricReader{}}, + Readers: []config.MetricReader{ + {Pull: &config.PullMetricReader{}}, }, }, }, @@ -66,178 +63,3 @@ func TestLoadConfig(t *testing.T) { }) } } - -// Force the state of feature gate for a test -func setFeatureGateForTest(t testing.TB, gate *featuregate.Gate, enabled bool) func() { - originalValue := gate.IsEnabled() - require.NoError(t, featuregate.GlobalRegistry().Set(gate.ID(), enabled)) - return func() { - require.NoError(t, featuregate.GlobalRegistry().Set(gate.ID(), originalValue)) - } -} - -func TestUnmarshalMetricReaderWithGateOff(t *testing.T) { - defer setFeatureGateForTest(t, obsreportconfig.UseOtelWithSDKConfigurationForInternalTelemetryFeatureGate, false)() - reader := MetricReader{} - assert.NoError(t, reader.Unmarshal(confmap.NewFromStringMap(map[string]any{"invalid": "invalid"}))) -} - -func TestUnmarshalMetricReader(t *testing.T) { - defer setFeatureGateForTest(t, obsreportconfig.UseOtelWithSDKConfigurationForInternalTelemetryFeatureGate, true)() - tests := []struct { - name string - cfg *confmap.Conf - err string - }{ - { - name: "invalid config", - cfg: confmap.NewFromStringMap(map[string]any{"invalid": "invalid"}), - err: "unsupported metric reader type [invalid]", - }, - { - name: "nil config, nothing to do", - }, - { - name: "invalid pull reader type with valid prometheus exporter", - cfg: confmap.NewFromStringMap(map[string]any{"pull/prometheus1": PullMetricReader{ - Exporter: MetricExporter{ - Prometheus: &Prometheus{}, - }, - }}), - err: "unsupported metric reader type [pull/prometheus1]", - }, - { - name: "valid reader type, invalid config", - cfg: confmap.NewFromStringMap(map[string]any{"pull": "garbage"}), - err: "invalid metric reader configuration", - }, - { - name: "valid pull reader type, no exporter", - cfg: confmap.NewFromStringMap(map[string]any{"pull": PullMetricReader{}}), - err: "invalid exporter configuration", - }, - { - name: "valid pull reader type, invalid exporter", - cfg: confmap.NewFromStringMap(map[string]any{"pull": PullMetricReader{ - Exporter: MetricExporter{ - Prometheus: nil, - }, - }}), - err: "invalid exporter configuration", - }, - { - name: "valid pull reader type, valid prometheus exporter", - cfg: confmap.NewFromStringMap(map[string]any{"pull": PullMetricReader{ - Exporter: MetricExporter{ - Prometheus: &Prometheus{}, - }, - }}), - }, - { - name: "valid periodic reader type, valid console exporter", - cfg: confmap.NewFromStringMap(map[string]any{"periodic": PeriodicMetricReader{ - Exporter: MetricExporter{ - Console: Console{}, - }, - }}), - }, - { - name: "valid periodic reader type, invalid console exporter", - cfg: confmap.NewFromStringMap(map[string]any{"periodic": PeriodicMetricReader{ - Exporter: MetricExporter{ - Prometheus: &Prometheus{}, - }, - }}), - err: "invalid exporter configuration", - }, - { - name: "valid periodic reader type, valid otlp exporter", - cfg: confmap.NewFromStringMap(map[string]any{"periodic": PeriodicMetricReader{ - Exporter: MetricExporter{ - Otlp: &OtlpMetric{}, - }, - }}), - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - reader := MetricReader{} - err := reader.Unmarshal(tt.cfg) - if len(tt.err) > 0 { - assert.ErrorContains(t, err, tt.err) - } else { - assert.NoError(t, err) - } - }) - } -} - -func TestUnmarshalSpanProcessorWithGateOff(t *testing.T) { - defer setFeatureGateForTest(t, obsreportconfig.UseOtelWithSDKConfigurationForInternalTelemetryFeatureGate, false)() - sp := SpanProcessor{} - assert.NoError(t, sp.Unmarshal(confmap.NewFromStringMap(map[string]any{"invalid": "invalid"}))) -} - -func TestUnmarshalSpanProcessor(t *testing.T) { - defer setFeatureGateForTest(t, obsreportconfig.UseOtelWithSDKConfigurationForInternalTelemetryFeatureGate, true)() - tests := []struct { - name string - cfg *confmap.Conf - err string - }{ - { - name: "invalid config", - cfg: confmap.NewFromStringMap(map[string]any{"invalid": "invalid"}), - err: "unsupported span processor type [invalid]", - }, - { - name: "nil config, nothing to do", - }, - { - name: "invalid batch processor type with valid console exporter", - cfg: confmap.NewFromStringMap(map[string]any{"thing": BatchSpanProcessor{ - Exporter: SpanExporter{ - Console: Console{}, - }, - }}), - err: "unsupported span processor type [thing]", - }, - { - name: "valid batch processor, invalid config", - cfg: confmap.NewFromStringMap(map[string]any{"batch": "garbage"}), - err: "invalid span processor configuration", - }, - { - name: "valid batch processor, no exporter", - cfg: confmap.NewFromStringMap(map[string]any{"batch": BatchSpanProcessor{}}), - err: "invalid exporter configuration", - }, - { - name: "valid batch processor, valid console exporter", - cfg: confmap.NewFromStringMap(map[string]any{"batch": BatchSpanProcessor{ - Exporter: SpanExporter{ - Console: Console{}, - }, - }}), - }, - { - name: "valid batch processor type, valid otlp exporter", - cfg: confmap.NewFromStringMap(map[string]any{"batch": BatchSpanProcessor{ - Exporter: SpanExporter{ - Otlp: &Otlp{}, - }, - }}), - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - processor := SpanProcessor{} - err := processor.Unmarshal(tt.cfg) - if len(tt.err) > 0 { - assert.ErrorContains(t, err, tt.err) - } else { - assert.NoError(t, err) - } - }) - } -} diff --git a/service/telemetry/generated_config.go b/service/telemetry/generated_config.go deleted file mode 100644 index 340d9aac766..00000000000 --- a/service/telemetry/generated_config.go +++ /dev/null @@ -1,577 +0,0 @@ -// Code generated by github.com/atombender/go-jsonschema, DO NOT EDIT. - -package telemetry - -import ( - "encoding/json" - "fmt" -) - -type Attributes struct { - // ServiceName corresponds to the JSON schema field "service.name". - ServiceName *string `mapstructure:"service.name,omitempty"` -} - -type BatchLogRecordProcessor struct { - // ExportTimeout corresponds to the JSON schema field "export_timeout". - ExportTimeout *int `mapstructure:"export_timeout,omitempty"` - - // Exporter corresponds to the JSON schema field "exporter". - Exporter LogRecordExporter `mapstructure:"exporter"` - - // MaxExportBatchSize corresponds to the JSON schema field - // "max_export_batch_size". - MaxExportBatchSize *int `mapstructure:"max_export_batch_size,omitempty"` - - // MaxQueueSize corresponds to the JSON schema field "max_queue_size". - MaxQueueSize *int `mapstructure:"max_queue_size,omitempty"` - - // ScheduleDelay corresponds to the JSON schema field "schedule_delay". - ScheduleDelay *int `mapstructure:"schedule_delay,omitempty"` -} - -type BatchSpanProcessor struct { - // ExportTimeout corresponds to the JSON schema field "export_timeout". - ExportTimeout *int `mapstructure:"export_timeout,omitempty"` - - // Exporter corresponds to the JSON schema field "exporter". - Exporter SpanExporter `mapstructure:"exporter"` - - // MaxExportBatchSize corresponds to the JSON schema field - // "max_export_batch_size". - MaxExportBatchSize *int `mapstructure:"max_export_batch_size,omitempty"` - - // MaxQueueSize corresponds to the JSON schema field "max_queue_size". - MaxQueueSize *int `mapstructure:"max_queue_size,omitempty"` - - // ScheduleDelay corresponds to the JSON schema field "schedule_delay". - ScheduleDelay *int `mapstructure:"schedule_delay,omitempty"` -} - -type CommonJson map[string]interface{} - -type Console map[string]interface{} - -type Headers map[string]string - -type LogRecordExporter struct { - // Otlp corresponds to the JSON schema field "otlp". - Otlp *Otlp `mapstructure:"otlp,omitempty"` -} - -type LogRecordLimits struct { - // AttributeCountLimit corresponds to the JSON schema field - // "attribute_count_limit". - AttributeCountLimit *int `mapstructure:"attribute_count_limit,omitempty"` - - // AttributeValueLengthLimit corresponds to the JSON schema field - // "attribute_value_length_limit". - AttributeValueLengthLimit *int `mapstructure:"attribute_value_length_limit,omitempty"` -} - -type LogRecordProcessor struct { - // Batch corresponds to the JSON schema field "batch". - Batch *BatchLogRecordProcessor `mapstructure:"batch,omitempty"` - - // Simple corresponds to the JSON schema field "simple". - Simple *SimpleLogRecordProcessor `mapstructure:"simple,omitempty"` -} - -type LoggerProviderJson struct { - // Limits corresponds to the JSON schema field "limits". - Limits *LogRecordLimits `mapstructure:"limits,omitempty"` - - // Processors corresponds to the JSON schema field "processors". - Processors []LogRecordProcessor `mapstructure:"processors,omitempty"` -} - -type MeterProviderJson struct { - // Readers corresponds to the JSON schema field "readers". - Readers []MetricReader `mapstructure:"readers,omitempty"` - - // Views corresponds to the JSON schema field "views". - Views []View `mapstructure:"views,omitempty"` -} - -type MetricExporter struct { - // Console corresponds to the JSON schema field "console". - Console Console `mapstructure:"console,omitempty"` - - // Otlp corresponds to the JSON schema field "otlp". - Otlp *OtlpMetric `mapstructure:"otlp,omitempty"` - - // Prometheus corresponds to the JSON schema field "prometheus". - Prometheus *Prometheus `mapstructure:"prometheus,omitempty"` -} - -type MetricReader struct { - // Periodic corresponds to the JSON schema field "periodic". - Periodic *PeriodicMetricReader `mapstructure:"periodic,omitempty"` - - // Pull corresponds to the JSON schema field "pull". - Pull *PullMetricReader `mapstructure:"pull,omitempty"` -} - -type Otlp struct { - // Certificate corresponds to the JSON schema field "certificate". - Certificate *string `mapstructure:"certificate,omitempty"` - - // ClientCertificate corresponds to the JSON schema field "client_certificate". - ClientCertificate *string `mapstructure:"client_certificate,omitempty"` - - // ClientKey corresponds to the JSON schema field "client_key". - ClientKey *string `mapstructure:"client_key,omitempty"` - - // Compression corresponds to the JSON schema field "compression". - Compression *string `mapstructure:"compression,omitempty"` - - // Endpoint corresponds to the JSON schema field "endpoint". - Endpoint string `mapstructure:"endpoint"` - - // Headers corresponds to the JSON schema field "headers". - Headers Headers `mapstructure:"headers,omitempty"` - - // Protocol corresponds to the JSON schema field "protocol". - Protocol string `mapstructure:"protocol"` - - // Timeout corresponds to the JSON schema field "timeout". - Timeout *int `mapstructure:"timeout,omitempty"` -} - -type OtlpMetric struct { - // Certificate corresponds to the JSON schema field "certificate". - Certificate *string `mapstructure:"certificate,omitempty"` - - // ClientCertificate corresponds to the JSON schema field "client_certificate". - ClientCertificate *string `mapstructure:"client_certificate,omitempty"` - - // ClientKey corresponds to the JSON schema field "client_key". - ClientKey *string `mapstructure:"client_key,omitempty"` - - // Compression corresponds to the JSON schema field "compression". - Compression *string `mapstructure:"compression,omitempty"` - - // DefaultHistogramAggregation corresponds to the JSON schema field - // "default_histogram_aggregation". - DefaultHistogramAggregation *string `mapstructure:"default_histogram_aggregation,omitempty"` - - // Endpoint corresponds to the JSON schema field "endpoint". - Endpoint string `mapstructure:"endpoint"` - - // Headers corresponds to the JSON schema field "headers". - Headers Headers `mapstructure:"headers,omitempty"` - - // Protocol corresponds to the JSON schema field "protocol". - Protocol string `mapstructure:"protocol"` - - // TemporalityPreference corresponds to the JSON schema field - // "temporality_preference". - TemporalityPreference *string `mapstructure:"temporality_preference,omitempty"` - - // Timeout corresponds to the JSON schema field "timeout". - Timeout *int `mapstructure:"timeout,omitempty"` -} - -type PeriodicMetricReader struct { - // Exporter corresponds to the JSON schema field "exporter". - Exporter MetricExporter `mapstructure:"exporter"` - - // Interval corresponds to the JSON schema field "interval". - Interval *int `mapstructure:"interval,omitempty"` - - // Timeout corresponds to the JSON schema field "timeout". - Timeout *int `mapstructure:"timeout,omitempty"` -} - -type Prometheus struct { - // Host corresponds to the JSON schema field "host". - Host *string `mapstructure:"host,omitempty"` - - // Port corresponds to the JSON schema field "port". - Port *int `mapstructure:"port,omitempty"` -} - -type PullMetricReader struct { - // Exporter corresponds to the JSON schema field "exporter". - Exporter MetricExporter `mapstructure:"exporter"` -} - -type ResourceJson struct { - // Attributes corresponds to the JSON schema field "attributes". - Attributes *Attributes `mapstructure:"attributes,omitempty"` -} - -type Sampler struct { - // AlwaysOff corresponds to the JSON schema field "always_off". - AlwaysOff SamplerAlwaysOff `mapstructure:"always_off,omitempty"` - - // AlwaysOn corresponds to the JSON schema field "always_on". - AlwaysOn SamplerAlwaysOn `mapstructure:"always_on,omitempty"` - - // JaegerRemote corresponds to the JSON schema field "jaeger_remote". - JaegerRemote *SamplerJaegerRemote `mapstructure:"jaeger_remote,omitempty"` - - // ParentBased corresponds to the JSON schema field "parent_based". - ParentBased *SamplerParentBased `mapstructure:"parent_based,omitempty"` - - // TraceIdRatioBased corresponds to the JSON schema field "trace_id_ratio_based". - TraceIdRatioBased *SamplerTraceIdRatioBased `mapstructure:"trace_id_ratio_based,omitempty"` -} - -type SamplerAlwaysOff map[string]interface{} - -type SamplerAlwaysOn map[string]interface{} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *BatchSpanProcessor) UnmarshalJSON(b []byte) error { - var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if v, ok := raw["exporter"]; !ok || v == nil { - return fmt.Errorf("field exporter in BatchSpanProcessor: required") - } - type Plain BatchSpanProcessor - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - *j = BatchSpanProcessor(plain) - return nil -} - -type ViewStreamAggregationExplicitBucketHistogram struct { - // Boundaries corresponds to the JSON schema field "boundaries". - Boundaries []float64 `mapstructure:"boundaries,omitempty"` - - // RecordMinMax corresponds to the JSON schema field "record_min_max". - RecordMinMax *bool `mapstructure:"record_min_max,omitempty"` -} - -type ViewStreamAggregationExponentialBucketHistogram struct { - // MaxScale corresponds to the JSON schema field "max_scale". - MaxScale *int `mapstructure:"max_scale,omitempty"` - - // MaxSize corresponds to the JSON schema field "max_size". - MaxSize *int `mapstructure:"max_size,omitempty"` - - // RecordMinMax corresponds to the JSON schema field "record_min_max". - RecordMinMax *bool `mapstructure:"record_min_max,omitempty"` -} - -type ViewStreamAggregation struct { - // Default corresponds to the JSON schema field "default". - Default interface{} `mapstructure:"default,omitempty"` - - // Drop corresponds to the JSON schema field "drop". - Drop interface{} `mapstructure:"drop,omitempty"` - - // ExplicitBucketHistogram corresponds to the JSON schema field - // "explicit_bucket_histogram". - ExplicitBucketHistogram *ViewStreamAggregationExplicitBucketHistogram `mapstructure:"explicit_bucket_histogram,omitempty"` - - // ExponentialBucketHistogram corresponds to the JSON schema field - // "exponential_bucket_histogram". - ExponentialBucketHistogram *ViewStreamAggregationExponentialBucketHistogram `mapstructure:"exponential_bucket_histogram,omitempty"` - - // LastValue corresponds to the JSON schema field "last_value". - LastValue interface{} `mapstructure:"last_value,omitempty"` - - // Sum corresponds to the JSON schema field "sum". - Sum interface{} `mapstructure:"sum,omitempty"` -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *ViewStreamAggregation) UnmarshalJSON(b []byte) error { - var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - type Plain ViewStreamAggregation - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - if plain.Default != nil { - return fmt.Errorf("field %s: must be null", "default") - } - if plain.Drop != nil { - return fmt.Errorf("field %s: must be null", "drop") - } - if plain.LastValue != nil { - return fmt.Errorf("field %s: must be null", "last_value") - } - if plain.Sum != nil { - return fmt.Errorf("field %s: must be null", "sum") - } - *j = ViewStreamAggregation(plain) - return nil -} - -type ViewStream struct { - // Aggregation corresponds to the JSON schema field "aggregation". - Aggregation *ViewStreamAggregation `mapstructure:"aggregation,omitempty"` - - // AttributeKeys corresponds to the JSON schema field "attribute_keys". - AttributeKeys []string `mapstructure:"attribute_keys,omitempty"` - - // Description corresponds to the JSON schema field "description". - Description *string `mapstructure:"description,omitempty"` - - // Name corresponds to the JSON schema field "name". - Name *string `mapstructure:"name,omitempty"` -} - -type View struct { - // Selector corresponds to the JSON schema field "selector". - Selector *ViewSelector `mapstructure:"selector,omitempty"` - - // Stream corresponds to the JSON schema field "stream". - Stream *ViewStream `mapstructure:"stream,omitempty"` -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *PullMetricReader) UnmarshalJSON(b []byte) error { - var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if v, ok := raw["exporter"]; !ok || v == nil { - return fmt.Errorf("field exporter in PullMetricReader: required") - } - type Plain PullMetricReader - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - *j = PullMetricReader(plain) - return nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *Otlp) UnmarshalJSON(b []byte) error { - var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if v, ok := raw["endpoint"]; !ok || v == nil { - return fmt.Errorf("field endpoint in Otlp: required") - } - if v, ok := raw["protocol"]; !ok || v == nil { - return fmt.Errorf("field protocol in Otlp: required") - } - type Plain Otlp - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - *j = Otlp(plain) - return nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *PeriodicMetricReader) UnmarshalJSON(b []byte) error { - var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if v, ok := raw["exporter"]; !ok || v == nil { - return fmt.Errorf("field exporter in PeriodicMetricReader: required") - } - type Plain PeriodicMetricReader - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - *j = PeriodicMetricReader(plain) - return nil -} - -type SpanExporter struct { - // Console corresponds to the JSON schema field "console". - Console Console `mapstructure:"console,omitempty"` - - // Otlp corresponds to the JSON schema field "otlp". - Otlp *Otlp `mapstructure:"otlp,omitempty"` -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *OtlpMetric) UnmarshalJSON(b []byte) error { - var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if v, ok := raw["endpoint"]; !ok || v == nil { - return fmt.Errorf("field endpoint in OtlpMetric: required") - } - if v, ok := raw["protocol"]; !ok || v == nil { - return fmt.Errorf("field protocol in OtlpMetric: required") - } - type Plain OtlpMetric - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - *j = OtlpMetric(plain) - return nil -} - -type ViewSelector struct { - // InstrumentName corresponds to the JSON schema field "instrument_name". - InstrumentName *string `mapstructure:"instrument_name,omitempty"` - - // InstrumentType corresponds to the JSON schema field "instrument_type". - InstrumentType *string `mapstructure:"instrument_type,omitempty"` - - // MeterName corresponds to the JSON schema field "meter_name". - MeterName *string `mapstructure:"meter_name,omitempty"` - - // MeterSchemaUrl corresponds to the JSON schema field "meter_schema_url". - MeterSchemaUrl *string `mapstructure:"meter_schema_url,omitempty"` - - // MeterVersion corresponds to the JSON schema field "meter_version". - MeterVersion *string `mapstructure:"meter_version,omitempty"` -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *BatchLogRecordProcessor) UnmarshalJSON(b []byte) error { - var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if v, ok := raw["exporter"]; !ok || v == nil { - return fmt.Errorf("field exporter in BatchLogRecordProcessor: required") - } - type Plain BatchLogRecordProcessor - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - *j = BatchLogRecordProcessor(plain) - return nil -} - -type SimpleLogRecordProcessor struct { - // Exporter corresponds to the JSON schema field "exporter". - Exporter LogRecordExporter `mapstructure:"exporter"` -} - -type SamplerJaegerRemote struct { - // Endpoint corresponds to the JSON schema field "endpoint". - Endpoint *string `mapstructure:"endpoint,omitempty"` - - // InitialSampler corresponds to the JSON schema field "initial_sampler". - InitialSampler *Sampler `mapstructure:"initial_sampler,omitempty"` - - // Interval corresponds to the JSON schema field "interval". - Interval *int `mapstructure:"interval,omitempty"` -} - -type SamplerParentBased struct { - // LocalParentNotSampled corresponds to the JSON schema field - // "local_parent_not_sampled". - LocalParentNotSampled *Sampler `mapstructure:"local_parent_not_sampled,omitempty"` - - // LocalParentSampled corresponds to the JSON schema field "local_parent_sampled". - LocalParentSampled *Sampler `mapstructure:"local_parent_sampled,omitempty"` - - // RemoteParentNotSampled corresponds to the JSON schema field - // "remote_parent_not_sampled". - RemoteParentNotSampled *Sampler `mapstructure:"remote_parent_not_sampled,omitempty"` - - // RemoteParentSampled corresponds to the JSON schema field - // "remote_parent_sampled". - RemoteParentSampled *Sampler `mapstructure:"remote_parent_sampled,omitempty"` - - // Root corresponds to the JSON schema field "root". - Root *Sampler `mapstructure:"root,omitempty"` -} - -type SamplerTraceIdRatioBased struct { - // Ratio corresponds to the JSON schema field "ratio". - Ratio *float64 `mapstructure:"ratio,omitempty"` -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *SimpleLogRecordProcessor) UnmarshalJSON(b []byte) error { - var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if v, ok := raw["exporter"]; !ok || v == nil { - return fmt.Errorf("field exporter in SimpleLogRecordProcessor: required") - } - type Plain SimpleLogRecordProcessor - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - *j = SimpleLogRecordProcessor(plain) - return nil -} - -type SimpleSpanProcessor struct { - // Exporter corresponds to the JSON schema field "exporter". - Exporter SpanExporter `mapstructure:"exporter"` -} - -// UnmarshalJSON implements json.Unmarshaler. -func (j *SimpleSpanProcessor) UnmarshalJSON(b []byte) error { - var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { - return err - } - if v, ok := raw["exporter"]; !ok || v == nil { - return fmt.Errorf("field exporter in SimpleSpanProcessor: required") - } - type Plain SimpleSpanProcessor - var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { - return err - } - *j = SimpleSpanProcessor(plain) - return nil -} - -type SpanLimits struct { - // AttributeCountLimit corresponds to the JSON schema field - // "attribute_count_limit". - AttributeCountLimit *int `mapstructure:"attribute_count_limit,omitempty"` - - // AttributeValueLengthLimit corresponds to the JSON schema field - // "attribute_value_length_limit". - AttributeValueLengthLimit *int `mapstructure:"attribute_value_length_limit,omitempty"` - - // EventAttributeCountLimit corresponds to the JSON schema field - // "event_attribute_count_limit". - EventAttributeCountLimit *int `mapstructure:"event_attribute_count_limit,omitempty"` - - // EventCountLimit corresponds to the JSON schema field "event_count_limit". - EventCountLimit *int `mapstructure:"event_count_limit,omitempty"` - - // LinkAttributeCountLimit corresponds to the JSON schema field - // "link_attribute_count_limit". - LinkAttributeCountLimit *int `mapstructure:"link_attribute_count_limit,omitempty"` - - // LinkCountLimit corresponds to the JSON schema field "link_count_limit". - LinkCountLimit *int `mapstructure:"link_count_limit,omitempty"` -} - -type SpanProcessor struct { - // Batch corresponds to the JSON schema field "batch". - Batch *BatchSpanProcessor `mapstructure:"batch,omitempty"` - - // Simple corresponds to the JSON schema field "simple". - Simple *SimpleSpanProcessor `mapstructure:"simple,omitempty"` -} - -type TracerProviderJson struct { - // Limits corresponds to the JSON schema field "limits". - Limits *SpanLimits `mapstructure:"limits,omitempty"` - - // Processors corresponds to the JSON schema field "processors". - Processors []SpanProcessor `mapstructure:"processors,omitempty"` - - // Sampler corresponds to the JSON schema field "sampler". - Sampler *Sampler `mapstructure:"sampler,omitempty"` -} diff --git a/service/telemetry/otel_trace_sampler.go b/service/telemetry/otel_trace_sampler.go index 1a8bb595cb6..25928bfe31e 100644 --- a/service/telemetry/otel_trace_sampler.go +++ b/service/telemetry/otel_trace_sampler.go @@ -9,7 +9,7 @@ import ( type recordSampler struct{} -func (r recordSampler) ShouldSample(_ sdktrace.SamplingParameters) sdktrace.SamplingResult { +func (r recordSampler) ShouldSample(sdktrace.SamplingParameters) sdktrace.SamplingResult { return sdktrace.SamplingResult{Decision: sdktrace.RecordOnly} } diff --git a/service/telemetry/package_test.go b/service/telemetry/package_test.go new file mode 100644 index 00000000000..7d5570bf8df --- /dev/null +++ b/service/telemetry/package_test.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package telemetry + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/service/telemetry/telemetry.go b/service/telemetry/telemetry.go index 00f9db630b0..d557d1e957e 100644 --- a/service/telemetry/telemetry.go +++ b/service/telemetry/telemetry.go @@ -5,12 +5,30 @@ package telemetry // import "go.opentelemetry.io/collector/service/telemetry" import ( "context" + "errors" + "go.opentelemetry.io/contrib/propagators/b3" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/trace" "go.uber.org/multierr" "go.uber.org/zap" "go.uber.org/zap/zapcore" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/service/internal/proctelemetry" + "go.opentelemetry.io/collector/service/internal/resource" +) + +const ( + // supported trace propagators + traceContextPropagator = "tracecontext" + b3Propagator = "b3" +) + +var ( + errUnsupportedPropagator = errors.New("unsupported trace propagator") ) type Telemetry struct { @@ -35,31 +53,73 @@ func (t *Telemetry) Shutdown(ctx context.Context) error { // Settings holds configuration for building Telemetry. type Settings struct { + BuildInfo component.BuildInfo ZapOptions []zap.Option } // New creates a new Telemetry from Config. -func New(_ context.Context, set Settings, cfg Config) (*Telemetry, error) { +func New(ctx context.Context, set Settings, cfg Config) (*Telemetry, error) { logger, err := newLogger(cfg.Logs, set.ZapOptions) if err != nil { return nil, err } - tp := sdktrace.NewTracerProvider( - // needed for supporting the zpages extension - sdktrace.WithSampler(alwaysRecord()), - ) + + tp, err := newTracerProvider(ctx, set, cfg) + if err != nil { + return nil, err + } + return &Telemetry{ logger: logger, tracerProvider: tp, }, nil } +func newTracerProvider(ctx context.Context, set Settings, cfg Config) (*sdktrace.TracerProvider, error) { + opts := []sdktrace.TracerProviderOption{sdktrace.WithSampler(alwaysRecord())} + for _, processor := range cfg.Traces.Processors { + sp, err := proctelemetry.InitSpanProcessor(ctx, processor) + if err != nil { + return nil, err + } + opts = append(opts, sdktrace.WithSpanProcessor(sp)) + } + + res := resource.New(set.BuildInfo, cfg.Resource) + tp, err := proctelemetry.InitTracerProvider(res, opts) + if err != nil { + return nil, err + } + + if tp, err := textMapPropagatorFromConfig(cfg.Traces.Propagators); err == nil { + otel.SetTextMapPropagator(tp) + } else { + return nil, err + } + + return tp, nil +} + +func textMapPropagatorFromConfig(props []string) (propagation.TextMapPropagator, error) { + var textMapPropagators []propagation.TextMapPropagator + for _, prop := range props { + switch prop { + case traceContextPropagator: + textMapPropagators = append(textMapPropagators, propagation.TraceContext{}) + case b3Propagator: + textMapPropagators = append(textMapPropagators, b3.New()) + default: + return nil, errUnsupportedPropagator + } + } + return propagation.NewCompositeTextMapPropagator(textMapPropagators...), nil +} + func newLogger(cfg LogsConfig, options []zap.Option) (*zap.Logger, error) { // Copied from NewProductionConfig. zapCfg := &zap.Config{ Level: zap.NewAtomicLevelAt(cfg.Level), Development: cfg.Development, - Sampling: toSamplingConfig(cfg.Sampling), Encoding: cfg.Encoding, EncoderConfig: zap.NewProductionEncoderConfig(), OutputPaths: cfg.OutputPaths, @@ -78,16 +138,23 @@ func newLogger(cfg LogsConfig, options []zap.Option) (*zap.Logger, error) { if err != nil { return nil, err } + if cfg.Sampling != nil && cfg.Sampling.Enabled { + logger = newSampledLogger(logger, cfg.Sampling) + } return logger, nil } -func toSamplingConfig(sc *LogsSamplingConfig) *zap.SamplingConfig { - if sc == nil { - return nil - } - return &zap.SamplingConfig{ - Initial: sc.Initial, - Thereafter: sc.Thereafter, - } +func newSampledLogger(logger *zap.Logger, sc *LogsSamplingConfig) *zap.Logger { + // Create a logger that samples every Nth message after the first M messages every S seconds + // where N = sc.Thereafter, M = sc.Initial, S = sc.Tick. + opts := zap.WrapCore(func(core zapcore.Core) zapcore.Core { + return zapcore.NewSamplerWithOptions( + core, + sc.Tick, + sc.Initial, + sc.Thereafter, + ) + }) + return logger.WithOptions(opts) } diff --git a/service/telemetry/telemetry_test.go b/service/telemetry/telemetry_test.go new file mode 100644 index 00000000000..b01b3c7d8c8 --- /dev/null +++ b/service/telemetry/telemetry_test.go @@ -0,0 +1,117 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package telemetry + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + + "go.opentelemetry.io/collector/config/configtelemetry" +) + +func TestTelemetryConfiguration(t *testing.T) { + tests := []struct { + name string + cfg *Config + success bool + }{ + { + name: "Valid config", + cfg: &Config{ + Logs: LogsConfig{ + Level: zapcore.DebugLevel, + Encoding: "console", + }, + Metrics: MetricsConfig{ + Level: configtelemetry.LevelBasic, + Address: "127.0.0.1:3333", + }, + }, + success: true, + }, + { + name: "Invalid config", + cfg: &Config{ + Logs: LogsConfig{ + Level: zapcore.DebugLevel, + }, + Metrics: MetricsConfig{ + Level: configtelemetry.LevelBasic, + Address: "127.0.0.1:3333", + }, + }, + success: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + telemetry, err := New(context.Background(), Settings{ZapOptions: []zap.Option{}}, *tt.cfg) + if tt.success { + assert.NoError(t, err) + assert.NotNil(t, telemetry) + } else { + assert.Error(t, err) + assert.Nil(t, telemetry) + } + }) + } +} + +func TestSampledLogger(t *testing.T) { + tests := []struct { + name string + cfg *Config + }{ + { + name: "Default sampling", + cfg: &Config{ + Logs: LogsConfig{ + Encoding: "console", + }, + }, + }, + { + name: "Custom sampling", + cfg: &Config{ + Logs: LogsConfig{ + Level: zapcore.DebugLevel, + Encoding: "console", + Sampling: &LogsSamplingConfig{ + Enabled: true, + Tick: 1 * time.Second, + Initial: 100, + Thereafter: 100, + }, + }, + }, + }, + { + name: "Disable sampling", + cfg: &Config{ + Logs: LogsConfig{ + Level: zapcore.DebugLevel, + Encoding: "console", + Sampling: &LogsSamplingConfig{ + Enabled: false, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + telemetry, err := New(context.Background(), Settings{ZapOptions: []zap.Option{}}, *tt.cfg) + assert.NoError(t, err) + assert.NotNil(t, telemetry) + assert.NotNil(t, telemetry.Logger()) + }) + } +} diff --git a/service/telemetry_test.go b/service/telemetry_test.go index a4144e27890..37bd3d82b28 100644 --- a/service/telemetry_test.go +++ b/service/telemetry_test.go @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/require" "go.opencensus.io/stats" "go.opencensus.io/stats/view" + "go.opentelemetry.io/contrib/config" "go.opentelemetry.io/otel/metric" "go.uber.org/zap" @@ -23,6 +24,7 @@ import ( "go.opentelemetry.io/collector/internal/testutil" semconv "go.opentelemetry.io/collector/semconv/v1.18.0" "go.opentelemetry.io/collector/service/internal/proctelemetry" + "go.opentelemetry.io/collector/service/internal/resource" "go.opentelemetry.io/collector/service/telemetry" ) @@ -40,7 +42,7 @@ func TestBuildResource(t *testing.T) { // Check default config cfg := telemetry.Config{} - otelRes := buildResource(buildInfo, cfg) + otelRes := resource.New(buildInfo, cfg.Resource) res := pdataFromSdk(otelRes) assert.Equal(t, res.Attributes().Len(), 3) @@ -62,7 +64,7 @@ func TestBuildResource(t *testing.T) { semconv.AttributeServiceInstanceID: nil, }, } - otelRes = buildResource(buildInfo, cfg) + otelRes = resource.New(buildInfo, cfg.Resource) res = pdataFromSdk(otelRes) // Attributes should not exist since we nil-ified all. @@ -77,7 +79,7 @@ func TestBuildResource(t *testing.T) { semconv.AttributeServiceInstanceID: strPtr("c"), }, } - otelRes = buildResource(buildInfo, cfg) + otelRes = resource.New(buildInfo, cfg.Resource) res = pdataFromSdk(otelRes) assert.Equal(t, res.Attributes().Len(), 3) @@ -100,15 +102,13 @@ func TestTelemetryInit(t *testing.T) { for _, tc := range []struct { name string - useOtel bool disableHighCard bool expectedMetrics map[string]metricValue extendedConfig bool cfg *telemetry.Config }{ { - name: "UseOpenCensusForInternalMetrics", - useOtel: false, + name: "UseOpenTelemetryForInternalMetrics", expectedMetrics: map[string]metricValue{ metricPrefix + ocPrefix + counterName: { value: 13, @@ -118,36 +118,36 @@ func TestTelemetryInit(t *testing.T) { "service_instance_id": testInstanceID, }, }, - }, - }, - { - name: "UseOpenTelemetryForInternalMetrics", - useOtel: true, - expectedMetrics: map[string]metricValue{ - metricPrefix + ocPrefix + counterName + "_total": { - value: 13, - labels: map[string]string{}, - }, - metricPrefix + otelPrefix + counterName + "_total": { - value: 13, - labels: map[string]string{}, + metricPrefix + otelPrefix + counterName: { + value: 13, + labels: map[string]string{ + "service_name": "otelcol", + "service_version": "latest", + "service_instance_id": testInstanceID, + }, }, - metricPrefix + grpcPrefix + counterName + "_total": { + metricPrefix + grpcPrefix + counterName: { value: 11, labels: map[string]string{ - "net_sock_peer_addr": "", - "net_sock_peer_name": "", - "net_sock_peer_port": "", + "net_sock_peer_addr": "", + "net_sock_peer_name": "", + "net_sock_peer_port": "", + "service_name": "otelcol", + "service_version": "latest", + "service_instance_id": testInstanceID, }, }, - metricPrefix + httpPrefix + counterName + "_total": { + metricPrefix + httpPrefix + counterName: { value: 10, labels: map[string]string{ - "net_host_name": "", - "net_host_port": "", + "net_host_name": "", + "net_host_port": "", + "service_name": "otelcol", + "service_version": "latest", + "service_instance_id": testInstanceID, }, }, - metricPrefix + "target_info": { + "target_info": { value: 0, labels: map[string]string{ "service_name": "otelcol", @@ -159,26 +159,41 @@ func TestTelemetryInit(t *testing.T) { }, { name: "DisableHighCardinalityWithOtel", - useOtel: true, disableHighCard: true, expectedMetrics: map[string]metricValue{ - metricPrefix + ocPrefix + counterName + "_total": { - value: 13, - labels: map[string]string{}, + metricPrefix + ocPrefix + counterName: { + value: 13, + labels: map[string]string{ + "service_name": "otelcol", + "service_version": "latest", + "service_instance_id": testInstanceID, + }, }, - metricPrefix + otelPrefix + counterName + "_total": { - value: 13, - labels: map[string]string{}, + metricPrefix + otelPrefix + counterName: { + value: 13, + labels: map[string]string{ + "service_name": "otelcol", + "service_version": "latest", + "service_instance_id": testInstanceID, + }, }, - metricPrefix + grpcPrefix + counterName + "_total": { - value: 11, - labels: map[string]string{}, + metricPrefix + grpcPrefix + counterName: { + value: 11, + labels: map[string]string{ + "service_name": "otelcol", + "service_version": "latest", + "service_instance_id": testInstanceID, + }, }, - metricPrefix + httpPrefix + counterName + "_total": { - value: 10, - labels: map[string]string{}, + metricPrefix + httpPrefix + counterName: { + value: 10, + labels: map[string]string{ + "service_name": "otelcol", + "service_version": "latest", + "service_instance_id": testInstanceID, + }, }, - metricPrefix + "target_info": { + "target_info": { value: 0, labels: map[string]string{ "service_name": "otelcol", @@ -196,11 +211,11 @@ func TestTelemetryInit(t *testing.T) { Level: configtelemetry.LevelDetailed, }, Traces: telemetry.TracesConfig{ - Processors: []telemetry.SpanProcessor{ + Processors: []config.SpanProcessor{ { - Batch: &telemetry.BatchSpanProcessor{ - Exporter: telemetry.SpanExporter{ - Console: telemetry.Console{}, + Batch: &config.BatchSpanProcessor{ + Exporter: config.SpanExporter{ + Console: config.Console{}, }, }, }, @@ -211,30 +226,44 @@ func TestTelemetryInit(t *testing.T) { }, }, expectedMetrics: map[string]metricValue{ - metricPrefix + ocPrefix + counterName + "_total": { - value: 13, - labels: map[string]string{}, + metricPrefix + ocPrefix + counterName: { + value: 13, + labels: map[string]string{ + "service_name": "otelcol", + "service_version": "latest", + "service_instance_id": testInstanceID, + }, }, - metricPrefix + otelPrefix + counterName + "_total": { - value: 13, - labels: map[string]string{}, + metricPrefix + otelPrefix + counterName: { + value: 13, + labels: map[string]string{ + "service_name": "otelcol", + "service_version": "latest", + "service_instance_id": testInstanceID, + }, }, - metricPrefix + grpcPrefix + counterName + "_total": { + metricPrefix + grpcPrefix + counterName: { value: 11, labels: map[string]string{ - "net_sock_peer_addr": "", - "net_sock_peer_name": "", - "net_sock_peer_port": "", + "net_sock_peer_addr": "", + "net_sock_peer_name": "", + "net_sock_peer_port": "", + "service_name": "otelcol", + "service_version": "latest", + "service_instance_id": testInstanceID, }, }, - metricPrefix + httpPrefix + counterName + "_total": { + metricPrefix + httpPrefix + counterName: { value: 10, labels: map[string]string{ - "net_host_name": "", - "net_host_port": "", + "net_host_name": "", + "net_host_port": "", + "service_name": "otelcol", + "service_version": "latest", + "service_instance_id": testInstanceID, }, }, - metricPrefix + "target_info": { + "target_info": { value: 0, labels: map[string]string{ "service_name": "otelcol", @@ -246,13 +275,11 @@ func TestTelemetryInit(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - tel := newColTelemetry(tc.useOtel, tc.disableHighCard, tc.extendedConfig) - buildInfo := component.NewDefaultBuildInfo() if tc.extendedConfig { - tc.cfg.Metrics.Readers = []telemetry.MetricReader{ + tc.cfg.Metrics.Readers = []config.MetricReader{ { - Pull: &telemetry.PullMetricReader{ - Exporter: telemetry.MetricExporter{ + Pull: &config.PullMetricReader{ + Exporter: config.MetricExporter{ Prometheus: testutil.GetAvailableLocalAddressPrometheus(t), }, }, @@ -270,24 +297,26 @@ func TestTelemetryInit(t *testing.T) { }, } } - otelRes := buildResource(buildInfo, *tc.cfg) - res := pdataFromSdk(otelRes) - settings := component.TelemetrySettings{ - Logger: zap.NewNop(), - Resource: res, + set := meterProviderSettings{ + res: resource.New(component.NewDefaultBuildInfo(), tc.cfg.Resource), + logger: zap.NewNop(), + cfg: tc.cfg.Metrics, + asyncErrorChannel: make(chan error), } - err := tel.init(otelRes, settings, *tc.cfg, make(chan error)) + mp, err := newMeterProvider(set, tc.disableHighCard, tc.extendedConfig) require.NoError(t, err) defer func() { - require.NoError(t, tel.shutdown()) + if prov, ok := mp.(interface{ Shutdown(context.Context) error }); ok { + require.NoError(t, prov.Shutdown(context.Background())) + } }() - v := createTestMetrics(t, tel.mp) + v := createTestMetrics(t, mp) defer func() { view.Unregister(v) }() - metrics := getMetricsFromPrometheus(t, tel.servers[0].Handler) + metrics := getMetricsFromPrometheus(t, mp.(*meterProvider).servers[0].Handler) require.Equal(t, len(tc.expectedMetrics), len(metrics)) for metricName, metricValue := range tc.expectedMetrics { diff --git a/versions.yaml b/versions.yaml index 9a74763d86d..7c0074f9ad1 100644 --- a/versions.yaml +++ b/versions.yaml @@ -3,23 +3,31 @@ module-sets: stable: - version: v1.0.0-rcv0014 + version: v1.3.0 modules: - go.opentelemetry.io/collector/featuregate - go.opentelemetry.io/collector/pdata + - go.opentelemetry.io/collector/config/configopaque beta: - version: v0.85.0 + version: v0.96.0 modules: - go.opentelemetry.io/collector - go.opentelemetry.io/collector/cmd/builder + - go.opentelemetry.io/collector/cmd/mdatagen - go.opentelemetry.io/collector/component - go.opentelemetry.io/collector/confmap + - go.opentelemetry.io/collector/confmap/converter/expandconverter + - go.opentelemetry.io/collector/confmap/provider/envprovider + - go.opentelemetry.io/collector/confmap/provider/fileprovider + - go.opentelemetry.io/collector/confmap/provider/httpprovider + - go.opentelemetry.io/collector/confmap/provider/httpsprovider + - go.opentelemetry.io/collector/confmap/provider/yamlprovider - go.opentelemetry.io/collector/config/configauth - go.opentelemetry.io/collector/config/configcompression - go.opentelemetry.io/collector/config/configgrpc - go.opentelemetry.io/collector/config/confighttp - go.opentelemetry.io/collector/config/confignet - - go.opentelemetry.io/collector/config/configopaque + - go.opentelemetry.io/collector/config/configretry - go.opentelemetry.io/collector/config/configtelemetry - go.opentelemetry.io/collector/config/configtls - go.opentelemetry.io/collector/config/internal @@ -35,6 +43,7 @@ module-sets: - go.opentelemetry.io/collector/extension/auth - go.opentelemetry.io/collector/extension/ballastextension - go.opentelemetry.io/collector/extension/zpagesextension + - go.opentelemetry.io/collector/extension/memorylimiterextension - go.opentelemetry.io/collector/otelcol - go.opentelemetry.io/collector/processor - go.opentelemetry.io/collector/processor/batchprocessor @@ -46,4 +55,5 @@ module-sets: excluded-modules: - go.opentelemetry.io/collector/cmd/otelcorecol + - go.opentelemetry.io/collector/internal/e2e - go.opentelemetry.io/collector/internal/tools