From 41e5d7d8dda8fbe69410162f45630036b338e18b Mon Sep 17 00:00:00 2001 From: Steve Strugnell Date: Fri, 14 Jun 2024 10:28:46 +1200 Subject: [PATCH] Upstream merge 0.100.x (#42) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [configgrpc] Add `ToServerContext` (#9624) Adds a new function, `ToServerContext` which does what `ToServer` does, but takes a `context.Context`. After the next release we'll deprecate `ToServerContext` and rename it to `ToServer`. Related to https://github.com/open-telemetry/opentelemetry-collector/issues/9490 --------- Co-authored-by: Dmitrii Anoshin * [chore] Fix prepare-release.yml (#9675) **Description:** Fixes https://github.com/open-telemetry/opentelemetry-collector/actions/runs/8139621131/workflow ``` The workflow is not valid. .github/workflows/prepare-release.yml (Line: 54, Col: 9): Job 'prepare-release' depends on unknown job 'validate-version'. ``` #9409 introduced some errors because the workflow is not tested on PRs, #9668 partly fixed them and I mistakenly believed Github would notify me of further errors in the workflow, the same way it did with this one, but it did not. * [chore] Prepare release v1.3.0/v0.96.0 (#9680) The following commands were run to prepare this release: - make chlog-update VERSION=v1.3.0/v0.96.0 - make prepare-release PREVIOUS_VERSION=1.2.0 RELEASE_CANDIDATE=1.3.0 MODSET=stable - make prepare-release PREVIOUS_VERSION=0.95.0 RELEASE_CANDIDATE=0.96.0 MODSET=beta * [chore] Update release schedule (#9678) **Description:** Updates release schedule. The March 18th release overlaps with KubeCon EU, so I am shifting everything by one week starting with that release. This means the next release cycle will have three weeks. * [chore] Add reminder to update release schedule to release issue template (#9679) **Description:** Add reminder to update the release schedule * [chore] Update prepare release examples (#9677) **Description:** After #8975 we decided to not do any more explicit release candidates so we can update the examples. Note that due to #9676 this is not tested until we explicitly run the workflow on the next release, but the change is small enough to seem safe to merge. * [cmd/mdatagen] Pull new changes from contrib (#9683) To completely migrate mdatagen from contrib to core, we need to pull latest changes: - https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/31500 - https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/31503 - https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/31520 - https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/31525 - https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/31530 - https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/31532 --------- Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] fix type in confighttp readme (#9690) This doc incorrectly uses the otlp exporter as an example of using confighttp. That exporter doesn't use confighttp Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Update module github.com/stretchr/testify to v1.9.0 (#9695) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [github.com/stretchr/testify](https://togithub.com/stretchr/testify) | `v1.8.4` -> `v1.9.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fstretchr%2ftestify/v1.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/github.com%2fstretchr%2ftestify/v1.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/github.com%2fstretchr%2ftestify/v1.8.4/v1.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fstretchr%2ftestify/v1.8.4/v1.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
stretchr/testify (github.com/stretchr/testify) ### [`v1.9.0`](https://togithub.com/stretchr/testify/releases/tag/v1.9.0) [Compare Source](https://togithub.com/stretchr/testify/compare/v1.8.4...v1.9.0) #### What's Changed - Fix Go modules version by [@​SuperQ](https://togithub.com/SuperQ) in [https://github.com/stretchr/testify/pull/1394](https://togithub.com/stretchr/testify/pull/1394) - Document that require is not safe to call in created goroutines by [@​programmer04](https://togithub.com/programmer04) in [https://github.com/stretchr/testify/pull/1392](https://togithub.com/stretchr/testify/pull/1392) - Remove myself from MAINTAINERS.md by [@​mvdkleijn](https://togithub.com/mvdkleijn) in [https://github.com/stretchr/testify/pull/1367](https://togithub.com/stretchr/testify/pull/1367) - Correct spelling/grammar by [@​echarrod](https://togithub.com/echarrod) in [https://github.com/stretchr/testify/pull/1389](https://togithub.com/stretchr/testify/pull/1389) - docs: Update URLs in README by [@​davidjb](https://togithub.com/davidjb) in [https://github.com/stretchr/testify/pull/1349](https://togithub.com/stretchr/testify/pull/1349) - Update mockery link to Github Pages in README by [@​LandonTClipp](https://togithub.com/LandonTClipp) in [https://github.com/stretchr/testify/pull/1346](https://togithub.com/stretchr/testify/pull/1346) - docs: Fix typos in tests and comments by [@​alexandear](https://togithub.com/alexandear) in [https://github.com/stretchr/testify/pull/1410](https://togithub.com/stretchr/testify/pull/1410) - CI: tests from go1.17 by [@​SuperQ](https://togithub.com/SuperQ) in [https://github.com/stretchr/testify/pull/1409](https://togithub.com/stretchr/testify/pull/1409) - Fix adding ? when no values passed by [@​lesichkovm](https://togithub.com/lesichkovm) in [https://github.com/stretchr/testify/pull/1320](https://togithub.com/stretchr/testify/pull/1320) - codegen: use standard header for generated files by [@​dolmen](https://togithub.com/dolmen) in [https://github.com/stretchr/testify/pull/1406](https://togithub.com/stretchr/testify/pull/1406) - mock: AssertExpectations log reason only on failure by [@​hikyaru-suzuki](https://togithub.com/hikyaru-suzuki) in [https://github.com/stretchr/testify/pull/1360](https://togithub.com/stretchr/testify/pull/1360) - assert: fix flaky TestNeverTrue by [@​dolmen](https://togithub.com/dolmen) in [https://github.com/stretchr/testify/pull/1417](https://togithub.com/stretchr/testify/pull/1417) - README: fix typos "set up" vs "setup" by [@​ossan-dev](https://togithub.com/ossan-dev) in [https://github.com/stretchr/testify/pull/1428](https://togithub.com/stretchr/testify/pull/1428) - mock: move regexp compilation outside of `Called` by [@​aud10slave](https://togithub.com/aud10slave) in [https://github.com/stretchr/testify/pull/631](https://togithub.com/stretchr/testify/pull/631) - assert: refactor internal func getLen() by [@​dolmen](https://togithub.com/dolmen) in [https://github.com/stretchr/testify/pull/1445](https://togithub.com/stretchr/testify/pull/1445) - mock: deprecate type AnythingOfTypeArgument ([#​1434](https://togithub.com/stretchr/testify/issues/1434)) by [@​dolmen](https://togithub.com/dolmen) in [https://github.com/stretchr/testify/pull/1441](https://togithub.com/stretchr/testify/pull/1441) - Remove no longer needed assert.canConvert by [@​alexandear](https://togithub.com/alexandear) in [https://github.com/stretchr/testify/pull/1470](https://togithub.com/stretchr/testify/pull/1470) - assert: ObjectsAreEqual: use time.Equal for time.Time types by [@​tscales](https://togithub.com/tscales) in [https://github.com/stretchr/testify/pull/1464](https://togithub.com/stretchr/testify/pull/1464) - Bump actions/checkout from 3 to 4 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/stretchr/testify/pull/1466](https://togithub.com/stretchr/testify/pull/1466) - Bump actions/setup-go from 3.2.0 to 4.1.0 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/stretchr/testify/pull/1451](https://togithub.com/stretchr/testify/pull/1451) - fix: make EventuallyWithT concurrency safe by [@​czeslavo](https://togithub.com/czeslavo) in [https://github.com/stretchr/testify/pull/1395](https://togithub.com/stretchr/testify/pull/1395) - assert: fix httpCode and HTTPBody occur panic when http.Handler read Body by [@​hidu](https://togithub.com/hidu) in [https://github.com/stretchr/testify/pull/1484](https://togithub.com/stretchr/testify/pull/1484) - assert.EqualExportedValues: fix handling of arrays by [@​zrbecker](https://togithub.com/zrbecker) in [https://github.com/stretchr/testify/pull/1473](https://togithub.com/stretchr/testify/pull/1473) - .github: use latest Go versions by [@​kevinburkesegment](https://togithub.com/kevinburkesegment) in [https://github.com/stretchr/testify/pull/1489](https://togithub.com/stretchr/testify/pull/1489) - assert: Deprecate EqualExportedValues by [@​HaraldNordgren](https://togithub.com/HaraldNordgren) in [https://github.com/stretchr/testify/pull/1488](https://togithub.com/stretchr/testify/pull/1488) - suite: refactor test assertions by [@​alexandear](https://togithub.com/alexandear) in [https://github.com/stretchr/testify/pull/1474](https://togithub.com/stretchr/testify/pull/1474) - suite: fix SetupSubTest and TearDownSubTest execution order by [@​linusbarth](https://togithub.com/linusbarth) in [https://github.com/stretchr/testify/pull/1471](https://togithub.com/stretchr/testify/pull/1471) - docs: Fix deprecation comments for http package by [@​alexandear](https://togithub.com/alexandear) in [https://github.com/stretchr/testify/pull/1335](https://togithub.com/stretchr/testify/pull/1335) - Add map support doc comments to Subset and NotSubset by [@​jedevc](https://togithub.com/jedevc) in [https://github.com/stretchr/testify/pull/1306](https://togithub.com/stretchr/testify/pull/1306) - TestErrorIs/TestNotErrorIs: check error message contents by [@​craig65535](https://togithub.com/craig65535) in [https://github.com/stretchr/testify/pull/1435](https://togithub.com/stretchr/testify/pull/1435) - suite: fix subtest names (fix [#​1501](https://togithub.com/stretchr/testify/issues/1501)) by [@​dolmen](https://togithub.com/dolmen) in [https://github.com/stretchr/testify/pull/1504](https://togithub.com/stretchr/testify/pull/1504) - assert: improve unsafe.Pointer tests by [@​dolmen](https://togithub.com/dolmen) in [https://github.com/stretchr/testify/pull/1505](https://togithub.com/stretchr/testify/pull/1505) - assert: simplify isNil implementation by [@​dolmen](https://togithub.com/dolmen) in [https://github.com/stretchr/testify/pull/1506](https://togithub.com/stretchr/testify/pull/1506) - assert.InEpsilonSlice: fix expected/actual order and other improvements by [@​dolmen](https://togithub.com/dolmen) in [https://github.com/stretchr/testify/pull/1483](https://togithub.com/stretchr/testify/pull/1483) - Fix dependency cycle with objx [#​1292](https://togithub.com/stretchr/testify/issues/1292) by [@​dolmen](https://togithub.com/dolmen) in [https://github.com/stretchr/testify/pull/1453](https://togithub.com/stretchr/testify/pull/1453) - mock: refactor TestIsArgsEqual by [@​dolmen](https://togithub.com/dolmen) in [https://github.com/stretchr/testify/pull/1444](https://togithub.com/stretchr/testify/pull/1444) - mock: optimize argument matching checks by [@​dolmen](https://togithub.com/dolmen) in [https://github.com/stretchr/testify/pull/1416](https://togithub.com/stretchr/testify/pull/1416) - assert: fix TestEventuallyTimeout by [@​dolmen](https://togithub.com/dolmen) in [https://github.com/stretchr/testify/pull/1412](https://togithub.com/stretchr/testify/pull/1412) - CI: add go 1.21 in GitHub Actions by [@​dolmen](https://togithub.com/dolmen) in [https://github.com/stretchr/testify/pull/1450](https://togithub.com/stretchr/testify/pull/1450) - suite: fix recoverAndFailOnPanic to report test failure at the right location by [@​dolmen](https://togithub.com/dolmen) in [https://github.com/stretchr/testify/pull/1502](https://togithub.com/stretchr/testify/pull/1502) - Update maintainers by [@​brackendawson](https://togithub.com/brackendawson) in [https://github.com/stretchr/testify/pull/1533](https://togithub.com/stretchr/testify/pull/1533) - assert: Fix EqualValues to handle overflow/underflow by [@​arjunmahishi](https://togithub.com/arjunmahishi) in [https://github.com/stretchr/testify/pull/1531](https://togithub.com/stretchr/testify/pull/1531) - assert: better formatting for Len() error by [@​kevinburkesegment](https://togithub.com/kevinburkesegment) in [https://github.com/stretchr/testify/pull/1485](https://togithub.com/stretchr/testify/pull/1485) - Ensure AssertExpectations does not fail in skipped tests by [@​ianrose14](https://togithub.com/ianrose14) in [https://github.com/stretchr/testify/pull/1331](https://togithub.com/stretchr/testify/pull/1331) - suite: fix deadlock in suite.Require()/Assert() by [@​arjunmahishi](https://togithub.com/arjunmahishi) in [https://github.com/stretchr/testify/pull/1535](https://togithub.com/stretchr/testify/pull/1535) - Revert "assert: ObjectsAreEqual: use time.Equal for time.Time type" by [@​brackendawson](https://togithub.com/brackendawson) in [https://github.com/stretchr/testify/pull/1537](https://togithub.com/stretchr/testify/pull/1537) - \[chore] Add issue templates by [@​arjunmahishi](https://togithub.com/arjunmahishi) in [https://github.com/stretchr/testify/pull/1538](https://togithub.com/stretchr/testify/pull/1538) - Update the build status badge by [@​brackendawson](https://togithub.com/brackendawson) in [https://github.com/stretchr/testify/pull/1540](https://togithub.com/stretchr/testify/pull/1540) - Update Github workflows setup-go to V5 by [@​hendrywiranto](https://togithub.com/hendrywiranto) in [https://github.com/stretchr/testify/pull/1545](https://togithub.com/stretchr/testify/pull/1545) - Support Pointer to Struct in EqualExportedValues by [@​Lucaber](https://togithub.com/Lucaber) in [https://github.com/stretchr/testify/pull/1517](https://togithub.com/stretchr/testify/pull/1517) - README: drop link to gorc by [@​guettli](https://togithub.com/guettli) in [https://github.com/stretchr/testify/pull/1248](https://togithub.com/stretchr/testify/pull/1248) - http_assertions: honour the msgAndArgs provided with each assertion by [@​arjunmahishi](https://togithub.com/arjunmahishi) in [https://github.com/stretchr/testify/pull/1548](https://togithub.com/stretchr/testify/pull/1548) - fix typos in comments and tests by [@​ccoVeille](https://togithub.com/ccoVeille) in [https://github.com/stretchr/testify/pull/1247](https://togithub.com/stretchr/testify/pull/1247) - Include the auto-release notes in releases by [@​brackendawson](https://togithub.com/brackendawson) in [https://github.com/stretchr/testify/pull/1550](https://togithub.com/stretchr/testify/pull/1550) - Add `NotImplements` and variants by [@​hslatman](https://togithub.com/hslatman) in [https://github.com/stretchr/testify/pull/1385](https://togithub.com/stretchr/testify/pull/1385) - Add support to compare uintptr by [@​bogdandrutu](https://togithub.com/bogdandrutu) in [https://github.com/stretchr/testify/pull/1339](https://togithub.com/stretchr/testify/pull/1339) - build(deps): bump github.com/stretchr/objx from 0.5.1 to 0.5.2 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/stretchr/testify/pull/1552](https://togithub.com/stretchr/testify/pull/1552) #### New Contributors - [@​SuperQ](https://togithub.com/SuperQ) made their first contribution in [https://github.com/stretchr/testify/pull/1394](https://togithub.com/stretchr/testify/pull/1394) - [@​programmer04](https://togithub.com/programmer04) made their first contribution in [https://github.com/stretchr/testify/pull/1392](https://togithub.com/stretchr/testify/pull/1392) - [@​echarrod](https://togithub.com/echarrod) made their first contribution in [https://github.com/stretchr/testify/pull/1389](https://togithub.com/stretchr/testify/pull/1389) - [@​davidjb](https://togithub.com/davidjb) made their first contribution in [https://github.com/stretchr/testify/pull/1349](https://togithub.com/stretchr/testify/pull/1349) - [@​LandonTClipp](https://togithub.com/LandonTClipp) made their first contribution in [https://github.com/stretchr/testify/pull/1346](https://togithub.com/stretchr/testify/pull/1346) - [@​alexandear](https://togithub.com/alexandear) made their first contribution in [https://github.com/stretchr/testify/pull/1410](https://togithub.com/stretchr/testify/pull/1410) - [@​lesichkovm](https://togithub.com/lesichkovm) made their first contribution in [https://github.com/stretchr/testify/pull/1320](https://togithub.com/stretchr/testify/pull/1320) - [@​dolmen](https://togithub.com/dolmen) made their first contribution in [https://github.com/stretchr/testify/pull/1406](https://togithub.com/stretchr/testify/pull/1406) - [@​hikyaru-suzuki](https://togithub.com/hikyaru-suzuki) made their first contribution in [https://github.com/stretchr/testify/pull/1360](https://togithub.com/stretchr/testify/pull/1360) - [@​ossan-dev](https://togithub.com/ossan-dev) made their first contribution in [https://github.com/stretchr/testify/pull/1428](https://togithub.com/stretchr/testify/pull/1428) - [@​aud10slave](https://togithub.com/aud10slave) made their first contribution in [https://github.com/stretchr/testify/pull/631](https://togithub.com/stretchr/testify/pull/631) - [@​tscales](https://togithub.com/tscales) made their first contribution in [https://github.com/stretchr/testify/pull/1464](https://togithub.com/stretchr/testify/pull/1464) - [@​czeslavo](https://togithub.com/czeslavo) made their first contribution in [https://github.com/stretchr/testify/pull/1395](https://togithub.com/stretchr/testify/pull/1395) - [@​hidu](https://togithub.com/hidu) made their first contribution in [https://github.com/stretchr/testify/pull/1484](https://togithub.com/stretchr/testify/pull/1484) - [@​zrbecker](https://togithub.com/zrbecker) made their first contribution in [https://github.com/stretchr/testify/pull/1473](https://togithub.com/stretchr/testify/pull/1473) - [@​kevinburkesegment](https://togithub.com/kevinburkesegment) made their first contribution in [https://github.com/stretchr/testify/pull/1489](https://togithub.com/stretchr/testify/pull/1489) - [@​linusbarth](https://togithub.com/linusbarth) made their first contribution in [https://github.com/stretchr/testify/pull/1471](https://togithub.com/stretchr/testify/pull/1471) - [@​jedevc](https://togithub.com/jedevc) made their first contribution in [https://github.com/stretchr/testify/pull/1306](https://togithub.com/stretchr/testify/pull/1306) - [@​craig65535](https://togithub.com/craig65535) made their first contribution in [https://github.com/stretchr/testify/pull/1435](https://togithub.com/stretchr/testify/pull/1435) - [@​arjunmahishi](https://togithub.com/arjunmahishi) made their first contribution in [https://github.com/stretchr/testify/pull/1531](https://togithub.com/stretchr/testify/pull/1531) - [@​ianrose14](https://togithub.com/ianrose14) made their first contribution in [https://github.com/stretchr/testify/pull/1331](https://togithub.com/stretchr/testify/pull/1331) - [@​hendrywiranto](https://togithub.com/hendrywiranto) made their first contribution in [https://github.com/stretchr/testify/pull/1545](https://togithub.com/stretchr/testify/pull/1545) - [@​Lucaber](https://togithub.com/Lucaber) made their first contribution in [https://github.com/stretchr/testify/pull/1517](https://togithub.com/stretchr/testify/pull/1517) - [@​guettli](https://togithub.com/guettli) made their first contribution in [https://github.com/stretchr/testify/pull/1248](https://togithub.com/stretchr/testify/pull/1248) - [@​ccoVeille](https://togithub.com/ccoVeille) made their first contribution in [https://github.com/stretchr/testify/pull/1247](https://togithub.com/stretchr/testify/pull/1247) - [@​hslatman](https://togithub.com/hslatman) made their first contribution in [https://github.com/stretchr/testify/pull/1385](https://togithub.com/stretchr/testify/pull/1385) - [@​bogdandrutu](https://togithub.com/bogdandrutu) made their first contribution in [https://github.com/stretchr/testify/pull/1339](https://togithub.com/stretchr/testify/pull/1339) **Full Changelog**: https://github.com/stretchr/testify/compare/v1.8.4...v1.9.0
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * Update module go.opentelemetry.io/build-tools/semconvgen to v0.13.0 (#9701) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/build-tools/semconvgen](https://togithub.com/open-telemetry/opentelemetry-go-build-tools) | `v0.12.0` -> `v0.13.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fbuild-tools%2fsemconvgen/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fbuild-tools%2fsemconvgen/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fbuild-tools%2fsemconvgen/v0.12.0/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fbuild-tools%2fsemconvgen/v0.12.0/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-go-build-tools (go.opentelemetry.io/build-tools/semconvgen) ### [`v0.13.0`](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/blob/HEAD/CHANGELOG.md#v0130) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/compare/v0.12.0...v0.13.0) ##### 🛑 Breaking changes 🛑 - `all`: bump minimal Go version to 1.20 ([#​474](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/474)) ##### 💡 Enhancements 💡 - `multimod`: ignore excluded-modules when using sync to update dependencies ([#​442](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/442)) This allows users of the sync command to sync all modules in a monorepo, including those listed in the excluded-modules. This is useful for repositories where some modules may not yet be ready for releasing (therefore listed under excluded-modules) but their dependencies still need to be managed via multimod. - `crosslink`: Add `--skip` flag to ignore specified go modules ([#​480](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/480)) - `multimod`: add support for `--commit-hash` to allow users to overwrite the tag in a versions.yaml file ([#​422](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/422)) This feature allows users to specify a tag (i.e. main) when they want to update modules. - `chloggen`: support a custom changelog summary template ([#​501](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/501)) The changelog summary template can be customized by configuring a custom template with the `summary_template` configuration setting. The default template provides a starting point for a custom template: https://github.com/open-telemetry/opentelemetry-go-build-tools/blob/v0.13.0/chloggen/internal/chlog/summary.tmpl ##### 🧰 Bug fixes 🧰 - `crosslink`: Fix Windows produces backslashes instead of slashes ([#​458](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/458)) This fixes the issue of Windows produces backslashes instead of slashes when crosslinking dependencies in go.mod files on Windows. - `dbotconf`: Fix Windows produces backslashes instead of slashes ([#​264](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/264)) This fixes the issue of Windows produces backslashes instead of slashes when generating Dependabot configuration files on Windows. - `multimod`: Fix tagging on Windows ([#​464](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/464)) This fixes the issue of `multimod tag` failing on Windows. - `multimod`: Fix to log 'Using versioning file' and 'Successfully deleted module tags' to stderr instead of stdout ([#​507](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/507)) - `chloggen`: change generated files permissions from 0755 to 0644 ([#​457](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/457))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * Update module golang.org/x/tools to v0.19.0 (#9708) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | golang.org/x/tools | `v0.18.0` -> `v0.19.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2ftools/v0.19.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/golang.org%2fx%2ftools/v0.19.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/golang.org%2fx%2ftools/v0.18.0/v0.19.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2ftools/v0.18.0/v0.19.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * [cmd/mdatagen] Update the scope name generation method (#9693) Don't use hardcoded "go.opentelemetry.io/collector" prefix. Provide a way to specify the `scope_name` in metadata.yaml. If not provided, try to use the go package name. Updates https://github.com/open-telemetry/opentelemetry-collector/issues/9494 * Update module go.opentelemetry.io/collector/exporter/otlphttpexporter to v0.96.0 (#9703) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/collector/exporter/otlphttpexporter](https://togithub.com/open-telemetry/opentelemetry-collector) | `v0.95.0` -> `v0.96.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.96.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.96.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.95.0/v0.96.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.95.0/v0.96.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-collector (go.opentelemetry.io/collector/exporter/otlphttpexporter) ### [`v0.96.0`](https://togithub.com/open-telemetry/opentelemetry-collector/blob/HEAD/CHANGELOG.md#v130v0960) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-collector/compare/v0.95.0...v0.96.0) ##### 🛑 Breaking changes 🛑 - `configgrpc`: Remove deprecated `GRPCClientSettings`, `GRPCServerSettings`, and `ServerConfig.ToListenerContext`. ([#​9616](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9616)) - `confighttp`: Remove deprecated `HTTPClientSettings`, `NewDefaultHTTPClientSettings`, and `CORSSettings`. ([#​9625](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9625)) - `confignet`: Removes deprecated `NetAddr` and `TCPAddr` ([#​9614](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9614)) ##### 💡 Enhancements 💡 - `configtls`: Add `include_system_ca_certs_pool` to configtls, allowing to load system certs and additional custom certs. ([#​7774](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7774)) - `otelcol`: Add `ConfigProviderSettings` to `CollectorSettings` ([#​4759](https://togithub.com/open-telemetry/opentelemetry-collector/issues/4759)) This allows passing a custom list of `confmap.Provider`s to `otelcol.NewCommand`. - `pdata`: Update to OTLP v1.1.0 ([#​9587](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9587)) Introduces Span and SpanLink flags. - `confmap`: Update mapstructure to use a maintained fork, github.com/go-viper/mapstructure/v2. ([#​9634](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9634)) [https://github.com/mitchellh/mapstructure/issues/349](https://togithub.com/mitchellh/mapstructure/issues/349)/349 for context. ##### 🧰 Bug fixes 🧰 - `configretry`: Allow max_elapsed_time to be set to 0 for indefinite retries ([#​9641](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9641)) - `client`: Make `Metadata.Get` thread safe ([#​9595](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9595))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update module go.opentelemetry.io/collector/receiver/otlpreceiver to v0.96.0 (#9704) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/collector/receiver/otlpreceiver](https://togithub.com/open-telemetry/opentelemetry-collector) | `v0.95.0` -> `v0.96.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.96.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.96.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.95.0/v0.96.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.95.0/v0.96.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-collector (go.opentelemetry.io/collector/receiver/otlpreceiver) ### [`v0.96.0`](https://togithub.com/open-telemetry/opentelemetry-collector/blob/HEAD/CHANGELOG.md#v130v0960) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-collector/compare/v0.95.0...v0.96.0) ##### 🛑 Breaking changes 🛑 - `configgrpc`: Remove deprecated `GRPCClientSettings`, `GRPCServerSettings`, and `ServerConfig.ToListenerContext`. ([#​9616](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9616)) - `confighttp`: Remove deprecated `HTTPClientSettings`, `NewDefaultHTTPClientSettings`, and `CORSSettings`. ([#​9625](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9625)) - `confignet`: Removes deprecated `NetAddr` and `TCPAddr` ([#​9614](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9614)) ##### 💡 Enhancements 💡 - `configtls`: Add `include_system_ca_certs_pool` to configtls, allowing to load system certs and additional custom certs. ([#​7774](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7774)) - `otelcol`: Add `ConfigProviderSettings` to `CollectorSettings` ([#​4759](https://togithub.com/open-telemetry/opentelemetry-collector/issues/4759)) This allows passing a custom list of `confmap.Provider`s to `otelcol.NewCommand`. - `pdata`: Update to OTLP v1.1.0 ([#​9587](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9587)) Introduces Span and SpanLink flags. - `confmap`: Update mapstructure to use a maintained fork, github.com/go-viper/mapstructure/v2. ([#​9634](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9634)) [https://github.com/mitchellh/mapstructure/issues/349](https://togithub.com/mitchellh/mapstructure/issues/349)/349 for context. ##### 🧰 Bug fixes 🧰 - `configretry`: Allow max_elapsed_time to be set to 0 for indefinite retries ([#​9641](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9641)) - `client`: Make `Metadata.Get` thread safe ([#​9595](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9595))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * [chore] [cmd/mdatagen] Update status.go template (#9713) To produce the same output as mdatagen in contrib. It makes it easy to compare the diff for the mdatagen migration. * Update module golang.org/x/sys to v0.18.0 (#9706) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | golang.org/x/sys | `v0.17.0` -> `v0.18.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fsys/v0.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/golang.org%2fx%2fsys/v0.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/golang.org%2fx%2fsys/v0.17.0/v0.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fsys/v0.17.0/v0.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Update module google.golang.org/protobuf to v1.33.0 (#9712) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [google.golang.org/protobuf](https://togithub.com/protocolbuffers/protobuf-go) | `v1.32.0` -> `v1.33.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/google.golang.org%2fprotobuf/v1.33.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/google.golang.org%2fprotobuf/v1.33.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/google.golang.org%2fprotobuf/v1.32.0/v1.33.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/google.golang.org%2fprotobuf/v1.32.0/v1.33.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * Update module go.opentelemetry.io/collector/exporter/otlpexporter to v0.96.0 (#9702) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/collector/exporter/otlpexporter](https://togithub.com/open-telemetry/opentelemetry-collector) | `v0.95.0` -> `v0.96.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.96.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.96.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.95.0/v0.96.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.95.0/v0.96.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-collector (go.opentelemetry.io/collector/exporter/otlpexporter) ### [`v0.96.0`](https://togithub.com/open-telemetry/opentelemetry-collector/blob/HEAD/CHANGELOG.md#v130v0960) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-collector/compare/v0.95.0...v0.96.0) ##### 🛑 Breaking changes 🛑 - `configgrpc`: Remove deprecated `GRPCClientSettings`, `GRPCServerSettings`, and `ServerConfig.ToListenerContext`. ([#​9616](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9616)) - `confighttp`: Remove deprecated `HTTPClientSettings`, `NewDefaultHTTPClientSettings`, and `CORSSettings`. ([#​9625](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9625)) - `confignet`: Removes deprecated `NetAddr` and `TCPAddr` ([#​9614](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9614)) ##### 💡 Enhancements 💡 - `configtls`: Add `include_system_ca_certs_pool` to configtls, allowing to load system certs and additional custom certs. ([#​7774](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7774)) - `otelcol`: Add `ConfigProviderSettings` to `CollectorSettings` ([#​4759](https://togithub.com/open-telemetry/opentelemetry-collector/issues/4759)) This allows passing a custom list of `confmap.Provider`s to `otelcol.NewCommand`. - `pdata`: Update to OTLP v1.1.0 ([#​9587](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9587)) Introduces Span and SpanLink flags. - `confmap`: Update mapstructure to use a maintained fork, github.com/go-viper/mapstructure/v2. ([#​9634](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9634)) [https://github.com/mitchellh/mapstructure/issues/349](https://togithub.com/mitchellh/mapstructure/issues/349)/349 for context. ##### 🧰 Bug fixes 🧰 - `configretry`: Allow max_elapsed_time to be set to 0 for indefinite retries ([#​9641](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9641)) - `client`: Make `Metadata.Get` thread safe ([#​9595](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9595))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Update github-actions deps (#9691) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [actions/cache](https://togithub.com/actions/cache) | action | patch | `v4.0.0` -> `v4.0.1` | | [github/codeql-action](https://togithub.com/github/codeql-action) | action | patch | `v3.24.5` -> `v3.24.6` | --- ### Release Notes
actions/cache (actions/cache) ### [`v4.0.1`](https://togithub.com/actions/cache/releases/tag/v4.0.1) [Compare Source](https://togithub.com/actions/cache/compare/v4.0.0...v4.0.1) ##### What's Changed - Update README.md by [@​yacaovsnc](https://togithub.com/yacaovsnc) in [https://github.com/actions/cache/pull/1304](https://togithub.com/actions/cache/pull/1304) - Update examples by [@​yacaovsnc](https://togithub.com/yacaovsnc) in [https://github.com/actions/cache/pull/1305](https://togithub.com/actions/cache/pull/1305) - Update actions/cache publish flow by [@​bethanyj28](https://togithub.com/bethanyj28) in [https://github.com/actions/cache/pull/1340](https://togithub.com/actions/cache/pull/1340) - Update [@​actions/cache](https://togithub.com/actions/cache) by [@​bethanyj28](https://togithub.com/bethanyj28) in [https://github.com/actions/cache/pull/1341](https://togithub.com/actions/cache/pull/1341) ##### New Contributors - [@​yacaovsnc](https://togithub.com/yacaovsnc) made their first contribution in [https://github.com/actions/cache/pull/1304](https://togithub.com/actions/cache/pull/1304) **Full Changelog**: https://github.com/actions/cache/compare/v4...v4.0.1
github/codeql-action (github/codeql-action) ### [`v3.24.6`](https://togithub.com/github/codeql-action/compare/v3.24.5...v3.24.6) [Compare Source](https://togithub.com/github/codeql-action/compare/v3.24.5...v3.24.6)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update module golang.org/x/net to v0.22.0 (#9705) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | golang.org/x/net | `v0.21.0` -> `v0.22.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fnet/v0.22.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/golang.org%2fx%2fnet/v0.22.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/golang.org%2fx%2fnet/v0.21.0/v0.22.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fnet/v0.21.0/v0.22.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * Update module google.golang.org/grpc to v1.62.1 (#9711) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [google.golang.org/grpc](https://togithub.com/grpc/grpc-go) | `v1.62.0` -> `v1.62.1` | [![age](https://developer.mend.io/api/mc/badges/age/go/google.golang.org%2fgrpc/v1.62.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/google.golang.org%2fgrpc/v1.62.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/google.golang.org%2fgrpc/v1.62.0/v1.62.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/google.golang.org%2fgrpc/v1.62.0/v1.62.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
grpc/grpc-go (google.golang.org/grpc) ### [`v1.62.1`](https://togithub.com/grpc/grpc-go/releases/tag/v1.62.1): Release 1.62.1 [Compare Source](https://togithub.com/grpc/grpc-go/compare/v1.62.0...v1.62.1) ### Bug Fixes - xds: fix a bug that results in `no matching virtual host found` RPC errors due to a difference between the target and LDS resource names ([#​6997](https://togithub.com/grpc/grpc-go/issues/6997)) - server: fixed stats handler data `InPayload.Length` for unary RPC calls ([#​6766](https://togithub.com/grpc/grpc-go/issues/6766)) - Special Thanks: [@​hueypark](https://togithub.com/hueypark) - grpc: the experimental `RecvBufferPool` `DialOption` and `ServerOption` are now active during unary RPCs with compression ([#​6766](https://togithub.com/grpc/grpc-go/issues/6766)) - Special Thanks: [@​hueypark](https://togithub.com/hueypark) - grpc: trim whitespaces in `accept-encoding` header before determining compressors - Special Thanks: [@​sercand](https://togithub.com/sercand)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * Update module go.opentelemetry.io/build-tools/multimod to v0.13.0 (#9700) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/build-tools/multimod](https://togithub.com/open-telemetry/opentelemetry-go-build-tools) | `v0.12.0` -> `v0.13.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fbuild-tools%2fmultimod/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fbuild-tools%2fmultimod/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fbuild-tools%2fmultimod/v0.12.0/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fbuild-tools%2fmultimod/v0.12.0/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-go-build-tools (go.opentelemetry.io/build-tools/multimod) ### [`v0.13.0`](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/blob/HEAD/CHANGELOG.md#v0130) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/compare/v0.12.0...v0.13.0) ##### 🛑 Breaking changes 🛑 - `all`: bump minimal Go version to 1.20 ([#​474](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/474)) ##### 💡 Enhancements 💡 - `multimod`: ignore excluded-modules when using sync to update dependencies ([#​442](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/442)) This allows users of the sync command to sync all modules in a monorepo, including those listed in the excluded-modules. This is useful for repositories where some modules may not yet be ready for releasing (therefore listed under excluded-modules) but their dependencies still need to be managed via multimod. - `crosslink`: Add `--skip` flag to ignore specified go modules ([#​480](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/480)) - `multimod`: add support for `--commit-hash` to allow users to overwrite the tag in a versions.yaml file ([#​422](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/422)) This feature allows users to specify a tag (i.e. main) when they want to update modules. - `chloggen`: support a custom changelog summary template ([#​501](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/501)) The changelog summary template can be customized by configuring a custom template with the `summary_template` configuration setting. The default template provides a starting point for a custom template: https://github.com/open-telemetry/opentelemetry-go-build-tools/blob/v0.13.0/chloggen/internal/chlog/summary.tmpl ##### 🧰 Bug fixes 🧰 - `crosslink`: Fix Windows produces backslashes instead of slashes ([#​458](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/458)) This fixes the issue of Windows produces backslashes instead of slashes when crosslinking dependencies in go.mod files on Windows. - `dbotconf`: Fix Windows produces backslashes instead of slashes ([#​264](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/264)) This fixes the issue of Windows produces backslashes instead of slashes when generating Dependabot configuration files on Windows. - `multimod`: Fix tagging on Windows ([#​464](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/464)) This fixes the issue of `multimod tag` failing on Windows. - `multimod`: Fix to log 'Using versioning file' and 'Successfully deleted module tags' to stderr instead of stdout ([#​507](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/507)) - `chloggen`: change generated files permissions from 0755 to 0644 ([#​457](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/457))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * Update module go.opentelemetry.io/build-tools/crosslink to v0.13.0 (#9699) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/build-tools/crosslink](https://togithub.com/open-telemetry/opentelemetry-go-build-tools) | `v0.12.1-0.20240121161735-d70c842b1bf5` -> `v0.13.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fbuild-tools%2fcrosslink/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fbuild-tools%2fcrosslink/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fbuild-tools%2fcrosslink/v0.12.1-0.20240121161735-d70c842b1bf5/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fbuild-tools%2fcrosslink/v0.12.1-0.20240121161735-d70c842b1bf5/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-go-build-tools (go.opentelemetry.io/build-tools/crosslink) ### [`v0.13.0`](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/blob/HEAD/CHANGELOG.md#v0130) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/compare/v0.12.0...v0.13.0) ##### 🛑 Breaking changes 🛑 - `all`: bump minimal Go version to 1.20 ([#​474](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/474)) ##### 💡 Enhancements 💡 - `multimod`: ignore excluded-modules when using sync to update dependencies ([#​442](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/442)) This allows users of the sync command to sync all modules in a monorepo, including those listed in the excluded-modules. This is useful for repositories where some modules may not yet be ready for releasing (therefore listed under excluded-modules) but their dependencies still need to be managed via multimod. - `crosslink`: Add `--skip` flag to ignore specified go modules ([#​480](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/480)) - `multimod`: add support for `--commit-hash` to allow users to overwrite the tag in a versions.yaml file ([#​422](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/422)) This feature allows users to specify a tag (i.e. main) when they want to update modules. - `chloggen`: support a custom changelog summary template ([#​501](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/501)) The changelog summary template can be customized by configuring a custom template with the `summary_template` configuration setting. The default template provides a starting point for a custom template: https://github.com/open-telemetry/opentelemetry-go-build-tools/blob/v0.13.0/chloggen/internal/chlog/summary.tmpl ##### 🧰 Bug fixes 🧰 - `crosslink`: Fix Windows produces backslashes instead of slashes ([#​458](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/458)) This fixes the issue of Windows produces backslashes instead of slashes when crosslinking dependencies in go.mod files on Windows. - `dbotconf`: Fix Windows produces backslashes instead of slashes ([#​264](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/264)) This fixes the issue of Windows produces backslashes instead of slashes when generating Dependabot configuration files on Windows. - `multimod`: Fix tagging on Windows ([#​464](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/464)) This fixes the issue of `multimod tag` failing on Windows. - `multimod`: Fix to log 'Using versioning file' and 'Successfully deleted module tags' to stderr instead of stdout ([#​507](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/507)) - `chloggen`: change generated files permissions from 0755 to 0644 ([#​457](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/457))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * Update module go.opentelemetry.io/build-tools/chloggen to v0.13.0 (#9697) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/build-tools/chloggen](https://togithub.com/open-telemetry/opentelemetry-go-build-tools) | `v0.12.0` -> `v0.13.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fbuild-tools%2fchloggen/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fbuild-tools%2fchloggen/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fbuild-tools%2fchloggen/v0.12.0/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fbuild-tools%2fchloggen/v0.12.0/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-go-build-tools (go.opentelemetry.io/build-tools/chloggen) ### [`v0.13.0`](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/blob/HEAD/CHANGELOG.md#v0130) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/compare/v0.12.0...v0.13.0) ##### 🛑 Breaking changes 🛑 - `all`: bump minimal Go version to 1.20 ([#​474](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/474)) ##### 💡 Enhancements 💡 - `multimod`: ignore excluded-modules when using sync to update dependencies ([#​442](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/442)) This allows users of the sync command to sync all modules in a monorepo, including those listed in the excluded-modules. This is useful for repositories where some modules may not yet be ready for releasing (therefore listed under excluded-modules) but their dependencies still need to be managed via multimod. - `crosslink`: Add `--skip` flag to ignore specified go modules ([#​480](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/480)) - `multimod`: add support for `--commit-hash` to allow users to overwrite the tag in a versions.yaml file ([#​422](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/422)) This feature allows users to specify a tag (i.e. main) when they want to update modules. - `chloggen`: support a custom changelog summary template ([#​501](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/501)) The changelog summary template can be customized by configuring a custom template with the `summary_template` configuration setting. The default template provides a starting point for a custom template: https://github.com/open-telemetry/opentelemetry-go-build-tools/blob/v0.13.0/chloggen/internal/chlog/summary.tmpl ##### 🧰 Bug fixes 🧰 - `crosslink`: Fix Windows produces backslashes instead of slashes ([#​458](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/458)) This fixes the issue of Windows produces backslashes instead of slashes when crosslinking dependencies in go.mod files on Windows. - `dbotconf`: Fix Windows produces backslashes instead of slashes ([#​264](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/264)) This fixes the issue of Windows produces backslashes instead of slashes when generating Dependabot configuration files on Windows. - `multimod`: Fix tagging on Windows ([#​464](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/464)) This fixes the issue of `multimod tag` failing on Windows. - `multimod`: Fix to log 'Using versioning file' and 'Successfully deleted module tags' to stderr instead of stdout ([#​507](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/507)) - `chloggen`: change generated files permissions from 0755 to 0644 ([#​457](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/457))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * Add a workflow to test otelcorecol as a Windows service (#9689) **Description:** Adding a workflow to fix #6455 this will also be needed when fixing #5300 Fixes #6455 **Link to tracking Issue:** #6455 * Update module go.opentelemetry.io/build-tools/checkfile to v0.13.0 (#9696) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/build-tools/checkfile](https://togithub.com/open-telemetry/opentelemetry-go-build-tools) | `v0.12.0` -> `v0.13.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fbuild-tools%2fcheckfile/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fbuild-tools%2fcheckfile/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fbuild-tools%2fcheckfile/v0.12.0/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fbuild-tools%2fcheckfile/v0.12.0/v0.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-go-build-tools (go.opentelemetry.io/build-tools/checkfile) ### [`v0.13.0`](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/blob/HEAD/CHANGELOG.md#v0130) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/compare/v0.12.0...v0.13.0) ##### 🛑 Breaking changes 🛑 - `all`: bump minimal Go version to 1.20 ([#​474](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/474)) ##### 💡 Enhancements 💡 - `multimod`: ignore excluded-modules when using sync to update dependencies ([#​442](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/442)) This allows users of the sync command to sync all modules in a monorepo, including those listed in the excluded-modules. This is useful for repositories where some modules may not yet be ready for releasing (therefore listed under excluded-modules) but their dependencies still need to be managed via multimod. - `crosslink`: Add `--skip` flag to ignore specified go modules ([#​480](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/480)) - `multimod`: add support for `--commit-hash` to allow users to overwrite the tag in a versions.yaml file ([#​422](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/422)) This feature allows users to specify a tag (i.e. main) when they want to update modules. - `chloggen`: support a custom changelog summary template ([#​501](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/501)) The changelog summary template can be customized by configuring a custom template with the `summary_template` configuration setting. The default template provides a starting point for a custom template: https://github.com/open-telemetry/opentelemetry-go-build-tools/blob/v0.13.0/chloggen/internal/chlog/summary.tmpl ##### 🧰 Bug fixes 🧰 - `crosslink`: Fix Windows produces backslashes instead of slashes ([#​458](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/458)) This fixes the issue of Windows produces backslashes instead of slashes when crosslinking dependencies in go.mod files on Windows. - `dbotconf`: Fix Windows produces backslashes instead of slashes ([#​264](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/264)) This fixes the issue of Windows produces backslashes instead of slashes when generating Dependabot configuration files on Windows. - `multimod`: Fix tagging on Windows ([#​464](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/464)) This fixes the issue of `multimod tag` failing on Windows. - `multimod`: Fix to log 'Using versioning file' and 'Successfully deleted module tags' to stderr instead of stdout ([#​507](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/507)) - `chloggen`: change generated files permissions from 0755 to 0644 ([#​457](https://togithub.com/open-telemetry/opentelemetry-go-build-tools/issues/457))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * [docs][chore] warning for using localhost in security-best-practices (#9444) **Description:** warning and alert for using localhost which might go under DNS resolution and end up with an unexpected IP, risking security. **Link to tracking Issue:** #9338 **Documentation:** Added Waring and risk alert in https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/security-best-practices.md --------- Co-authored-by: Pablo Baeyens * [component] Change component.Type underlying type to a struct (#9472) **Description:** Follow up to #9414 and open-telemetry/opentelemetry-collector-contrib/pull/31038. **Link to tracking Issue:** Fixes #9208. * [chore] Bump go version in CI (#9716) * [chore] [exporterhelper] Update notes for the experimental API (#9719) Addressing https://github.com/open-telemetry/opentelemetry-collector/pull/8685#discussion_r1514315859 * Update module github.com/shirou/gopsutil/v3 to v3.24.2 (#9692) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [github.com/shirou/gopsutil/v3](https://togithub.com/shirou/gopsutil) | `v3.24.1` -> `v3.24.2` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fshirou%2fgopsutil%2fv3/v3.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/github.com%2fshirou%2fgopsutil%2fv3/v3.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/github.com%2fshirou%2fgopsutil%2fv3/v3.24.1/v3.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fshirou%2fgopsutil%2fv3/v3.24.1/v3.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
shirou/gopsutil (github.com/shirou/gopsutil/v3) ### [`v3.24.2`](https://togithub.com/shirou/gopsutil/compare/v3.24.1...v3.24.2) [Compare Source](https://togithub.com/shirou/gopsutil/compare/v3.24.1...v3.24.2)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] bump deps in tools (#9721) This addresses an indirect import of the protobuf lib. Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [confmap] Remove provider.New (#9698) **Description:** Follow up to #9443 - deleting the deprecated `New` methods on providers. * [chore] remove contents of roadmap (#9720) This is in preparation of the next PR which will introduce the new proposal for achieving a v1 release of the Collector. The idea being that we wanted to collect feedback on the proposal without having to deal with conflicts/changes in the old outdated document. Related to #9718 Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [exporterhelper] Turn panics into errors (#9717) * [config/configtls] Validate MinVersion and MaxVersion (#9664) **Description:** Add `Validate()` method to `TLSSetting` and validate tls `min_version` and `max_version`. **Link to tracking Issue:** #9475 * [configcompression] Mark as stable (#9571) **Description:** Mark `configcompression` as Stable **Link to tracking Issue:** Closes https://github.com/open-telemetry/opentelemetry-collector/issues/9374 --------- Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [exporter/otlphttp] enable lifecycle tests (#9722) enable lifecycle tests for otlphttpexporter **Link to tracking Issue:** fix #9685 Signed-off-by: Ziqi Zhao * [chore] [exporterhelper] Update docs to remove requeuing (#9723) * [exporterhelper] Introduce batching functionality (#8685) This change introduces new experimental batching functionality to the exporter helper. The batch sender is fully concurrent and synchronous. It's set after the queue sender, which, if enabled, introduces the asynchronous behavior and ensures no data loss with the permanent queue. Follow-up TODO list: - Add pre-built merge funcs for pdata - Handle partial errors - A missing part compared to the batch processor is the ability to shard the batches by context value. Updates https://github.com/open-telemetry/opentelemetry-collector/issues/8122 * [chore][Feature Request Template] Comment out header descriptions (#9732) **Description:** The descriptions for each header in the feature request template for this repository are useful to the person filing a request, but serve no purpose to the issue reader. These can be commented out to in the displayed markdown to save the user from having to delete each one (or if not deleted, save the reader from having to parse through extra information). * Remove deprecated obsreport/obsreporttest package (#9724) All API in the package was deprecated in 0.93.0 * use generated meter (#9669) This follows #9556 and uses the Meter func instead of managing the scope in the batch processor manually. Replaces #9581 Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Update github-actions deps (#9743) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [Wandalen/wretry.action](https://togithub.com/Wandalen/wretry.action) | action | patch | `v1.4.5` -> `v1.4.9` | | [actions/cache](https://togithub.com/actions/cache) | action | patch | `v4.0.0` -> `v4.0.1` | --- ### Release Notes
Wandalen/wretry.action (Wandalen/wretry.action) ### [`v1.4.9`](https://togithub.com/Wandalen/wretry.action/compare/v1.4.8...v1.4.9) [Compare Source](https://togithub.com/Wandalen/wretry.action/compare/v1.4.8...v1.4.9) ### [`v1.4.8`](https://togithub.com/Wandalen/wretry.action/compare/v1.4.7...v1.4.8) [Compare Source](https://togithub.com/Wandalen/wretry.action/compare/v1.4.7...v1.4.8) ### [`v1.4.7`](https://togithub.com/Wandalen/wretry.action/compare/v1.4.6...v1.4.7) [Compare Source](https://togithub.com/Wandalen/wretry.action/compare/v1.4.6...v1.4.7) ### [`v1.4.6`](https://togithub.com/Wandalen/wretry.action/compare/v1.4.5...v1.4.6) [Compare Source](https://togithub.com/Wandalen/wretry.action/compare/v1.4.5...v1.4.6)
actions/cache (actions/cache) ### [`v4.0.1`](https://togithub.com/actions/cache/releases/tag/v4.0.1) [Compare Source](https://togithub.com/actions/cache/compare/v4.0.0...v4.0.1) ##### What's Changed - Update README.md by [@​yacaovsnc](https://togithub.com/yacaovsnc) in [https://github.com/actions/cache/pull/1304](https://togithub.com/actions/cache/pull/1304) - Update examples by [@​yacaovsnc](https://togithub.com/yacaovsnc) in [https://github.com/actions/cache/pull/1305](https://togithub.com/actions/cache/pull/1305) - Update actions/cache publish flow by [@​bethanyj28](https://togithub.com/bethanyj28) in [https://github.com/actions/cache/pull/1340](https://togithub.com/actions/cache/pull/1340) - Update [@​actions/cache](https://togithub.com/actions/cache) by [@​bethanyj28](https://togithub.com/bethanyj28) in [https://github.com/actions/cache/pull/1341](https://togithub.com/actions/cache/pull/1341) ##### New Contributors - [@​yacaovsnc](https://togithub.com/yacaovsnc) made their first contribution in [https://github.com/actions/cache/pull/1304](https://togithub.com/actions/cache/pull/1304) **Full Changelog**: https://github.com/actions/cache/compare/v4...v4.0.1
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * [exporter/otlp] enable lifecycle test (#9735) **Description:** enable lifecycle test for otlpexporter **Link to tracking Issue:** fix #9684 Signed-off-by: Ziqi Zhao * [chore] group build-tools packages (#9742) Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [confmap] confmap honors `Unmarshal` methods on config embedded structs. (#9635) **Description:** This implements support for calling `Unmarshal` on embedded structs of structs being decoded. **Link to tracking Issue:** Fixes #6671 **Testing:** Unit tests. Contrib fix is open: https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/31406 * [exporterhelper] Fix persistent queue size backup on reads (#9740) **Description:** Persistent queue size backup on reads should depend on readIndex, not writeIndex. * Give NoOp create settings a unique name (#9637) Long story, but i'm working on updating the prometheus dependency: https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/30934 As part of that update, we need to adapt to a change that makes the prometheus servers' self-observability metrics independent. See https://github.com/prometheus/prometheus/issues/13507 and https://github.com/prometheus/prometheus/pull/13610 One way to adapt to this change is by adding a label to each receivers' metrics to differentiate one Prometheus receiver from another. I've tried taking that approach in https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/30934, but the current issue is that the NoOp components all have the same name, which causes the self-observability metrics to collide. I can work around this in the prometheus receiver's own tests, but I can't work around the issue in the `generated_component_test.go` tests, since those are generated. This PR makes the ID returned by `NewNopCreateSettings` unique by giving it a unique name. **Link to tracking Issue:** Part of https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/30883 cc @Aneurysm9 --------- Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Update github/codeql-action action to v3.24.7 (#9744) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [github/codeql-action](https://togithub.com/github/codeql-action) | action | patch | `v3.24.6` -> `v3.24.7` | --- ### Release Notes
github/codeql-action (github/codeql-action) ### [`v3.24.7`](https://togithub.com/github/codeql-action/compare/v3.24.6...v3.24.7) [Compare Source](https://togithub.com/github/codeql-action/compare/v3.24.6...v3.24.7)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * [exporter/nopexporter] Add the nopexporter (#9448) **Description:** Add the nopexporter. This can be helpful if a user wants to start the Collector with a dummy pipeline to only enable extensions. It could also be used to test Collector pipeline throughput. **Link to tracking Issue:** Resolves https://github.com/open-telemetry/opentelemetry-collector/issues/7316 **Testing:** Added lifecycle tests; the receiver doesn't do anything. **Documentation:** Added a readme for the component. cc @djaglowski @tigrannajaryan * [receiver/nopreceiver] Add the nopreceiver (#9446) **Description:** Add the nopreceiver. This can be helpful if a user wants to start the Collector with a dummy pipeline to only enable extensions. It could also be used to start a dynamically-configured Collector that starts with no config and waits to receive its config from a confmap.Provider that supports reloads. **Link to tracking Issue:** Works toward https://github.com/open-telemetry/opentelemetry-collector/issues/7316 **Testing:** Added lifecycle tests; the receiver doesn't do anything. **Documentation:** Added a readme for the component. * [chore] Run make gotidy to fix the CI (#9747) * [chore] group golang.org/x packages (#9741) Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] Fix an incorrect automatic replace made by a bot in `otel-config.yml` (#9746) This PR fixes an incorrect automatic replace made in the `otel-config.yml` file in this [pull request](https://github.com/open-telemetry/opentelemetry-collector/pull/9680/files#diff-c7c8156618a7f8126b25ca1bdfde3e172a0d2cb75c533d63a71617ae2a5c54ae) by a bot. I've taken the previous value which seems right. Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] Move resource test to service/internal/resource (#9730) **Description:** This test was out of place! Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] tidy code to return directly (#9751) * [chore] Refactor mdatagen unmarshaling to use less custom Unmarshalers (#9760) Now that we support embedded structs unmarshaling, we can simplify the code handling metric data unmarshaling somewhat. * [exporterhelper] Fix race in concurrency check in batch sender leading to smaller batch sizes (#9761) **Description:** Although activeRequests is atomic, it is possible for 2 arriving requests to both increment activeRequests, and when entering the critical section of bs.activeRequests.Load() >= bs.concurrencyLimit, both times it evaluates to true. The correct behavior should be that only the 2nd check is true. Remove the workaround in tests that bypassed the bug. --- Even with this change, the results are slightly better but still depend on goroutine scheduling. * [chore] Remove the top level error if it indicates an empty name (#9763) This is a split of #9750 that tries to work around mapstructure, which wraps an error around a decoding error. In the case when an error is returned from a top level construct, we get a not so helpful message that says: ``` error decoding '': error running encode hook: marshaling error ``` With this change, the error is unwrapped, giving the following string representation: ``` error running encode hook: marshaling error ``` Because #9750 enforces going through mapstructure, it would change errors returned with this not-so-helpful preamble. Adding this removes the problem. * [chore] change the way we unmarshal the config in tests (#9765) This change is required in preparation of #9750 This removes the call to `component.UnmarshalConfig` in preparation of its deprecation, and instead has the `Conf` object unmarshal itself into the `Config` struct. * [chore] Remove the development warning from readme for persistent queue (#9766) Removing the alpha status with the warning as discussed in the latest Collecor SIG meeting. cc @swiatekm-sumo * [chore] Remove `telemetry.useOtelForInternalMetrics` stable feature gate (#9752) **Description:** Remove the stable feature gate `telemetry.useOtelForInternalMetrics`. It was declared stable in 0.95.0. * [cmd/mdatagen] optimize mdatagen for batchprocessor failed test (#9768) **Description:** fix #9688 The batchprocessor use a `batchProcessor` as a common struct which implements `consumer.Traces`, `consumer.Metrics`, `consumer.Logs` in the meantime. As a result, the generated lifecycle test will fail, since when it create a metrics, traces processor object, it will still fall to the case `consumer.Logs` and panic. ``` === RUN TestComponentLifecycle/metrics-shutdown === RUN TestComponentLifecycle/metrics-lifecycle panic: interface conversion: interface {} is plog.Logs, not pmetric.Metrics goroutine 37 [running]: go.opentelemetry.io/collector/processor/batchprocessor.(*batchMetrics).add(0x14000208120?, {0x10572aae0?, 0x1400029c3f0?}) /Users/zhaoziqi/Documents/go/src/go.opentelemetry.io/opentelemetry-collector/processor/batchprocessor/batch_processor.go:450 +0x208 go.opentelemetry.io/collector/processor/batchprocessor.(*shard).processItem(0x14000292200, {0x10572aae0?, 0x1400029c3f0?}) /Users/zhaoziqi/Documents/go/src/go.opentelemetry.io/opentelemetry-collector/processor/batchprocessor/batch_processor.go:226 +0x38 go.opentelemetry.io/collector/processor/batchprocessor.(*shard).start(0x14000292200) /Users/zhaoziqi/Documents/go/src/go.opentelemetry.io/opentelemetry-collector/processor/batchprocessor/batch_processor.go:199 +0x1a0 created by go.opentelemetry.io/collector/processor/batchprocessor.(*batchProcessor).newShard in goroutine 36 /Users/zhaoziqi/Documents/go/src/go.opentelemetry.io/opentelemetry-collector/processor/batchprocessor/batch_processor.go:160 +0x1a4 exit status 2 FAIL go.opentelemetry.io/collector/processor/batchprocessor 0.594s ``` **Link to tracking Issue:** fix #9688 --------- Signed-off-by: Ziqi Zhao * [confignet] Change `Transport` from `string` to `TransportType` (#9385) **Description:** Changes `Transport` from a `string` to a new `TransportType`. Implements `UnmarshalText` for `TransportType` to enforce values. This PR may be too much - it introduces a breaking change a lot of new public APIs that may not be worth it for such a small module. If we don't like the surface area this creates or the breaking change, but we still want to enforce transport type values, I think implementing `Validate` keeps the API footprint smaller and isn't breaking. **Link to tracking Issue:** Closes https://github.com/open-telemetry/opentelemetry-collector/issues/9364 **Documentation:** Added godoc comments --------- Co-authored-by: Pablo Baeyens * Update module go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc to v0.49.0 (#9493) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc](https://togithub.com/open-telemetry/opentelemetry-go-contrib) | `v0.47.0` -> `v0.49.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fgoogle.golang.org%2fgrpc%2fotelgrpc/v0.49.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fgoogle.golang.org%2fgrpc%2fotelgrpc/v0.49.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fgoogle.golang.org%2fgrpc%2fotelgrpc/v0.47.0/v0.49.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fgoogle.golang.org%2fgrpc%2fotelgrpc/v0.47.0/v0.49.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Revert "[chore] change the way we unmarshal the config in tests" (#9771) Reverts open-telemetry/opentelemetry-collector#9765 We need to revert those changes as contrib has issues with them in isolation from #9750. * Respect telemetry configuration when running as a Windows service (#9726) **Description:** Fixes #5300 With this change the service telemetry section is respected by the collector when running as a Windows service. Log lever can be used to control the verbosity of the events logged and the logger can be redirected to a file by specifying an output path on the service telemetry config. By default `stdout` and `stderr` are redirected to the event log when running as a Windows service to keep the current behavior. The code change itself was made with a focus of not breaking the public APIs and not reading the config more than once. That said it is probably something to be refactored when the public APIs can be touched again. **Link to tracking Issue:** #5300 **Testing:** The test is an integration test that depends on the actual executable. It checks for event publication and file output. * Revert "[chore] Refactor mdatagen unmarshaling to use less custom Unmarshalers" (#9773) Reverts open-telemetry/opentelemetry-collector#9760 Trying to make contrib happy. We will be back with a unit test covering contrib's usage of mdatagen. * [chore] use the new function name in comment (#9781) `ReportComponentStatus` is now deprecated, and `ReportStatus` is used instead. * [chore] add new metric with input_type configuration (#9784) **Description:** Making sure we can test input_type moving forward. **Link to tracking Issue:** Fixes #9777 * [configgrpc] Deprecate SanitizedEndpoint (#9788) **Description:** Deprecates `configgrpc.SanitizedEndpoint()`. **Link to tracking Issue:** Works towards: https://github.com/open-telemetry/opentelemetry-collector/issues/9482 * [chore] rework memorylimiter test to avoid flaky tests (#9733) Peeling this set of changes from #9584 as a separate PR. These changes allow a reduction of issues when working with ARM64, which seems to fail on some of the resource locking used in those tests. * [chore][status] Remove deprecated functions `ReportComponentStatus` and `ReportComponentOkIfStarting` (#9782) **Description:** Remove deprecated functions `ReportComponentStatus` and `ReportComponentOkIfStarting` **Link to tracking Issue:** See #9148 * [receiver] Remove deprecated `ScraperControllerSettings` and `NewDefaultScraperControllerSettings` (#9783) **Description:** Remove deprecated `ScraperControllerSettings` and `NewDefaultScraperControllerSettings` **Link to tracking Issue:** #6767 * [connector] Remove deprecated interfaces LogsRouter, MetricsRouter and TracesRouter (#9780) **Description:** Remove deprecated interfaces LogsRouter, MetricsRouter and TracesRouter. **Link to tracking Issue:** Follow up to #9095 * [component] Remove deprecated error `ErrNilNextConsumer` (#9779) **Description:** Remove deprecated error `ErrNilNextConsumer` **Link to tracking Issue:** Fixes #9322 * Update module gonum.org/v1/gonum to v0.15.0 (#9791) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | gonum.org/v1/gonum | `v0.14.0` -> `v0.15.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/gonum.org%2fv1%2fgonum/v0.15.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/gonum.org%2fv1%2fgonum/v0.15.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/gonum.org%2fv1%2fgonum/v0.14.0/v0.15.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/gonum.org%2fv1%2fgonum/v0.14.0/v0.15.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * [CONTRIBUTING.md] Update golang version (#9792) **Description:** As of the referenced issue, this project's minimum supported version is 1.21. Documentation should accurately reflect this. **Link to tracking Issue:** https://github.com/open-telemetry/opentelemetry-collector/pull/9533 * Update github-actions deps (#9790) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [Wandalen/wretry.action](https://togithub.com/Wandalen/wretry.action) | action | patch | `v1.4.9` -> `v1.4.10` | | [actions/cache](https://togithub.com/actions/cache) | action | patch | `v4.0.1` -> `v4.0.2` | | [github/codeql-action](https://togithub.com/github/codeql-action) | action | patch | `v3.24.7` -> `v3.24.8` | --- ### Release Notes
Wandalen/wretry.action (Wandalen/wretry.action) ### [`v1.4.10`](https://togithub.com/Wandalen/wretry.action/compare/v1.4.9...v1.4.10) [Compare Source](https://togithub.com/Wandalen/wretry.action/compare/v1.4.9...v1.4.10)
actions/cache (actions/cache) ### [`v4.0.2`](https://togithub.com/actions/cache/compare/v4.0.1...v4.0.2) [Compare Source](https://togithub.com/actions/cache/compare/v4.0.1...v4.0.2)
github/codeql-action (github/codeql-action) ### [`v3.24.8`](https://togithub.com/github/codeql-action/compare/v3.24.7...v3.24.8) [Compare Source](https://togithub.com/github/codeql-action/compare/v3.24.7...v3.24.8)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * [confignet] added NewDefaultFunctions (#9671) **Description:** Added newDefault methods for structs in confignet package **Link to tracking Issue:** closes #9656 **Testing:** Tests were added for the newDefault functions **Documentation:** godoc --------- Co-authored-by: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com> * [configgrpc] Remove deprecated func, add ToServer with context (#9787) **Description:** Removes deprecated `ToServer`. Deprecate `ToServerContext` Add new `ToServer` with `context.Context`. **Link to tracking Issue:** Related to https://github.com/open-telemetry/opentelemetry-collector/issues/9490 --------- Co-authored-by: Dmitrii Anoshin * Nicer error message when passing an empty configuration file (#9762) This PR checks if `cfg.Validate()` error is `errMissingReceivers` error then returns a nicely formated error. * [otlphttpexporter] return nil from partial success handler when HTTP response body is empty (#9667) **Description:** Fixing a bug - When exporting using the otlphttpexporter, after receiving a successful HTTP response, when the response body's content length is 0 and the content type is specified as either "application/json" or "application/x-protobuf", an attempt will be made to unmarshal a nil value within any of the partial success response handler functions. This results in an error, and a potential resend of the original export request. To fix this scenario, a check was added to the `tracesPartialSuccessHandler`, `metricsPartialSuccessHandler`, and `logsPartialSuccessHandler` functions for a `nil` value in the `protoBytes` argument. When `nil`, the function will return with a `nil` value, indicating the absence of any error. **Link to tracking Issue:** #9666 * [chore] arm64 build (#9584) This PR adds a linux/arm64 build to the build of the collector, so it may support the goal of #9731 * Prevent starting unnecessary goroutines (#9817) Fixes https://github.com/open-telemetry/opentelemetry-collector/issues/9739 Replaces https://github.com/open-telemetry/opentelemetry-collector/pull/9814 Signed-off-by: Bogdan Drutu * [chore] Propose clarification to first step of release process (#9830) * [chore] Prepare release v1.4.0/v0.97.0 (#9832) The following commands were run to prepare this release: - make chlog-update VERSION=v1.4.0/v0.97.0 - make prepare-release PREVIOUS_VERSION=1.3.0 RELEASE_CANDIDATE=1.4.0 MODSET=stable - make prepare-release PREVIOUS_VERSION=0.96.0 RELEASE_CANDIDATE=0.97.0 MODSET=beta * [chore] Cleanup the v1.4.0/v0.97.0 changelog (#9834) Move API changes to the CHANGELOG-API.md and remove redundant entries * Update github/codeql-action action to v3.24.9 (#9839) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [github/codeql-action](https://togithub.com/github/codeql-action) | action | patch | `v3.24.8` -> `v3.24.9` | --- ### Release Notes
github/codeql-action (github/codeql-action) ### [`v3.24.9`](https://togithub.com/github/codeql-action/compare/v3.24.8...v3.24.9) [Compare Source](https://togithub.com/github/codeql-action/compare/v3.24.8...v3.24.9)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * [confmap] log a warning when using $VAR in config (WIP) (#9547) **Description:** As requested by @mx-psi , added a no-op log for when variables using the deprecated $VAR style are used. The logger should be replaced once it is clear how to pass it down (see #9443). Also, from my testing, the function passed to os.Expand is in fact only run when we have $VAR and not for ${env:VAR}, so I did not add additional checking. **Link to tracking Issue:** #9162 **Testing:** I am not sure how to go about testing it, since we are not passing a logger in yet, there is no easy way to know what is being logged or what the map looks like. Some ideas on this would be appreciated --------- Co-authored-by: Pablo Baeyens * Update module go.opentelemetry.io/collector/receiver/otlpreceiver to v0.97.0 (#9847) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/collector/receiver/otlpreceiver](https://togithub.com/open-telemetry/opentelemetry-collector) | `v0.96.0` -> `v0.97.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.97.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.97.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.96.0/v0.97.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.96.0/v0.97.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-collector (go.opentelemetry.io/collector/receiver/otlpreceiver) ### [`v0.97.0`](https://togithub.com/open-telemetry/opentelemetry-collector/blob/HEAD/CHANGELOG.md#v140v0970) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-collector/compare/v0.96.0...v0.97.0) ##### 🛑 Breaking changes 🛑 - `telemetry`: Remove telemetry.useOtelForInternalMetrics stable feature gate ([#​9752](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9752)) ##### 🚀 New components 🚀 - `exporter/nop`: Add the `nopexporter` to serve as a placeholder exporter in a pipeline ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) This is primarily useful for starting the Collector with only extensions enabled or to test Collector pipeline throughput. - `receiver/nop`: Add the `nopreceiver` to serve as a placeholder receiver in a pipeline ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) This is primarily useful for starting the Collector with only extensions enabled. ##### 💡 Enhancements 💡 - `configtls`: Validates TLS min_version and max_version ([#​9475](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9475)) Introduces `Validate()` method in TLSSetting. - `configcompression`: Mark module as Stable. ([#​9571](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9571)) - `cmd/mdatagen`: Use go package name for the scope name by default and add an option to provide the scope name in metadata.yaml. ([#​9693](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9693)) - `cmd/mdatagen`: Generate the lifecycle tests for components by default. ([#​9683](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9683)) It's encouraged to have lifecycle tests for all components enadled, but they can be disabled if needed in metadata.yaml with `skip_lifecycle: true` and `skip_shutdown: true` under `tests` section. - `cmd/mdatagen`: optimize the mdatagen for the case like batchprocessor which use a common struct to implement consumer.Traces, consumer.Metrics, consumer.Logs in the meantime. ([#​9688](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9688)) ##### 🧰 Bug fixes 🧰 - `exporterhelper`: Fix persistent queue size backup on reads. ([#​9740](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9740)) - `processor/batch`: Prevent starting unnecessary goroutines. ([#​9739](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9739)) - `otlphttpexporter`: prevent error on empty response body when content type is application/json ([#​9666](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9666)) - `confmap`: confmap honors `Unmarshal` methods on config embedded structs. ([#​6671](https://togithub.com/open-telemetry/opentelemetry-collector/issues/6671)) - `otelcol`: Respect telemetry configuration when running as a Windows service ([#​5300](https://togithub.com/open-telemetry/opentelemetry-collector/issues/5300))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update module go.opentelemetry.io/collector/exporter/otlpexporter to v0.97.0 (#9842) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/collector/exporter/otlpexporter](https://togithub.com/open-telemetry/opentelemetry-collector) | `v0.96.0` -> `v0.97.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.97.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.97.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.96.0/v0.97.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.96.0/v0.97.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-collector (go.opentelemetry.io/collector/exporter/otlpexporter) ### [`v0.97.0`](https://togithub.com/open-telemetry/opentelemetry-collector/blob/HEAD/CHANGELOG.md#v140v0970) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-collector/compare/v0.96.0...v0.97.0) ##### 🛑 Breaking changes 🛑 - `telemetry`: Remove telemetry.useOtelForInternalMetrics stable feature gate ([#​9752](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9752)) ##### 🚀 New components 🚀 - `exporter/nop`: Add the `nopexporter` to serve as a placeholder exporter in a pipeline ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) This is primarily useful for starting the Collector with only extensions enabled or to test Collector pipeline throughput. - `receiver/nop`: Add the `nopreceiver` to serve as a placeholder receiver in a pipeline ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) This is primarily useful for starting the Collector with only extensions enabled. ##### 💡 Enhancements 💡 - `configtls`: Validates TLS min_version and max_version ([#​9475](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9475)) Introduces `Validate()` method in TLSSetting. - `configcompression`: Mark module as Stable. ([#​9571](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9571)) - `cmd/mdatagen`: Use go package name for the scope name by default and add an option to provide the scope name in metadata.yaml. ([#​9693](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9693)) - `cmd/mdatagen`: Generate the lifecycle tests for components by default. ([#​9683](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9683)) It's encouraged to have lifecycle tests for all components enadled, but they can be disabled if needed in metadata.yaml with `skip_lifecycle: true` and `skip_shutdown: true` under `tests` section. - `cmd/mdatagen`: optimize the mdatagen for the case like batchprocessor which use a common struct to implement consumer.Traces, consumer.Metrics, consumer.Logs in the meantime. ([#​9688](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9688)) ##### 🧰 Bug fixes 🧰 - `exporterhelper`: Fix persistent queue size backup on reads. ([#​9740](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9740)) - `processor/batch`: Prevent starting unnecessary goroutines. ([#​9739](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9739)) - `otlphttpexporter`: prevent error on empty response body when content type is application/json ([#​9666](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9666)) - `confmap`: confmap honors `Unmarshal` methods on config embedded structs. ([#​6671](https://togithub.com/open-telemetry/opentelemetry-collector/issues/6671)) - `otelcol`: Respect telemetry configuration when running as a Windows service ([#​5300](https://togithub.com/open-telemetry/opentelemetry-collector/issues/5300))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update Wandalen/wretry.action action to v2 (#9849) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [Wandalen/wretry.action](https://togithub.com/Wandalen/wretry.action) | action | major | `v1.4.10` -> `v2.1.0` | --- ### Release Notes
Wandalen/wretry.action (Wandalen/wretry.action) ### [`v2.1.0`](https://togithub.com/Wandalen/wretry.action/compare/v2.0.0...v2.1.0) [Compare Source](https://togithub.com/Wandalen/wretry.action/compare/v2.0.0...v2.1.0) ### [`v2.0.0`](https://togithub.com/Wandalen/wretry.action/compare/v1.4.10...v2.0.0) [Compare Source](https://togithub.com/Wandalen/wretry.action/compare/v1.4.10...v2.0.0)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * [configtls] Update IncludeSystemCACertsPool to be used in server and client RootCAs (#9835) **Description:** Updates `ServerConfig` and `ClientConfig` to use `IncludeSystemCACertsPool` when doing `LoadTLSConfig`. Previously `IncludeSystemCACertsPool` was only used for `ServerConfig`'s `ClientCAs` via `newClientCAsReloader`. **Link to tracking Issue:** Closes https://github.com/open-telemetry/opentelemetry-collector/issues/9789 **Testing:** Added more tests * [chore][docs] Move RFC to a new RFCs folder (#9828) **Description:** Some housekeeping to organize the `docs` folder. I intend to file a new RFC-ish soon. **Link to tracking Issue:** Fixes #8893 * [chore] Do not log warning when feature gate is enabled (#9852) **Description:** Fixes #9753 * [client] Remove experimental comment from `Metadata` (#9796) **Description:** Removes the `experimental` tag from `Metadata`. This feature has been used in the headerssetter extension since Aug 2022. **Link to tracking Issue:** Relates to https://github.com/open-telemetry/opentelemetry-collector/issues/9381 Related to https://github.com/open-telemetry/opentelemetry-collector/issues/9795 * [receiver/otlp] Return proper http response code based on retryable errors (#9357) **Description:** Updates the receiver's http response to return a proper http status based on whether or not the pipeline returned a retryable error. Builds upon the work done in https://github.com/open-telemetry/opentelemetry-collector/pull/8080 and https://github.com/open-telemetry/opentelemetry-collector/pull/9307 **Link to tracking Issue:** Closes https://github.com/open-telemetry/opentelemetry-collector/issues/9337 Closes https://github.com/open-telemetry/opentelemetry-collector/issues/8132 Closes https://github.com/open-telemetry/opentelemetry-collector/issues/9636 Closes https://github.com/open-telemetry/opentelemetry-collector/issues/6725 **Testing:** Updated lots of unit tests * [configtls] Add context.Context to public functions (#9813) **Description:** Opening this PR to prompt discussion about `configtls` and `context.Context`. We could add `context.Context` to these public functions and go through the long deprecation/rename process, but I want to make sure it is valuable. Arguments against this PR: - There isn't anything within these functions that currently rely on a `context.Context`. - There isn't anything inside these functions interact with the network. Arguments in favor of this PR: - Interacts with filesystem. - Go best practice to allow passing context. **Link to tracking Issue:** Related to https://github.com/open-telemetry/opentelemetry-collector/issues/9811 --------- Co-authored-by: Andrzej Stencel * [configtls] Removed deprecated structs (#9786) **Description:** Removed deprecated structs **Link to tracking Issue:** Related to https://github.com/open-telemetry/opentelemetry-collector/issues/9428 Related to https://github.com/open-telemetry/opentelemetry-collector/issues/9474 Closes https://github.com/open-telemetry/opentelemetry-collector/issues/9548 * [component] make Type implement MarshalText (#9856) **Description:** Adds `MarshalText` function so that `Type` can be properly marshaled as yaml. **Link to tracking Issue:** Fixes https://github.com/open-telemetry/opentelemetry-collector/issues/9855 * [otlp exporter] Validate exporter endpoint has port (#9632) **Description:** This PR updates the otlp exporter config validation to ensure that the "endpoint" specified for the exporter includes a port. The goal of this is to fail fast if the configuration is invalid instead of waiting for an error to arise. The PR adds a function to the ClientConfig defined in configgrpc that parses the port defined in the endpoint. The otlp exporter uses this port parsing to validate that **Link to tracking Issue:** [Issue 9505](https://github.com/open-telemetry/opentelemetry-collector/issues/9505) * Fix validate command (#9866) **Description:** Fixes issue where validate command was not properly printing valid values. **Link to tracking Issue:** Closes https://github.com/open-telemetry/opentelemetry-collector/issues/9863 **Testing:** Updated unit tests * Update module go.opentelemetry.io/collector/exporter/otlphttpexporter to v0.97.0 (#9846) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/collector/exporter/otlphttpexporter](https://togithub.com/open-telemetry/opentelemetry-collector) | `v0.96.0` -> `v0.97.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.97.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.97.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.96.0/v0.97.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.96.0/v0.97.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-collector (go.opentelemetry.io/collector/exporter/otlphttpexporter) ### [`v0.97.0`](https://togithub.com/open-telemetry/opentelemetry-collector/blob/HEAD/CHANGELOG.md#v140v0970) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-collector/compare/v0.96.0...v0.97.0) ##### 🛑 Breaking changes 🛑 - `telemetry`: Remove telemetry.useOtelForInternalMetrics stable feature gate ([#​9752](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9752)) ##### 🚀 New components 🚀 - `exporter/nop`: Add the `nopexporter` to serve as a placeholder exporter in a pipeline ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) This is primarily useful for starting the Collector with only extensions enabled or to test Collector pipeline throughput. - `receiver/nop`: Add the `nopreceiver` to serve as a placeholder receiver in a pipeline ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) This is primarily useful for starting the Collector with only extensions enabled. ##### 💡 Enhancements 💡 - `configtls`: Validates TLS min_version and max_version ([#​9475](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9475)) Introduces `Validate()` method in TLSSetting. - `configcompression`: Mark module as Stable. ([#​9571](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9571)) - `cmd/mdatagen`: Use go package name for the scope name by default and add an option to provide the scope name in metadata.yaml. ([#​9693](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9693)) - `cmd/mdatagen`: Generate the lifecycle tests for components by default. ([#​9683](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9683)) It's encouraged to have lifecycle tests for all components enadled, but they can be disabled if needed in metadata.yaml with `skip_lifecycle: true` and `skip_shutdown: true` under `tests` section. - `cmd/mdatagen`: optimize the mdatagen for the case like batchprocessor which use a common struct to implement consumer.Traces, consumer.Metrics, consumer.Logs in the meantime. ([#​9688](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9688)) ##### 🧰 Bug fixes 🧰 - `exporterhelper`: Fix persistent queue size backup on reads. ([#​9740](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9740)) - `processor/batch`: Prevent starting unnecessary goroutines. ([#​9739](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9739)) - `otlphttpexporter`: prevent error on empty response body when content type is application/json ([#​9666](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9666)) - `confmap`: confmap honors `Unmarshal` methods on config embedded structs. ([#​6671](https://togithub.com/open-telemetry/opentelemetry-collector/issues/6671)) - `otelcol`: Respect telemetry configuration when running as a Windows service ([#​5300](https://togithub.com/open-telemetry/opentelemetry-collector/issues/5300))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * [chore] Remove vendor distributions mentions in metadata.yaml (#9865) Related to https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/30657 This removes all distributions linked to this repository maintained outside of OpenTelemetry. Co-authored-by: Dmitrii Anoshin * [exporterhelper] Add default batching for OTLP data type (#9738) Introduce default batching functionality based on the internal data type (pdata). This makes the exporter batching capability available to the regular exporter helpers without using custom requests. Updates #8122 * [cmd/mdatagen] add unsupported platforms to the README header (#9803) **Description:** Add unsupported platforms to the README header **Link to tracking Issue:** Fixes #9794 * [chore] update the comment of the component package (#9798) Add connector as a type of component. * Remove docs/design.md and linked images (#9797) **Description:**searched both the core and contrib Collector repositories and found that the images are only used in this file. So I think it's safe to remove them as well. **Link to tracking Issue:** fixes #8889 * Update module github.com/cenkalti/backoff/v4 to v4.3.0 (#9841) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [github.com/cenkalti/backoff/v4](https://togithub.com/cenkalti/backoff) | `v4.2.1` -> `v4.3.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fcenkalti%2fbackoff%2fv4/v4.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/github.com%2fcenkalti%2fbackoff%2fv4/v4.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/github.com%2fcenkalti%2fbackoff%2fv4/v4.2.1/v4.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fcenkalti%2fbackoff%2fv4/v4.2.1/v4.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
cenkalti/backoff (github.com/cenkalti/backoff/v4) ### [`v4.3.0`](https://togithub.com/cenkalti/backoff/compare/v4.2.1...v4.3.0) [Compare Source](https://togithub.com/cenkalti/backoff/compare/v4.2.1...v4.3.0)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * Update Wandalen/wretry.action action to v3 (#9877) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [Wandalen/wretry.action](https://togithub.com/Wandalen/wretry.action) | action | major | `v2.1.0` -> `v3.0.0` | --- ### Release Notes
Wandalen/wretry.action (Wandalen/wretry.action) ### [`v3.0.0`](https://togithub.com/Wandalen/wretry.action/compare/v2.1.0...v3.0.0) [Compare Source](https://togithub.com/Wandalen/wretry.action/compare/v2.1.0...v3.0.0)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update module github.com/shirou/gopsutil/v3 to v3.24.3 (#9876) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [github.com/shirou/gopsutil/v3](https://togithub.com/shirou/gopsutil) | `v3.24.2` -> `v3.24.3` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fshirou%2fgopsutil%2fv3/v3.24.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/github.com%2fshirou%2fgopsutil%2fv3/v3.24.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/github.com%2fshirou%2fgopsutil%2fv3/v3.24.2/v3.24.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fshirou%2fgopsutil%2fv3/v3.24.2/v3.24.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
shirou/gopsutil (github.com/shirou/gopsutil/v3) ### [`v3.24.3`](https://togithub.com/shirou/gopsutil/releases/tag/v3.24.3) [Compare Source](https://togithub.com/shirou/gopsutil/compare/v3.24.2...v3.24.3) #### What's Changed ##### disk - chore: fix typo by [@​majorteach](https://togithub.com/majorteach) in [https://github.com/shirou/gopsutil/pull/1615](https://togithub.com/shirou/gopsutil/pull/1615) ##### host - \[host]\[linux]: fix utmp size on linux/arm64 by [@​shirou](https://togithub.com/shirou) in [https://github.com/shirou/gopsutil/pull/1603](https://togithub.com/shirou/gopsutil/pull/1603) ##### load - Total Processes in `MiscStat` Corrected by [@​eric1234](https://togithub.com/eric1234) in [https://github.com/shirou/gopsutil/pull/1612](https://togithub.com/shirou/gopsutil/pull/1612) ##### process - \[process]\[freebsd]: re-generate types on freebsd arm64 by [@​shirou](https://togithub.com/shirou) in [https://github.com/shirou/gopsutil/pull/1609](https://togithub.com/shirou/gopsutil/pull/1609) #### New Contributors - [@​majorteach](https://togithub.com/majorteach) made their first contribution in [https://github.com/shirou/gopsutil/pull/1615](https://togithub.com/shirou/gopsutil/pull/1615) - [@​eric1234](https://togithub.com/eric1234) made their first contribution in [https://github.com/shirou/gopsutil/pull/1612](https://togithub.com/shirou/gopsutil/pull/1612) **Full Changelog**: https://github.com/shirou/gopsutil/compare/v3.24.2...v3.24.3
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * [chore] Actually remove design.md (#9874) Follow up to #9797 to actually remove the file, not just its contents * updated README.md file in otlpreceiver (#9756) **Description:** Updated the README.md file in otlpreceiver - Corrected the serialization format to OTLP-JSON **Link to tracking Issue:** [(https://opentelemetry.io/docs/specs/otel/protocol/file-exporter/)](https://github.com/open-telemetry/opentelemetry-collector/issues/9207) **Documentation:** Changed the serialization format from Protobuf-JSON to OTLP-JSON --------- Co-authored-by: Pablo Baeyens * [chore] Adds two confmap tests (#9879) **Description:** Adds two tests to confmap to test some edge cases **Link to tracking Issue:** Written while reviewing #9862 * Update Wandalen/wretry.action action to v3.0.1 (#9878) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [Wandalen/wretry.action](https://togithub.com/Wandalen/wretry.action) | action | patch | `v3.0.0` -> `v3.0.1` | --- ### Release Notes
Wandalen/wretry.action (Wandalen/wretry.action) ### [`v3.0.1`](https://togithub.com/Wandalen/wretry.action/compare/v3.0.0...v3.0.1) [Compare Source](https://togithub.com/Wandalen/wretry.action/compare/v3.0.0...v3.0.1)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * [chore] Updated `unmarshalText` func (#9838) Changed the switch statement in` UnmarshalText` function to an if statement {configcompression} Link to the issue: https://github.com/open-telemetry/opentelemetry-collector/issues/9458 --------- Co-authored-by: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [confmap] support unmarshaling for embedded structs with and without squashing (#9861) This is taking a small slice of #9750 to document the behavior of confmap and make sure we can unmarshal embedded structs. * [configgrpc] remove deprecated funcs (#9836) Closes https://github.com/open-telemetry/opentelemetry-collector/issues/9482 Closes https://github.com/open-telemetry/opentelemetry-collector/issues/9812 * [telemetry] emit metrics with _ instead of / (#9775) This is addressing an issue w/ the names of the metrics generated by the Collector for its internal metrics. Note that this change only impacts users that emit telemetry using OTLP, which is currently still in experimental support. The prometheus metrics already replaced `/` with `_`. Fixes #9774 --------- Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * update golang.org/x/net to v0.23.0 (#9887) * Log when Environment Provider tries to pull unset or empty env var (#9837) **Description:** Creates a logger in the confmap.ProviderSettings and uses it to log when there is a missing or blank environment variable referenced in config. For now the noop logger is used everywhere except tests. **Link to tracking Issue:** [5615](https://github.com/open-telemetry/opentelemetry-collector/issues/5615) **Testing:** I wrote unit tests that ensured 1. logging occurred when an environment variable was unset 2. logging occcured when the env var was empty. 3. there was no log when an env var was used correctly I also started the otel collector with the sample config - and added an env var reference in the sample config. I then inserted a print statement next to each log call to see whether my code paths were hit in the live application. I then went through the 3 cases mentioned above and ensured that logging behavior was accurate. * [chore] bump go to 1.21.9 (#9888) Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [receiver/otlp] Refactor http error handling (#9893) **Description:** This PR slightly refactors the otlp receiver's HTTP error handling. The result is a few less calls to `status.FromError`, increased accuracy in the grpc code included in the body of the response, and centralizing http<->grpc mapping in the `internal/errors` package. This PR intentionally changes how we map from HTTP status code to grpc `Status.code`. I don't consider this to be a breaking change, or even worthy of a changelog, since the specification states that `"The clients are not expected to alter their behavior based on Status.code field but MAY record it for troubleshooting purposes."` Honestly, I'd be ok if we chose to stop including the `Status.code` entirely as it leads to more confusion in the code and payload in my opinion. **Link to tracking Issue:** Closes https://github.com/open-telemetry/opentelemetry-collector/issues/9864 **Testing:** Added new tests * [chore] update release schedule (#9900) Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Updated public methods in confighttp (#9895) Added context.Context to the following functions: ToClient ToServer ToListener Link: https://github.com/open-telemetry/opentelemetry-collector/issues/9807 * [receiver/nop] Promote to beta (#9902) This will be put into core/contrib in https://github.com/open-telemetry/opentelemetry-collector-releases/pull/519. Realistically we could declare this stable as well, it doesn't seem feasible to introduce breaking changes. **Link to tracking Issue:** https://github.com/open-telemetry/opentelemetry-collector/issues/7316 * [chore][receiver/scraperhelper] Fix typos in comments (#9904) This just fixes a couple typos in comments in the `scrapercontroller.go` file. * [exporter/nop] Promote to beta (#9903) This will be put into core/contrib in https://github.com/open-telemetry/opentelemetry-collector-releases/pull/519. Realistically we could declare this stable as well, it doesn't seem feasible to introduce breaking changes. **Link to tracking Issue:** https://github.com/open-telemetry/opentelemetry-collector/issues/7316 * move internal/testdata to pdata/testdata (#9885) This reduces dependencies from the consumer package while making testdata available across repos. It will allow us to remove duplicated code and its a fairly small surface area. Fixes https://github.com/open-telemetry/opentelemetry-collector/issues/9886 --------- Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Update module github.com/prometheus/client_model to v0.6.1 (#9913) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [github.com/prometheus/client_model](https://togithub.com/prometheus/client_model) | `v0.6.0` -> `v0.6.1` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fprometheus%2fclient_model/v0.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/github.com%2fprometheus%2fclient_model/v0.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/github.com%2fprometheus%2fclient_model/v0.6.0/v0.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fprometheus%2fclient_model/v0.6.0/v0.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
prometheus/client_model (github.com/prometheus/client_model) ### [`v0.6.1`](https://togithub.com/prometheus/client_model/releases/tag/v0.6.1) [Compare Source](https://togithub.com/prometheus/client_model/compare/v0.6.0...v0.6.1) #### What's Changed - Bump google.golang.org/protobuf from 1.32.0 to 1.33.0 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/prometheus/client_model/pull/84](https://togithub.com/prometheus/client_model/pull/84) **Full Changelog**: https://github.com/prometheus/client_model/compare/v0.6.0...v0.6.1
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * [chore] update pdata/testdata dep (#9909) This will make updating contrib easier. Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore][CI/CD] Fix failing codecov uploads (#9930) The `build-and-test` workflow has been failing consistently the last few days on the upload coverage step. The reason is outlined in https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/32259. Contrib issue, but same underlying cause: https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/32259 None yet, the CI/CD tests on this PR should be successful if this works. * Update github-actions deps (#9914) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [Wandalen/wretry.action](https://togithub.com/Wandalen/wretry.action) | action | minor | `v3.0.1` -> `v3.2.0` | | [github/codeql-action](https://togithub.com/github/codeql-action) | action | patch | `v3.24.9` -> `v3.24.10` | --- ### Release Notes
Wandalen/wretry.action (Wandalen/wretry.action) ### [`v3.2.0`](https://togithub.com/Wandalen/wretry.action/compare/v3.1.0...v3.2.0) [Compare Source](https://togithub.com/Wandalen/wretry.action/compare/v3.1.0...v3.2.0) ### [`v3.1.0`](https://togithub.com/Wandalen/wretry.action/compare/v3.0.1...v3.1.0) [Compare Source](https://togithub.com/Wandalen/wretry.action/compare/v3.0.1...v3.1.0)
github/codeql-action (github/codeql-action) ### [`v3.24.10`](https://togithub.com/github/codeql-action/compare/v3.24.9...v3.24.10) [Compare Source](https://togithub.com/github/codeql-action/compare/v3.24.9...v3.24.10)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Move arm64 to platform support tier 2 (#9910) This is a documentation change reflecting the progress we have made in supporting Linux ARM64 type machines. We now run both core and contrib builds on Ampere machines, supported by the CNCF, through Actuated github action runners. This PR fixes #9731 * Update module go.opentelemetry.io/contrib/zpages to v0.50.0 (#9923) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/contrib/zpages](https://togithub.com/open-telemetry/opentelemetry-go-contrib) | `v0.49.0` -> `v0.50.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcontrib%2fzpages/v0.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcontrib%2fzpages/v0.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcontrib%2fzpages/v0.49.0/v0.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcontrib%2fzpages/v0.49.0/v0.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Update module golang.org/x/net to v0.24.0 (#9924) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | golang.org/x/net | `v0.23.0` -> `v0.24.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fnet/v0.24.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/golang.org%2fx%2fnet/v0.24.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/golang.org%2fx%2fnet/v0.23.0/v0.24.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fnet/v0.23.0/v0.24.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Update module golang.org/x/tools to v0.20.0 (#9926) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | golang.org/x/tools | `v0.19.0` -> `v0.20.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2ftools/v0.20.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/golang.org%2fx%2ftools/v0.20.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/golang.org%2fx%2ftools/v0.19.0/v0.20.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2ftools/v0.19.0/v0.20.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Update module github.com/klauspost/compress to v1.17.8 (#9927) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [github.com/klauspost/compress](https://togithub.com/klauspost/compress) | `v1.17.7` -> `v1.17.8` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fklauspost%2fcompress/v1.17.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/github.com%2fklauspost%2fcompress/v1.17.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/github.com%2fklauspost%2fcompress/v1.17.7/v1.17.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fklauspost%2fcompress/v1.17.7/v1.17.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
klauspost/compress (github.com/klauspost/compress) ### [`v1.17.8`](https://togithub.com/klauspost/compress/releases/tag/v1.17.8) [Compare Source](https://togithub.com/klauspost/compress/compare/v1.17.7...v1.17.8) #### What's Changed - zstd: Reject blocks where reserved values are not 0 by [@​klauspost](https://togithub.com/klauspost) in [https://github.com/klauspost/compress/pull/885](https://togithub.com/klauspost/compress/pull/885) - zstd: Add RLE detection+encoding by [@​klauspost](https://togithub.com/klauspost) in [https://github.com/klauspost/compress/pull/938](https://togithub.com/klauspost/compress/pull/938) #### New Contributors - [@​ankon](https://togithub.com/ankon) made their first contribution in [https://github.com/klauspost/compress/pull/932](https://togithub.com/klauspost/compress/pull/932) - [@​kindhuge](https://togithub.com/kindhuge) made their first contribution in [https://github.com/klauspost/compress/pull/946](https://togithub.com/klauspost/compress/pull/946) **Full Changelog**: https://github.com/klauspost/compress/compare/v1.17.7...v1.17.8
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Update module go.opentelemetry.io/contrib/propagators/b3 to v1.25.0 (#9920) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/contrib/propagators/b3](https://togithub.com/open-telemetry/opentelemetry-go-contrib) | `v1.24.0` -> `v1.25.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcontrib%2fpropagators%2fb3/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcontrib%2fpropagators%2fb3/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcontrib%2fpropagators%2fb3/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcontrib%2fpropagators%2fb3/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-go-contrib (go.opentelemetry.io/contrib/propagators/b3) ### [`v1.25.0`](https://togithub.com/open-telemetry/opentelemetry-go-contrib/releases/tag/v1.25.0): /v0.50.0/v0.19.0/v0.5.0/v0.0.1 [Compare Source](https://togithub.com/open-telemetry/opentelemetry-go-contrib/compare/v1.24.0...v1.25.0) ##### Added - Implemented setting the `cloud.resource_id` resource attribute in `go.opentelemetry.io/detectors/aws/ecs` based on the ECS Metadata v4 endpoint. ([#​5091](https://togithub.com/open-telemetry/opentelemetry-go-contrib/issues/5091)) - The `go.opentelemetry.io/contrib/bridges/otelslog` module. This module provides an OpenTelemetry logging bridge for "log/slog". ([#​5335](https://togithub.com/open-telemetry/opentelemetry-go-contrib/issues/5335)) ##### Fixed - Update all dependencies to address \[GO-2024-2687]. ([#​5359](https://togithub.com/open-telemetry/opentelemetry-go-contrib/issues/5359)) ##### Removed - Drop support for [Go 1.20]. ([#​5163](https://togithub.com/open-telemetry/opentelemetry-go-contrib/issues/5163)) [Go 1.20]: https://go.dev/doc/go1.20 **Full Changelog**: https://github.com/open-telemetry/opentelemetry-go-contrib/compare/v1.24.0...v1.25.0
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Update module golang.org/x/sys to v0.19.0 (#9925) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | golang.org/x/sys | `v0.18.0` -> `v0.19.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fsys/v0.19.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/golang.org%2fx%2fsys/v0.19.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/golang.org%2fx%2fsys/v0.18.0/v0.19.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fsys/v0.18.0/v0.19.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * Update module github.com/knadh/koanf/v2 to v2.1.1 (#9912) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [github.com/knadh/koanf/v2](https://togithub.com/knadh/koanf) | `v2.1.0` -> `v2.1.1` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fknadh%2fkoanf%2fv2/v2.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/github.com%2fknadh%2fkoanf%2fv2/v2.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/github.com%2fknadh%2fkoanf%2fv2/v2.1.0/v2.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fknadh%2fkoanf%2fv2/v2.1.0/v2.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
knadh/koanf (github.com/knadh/koanf/v2) ### [`v2.1.1`](https://togithub.com/knadh/koanf/releases/tag/v2.1.1) [Compare Source](https://togithub.com/knadh/koanf/compare/v2.1.0...v2.1.1) #### What's Changed - fix: run submodule tests by [@​rhnvrm](https://togithub.com/rhnvrm) in [https://github.com/knadh/koanf/pull/276](https://togithub.com/knadh/koanf/pull/276) - Bump google.golang.org/protobuf from 1.30.0 to 1.33.0 in /examples by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/knadh/koanf/pull/282](https://togithub.com/knadh/koanf/pull/282) - Bump google.golang.org/protobuf from 1.30.0 to 1.33.0 in /providers/etcd by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/knadh/koanf/pull/281](https://togithub.com/knadh/koanf/pull/281) - Bump google.golang.org/protobuf from 1.30.0 to 1.33.0 in /providers/nats by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/knadh/koanf/pull/280](https://togithub.com/knadh/koanf/pull/280) - feat: add ParserEnvWithValue by [@​tlipoca9](https://togithub.com/tlipoca9) in [https://github.com/knadh/koanf/pull/284](https://togithub.com/knadh/koanf/pull/284) - Fix map unflattening no-delimiter behaviour by [@​knadh](https://togithub.com/knadh) in [https://github.com/knadh/koanf/pull/278](https://togithub.com/knadh/koanf/pull/278) #### New Contributors - [@​tlipoca9](https://togithub.com/tlipoca9) made their first contribution in [https://github.com/knadh/koanf/pull/284](https://togithub.com/knadh/koanf/pull/284) **Full Changelog**: https://github.com/knadh/koanf/compare/v2.1.0...v2.1.1
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Update opentelemetry-go monorepo (#9929) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/otel](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.24.0` -> `v1.25.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/bridge/opencensus](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.24.0` -> `v1.25.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fbridge%2fopencensus/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fbridge%2fopencensus/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fbridge%2fopencensus/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fbridge%2fopencensus/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.24.0` -> `v1.25.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetricgrpc/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetricgrpc/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetricgrpc/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetricgrpc/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.24.0` -> `v1.25.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetrichttp/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetrichttp/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetrichttp/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetrichttp/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.24.0` -> `v1.25.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlptrace%2fotlptracegrpc/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlptrace%2fotlptracegrpc/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlptrace%2fotlptracegrpc/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlptrace%2fotlptracegrpc/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.24.0` -> `v1.25.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlptrace%2fotlptracehttp/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlptrace%2fotlptracehttp/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlptrace%2fotlptracehttp/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlptrace%2fotlptracehttp/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/exporters/prometheus](https://togithub.com/open-telemetry/opentelemetry-go) | `v0.46.0` -> `v0.47.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fexporters%2fprometheus/v0.47.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fexporters%2fprometheus/v0.47.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fexporters%2fprometheus/v0.46.0/v0.47.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fexporters%2fprometheus/v0.46.0/v0.47.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/exporters/stdout/stdoutmetric](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.24.0` -> `v1.25.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fexporters%2fstdout%2fstdoutmetric/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fexporters%2fstdout%2fstdoutmetric/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fexporters%2fstdout%2fstdoutmetric/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fexporters%2fstdout%2fstdoutmetric/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/exporters/stdout/stdouttrace](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.24.0` -> `v1.25.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fexporters%2fstdout%2fstdouttrace/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fexporters%2fstdout%2fstdouttrace/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fexporters%2fstdout%2fstdouttrace/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fexporters%2fstdout%2fstdouttrace/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/metric](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.24.0` -> `v1.25.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fmetric/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fmetric/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fmetric/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fmetric/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/sdk](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.24.0` -> `v1.25.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fsdk/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fsdk/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fsdk/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fsdk/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/sdk/metric](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.24.0` -> `v1.25.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fsdk%2fmetric/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fsdk%2fmetric/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fsdk%2fmetric/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fsdk%2fmetric/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/trace](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.24.0` -> `v1.25.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2ftrace/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2ftrace/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2ftrace/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2ftrace/v1.24.0/v1.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-go (go.opentelemetry.io/otel) ### [`v1.25.0`](https://togithub.com/open-telemetry/opentelemetry-go/releases/tag/v1.25.0): /v0.47.0/v0.0.8/v0.1.0-alpha [Compare Source](https://togithub.com/open-telemetry/opentelemetry-go/compare/v1.24.0...v1.25.0) ##### Added - Add `WithProxy` option in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. ([#​4906](https://togithub.com/open-telemetry/opentelemetry-go/issues/4906)) - Add `WithProxy` option in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlptracehttp`. ([#​4906](https://togithub.com/open-telemetry/opentelemetry-go/issues/4906)) - Add `AddLink` method to the `Span` interface in `go.opentelemetry.io/otel/trace`. ([#​5032](https://togithub.com/open-telemetry/opentelemetry-go/issues/5032)) - The `Enabled` method is added to the `Logger` interface in `go.opentelemetry.io/otel/log`. This method is used to notify users if a log record will be emitted or not. ([#​5071](https://togithub.com/open-telemetry/opentelemetry-go/issues/5071)) - Add `SeverityUndefined` `const` to `go.opentelemetry.io/otel/log`. This value represents an unset severity level. ([#​5072](https://togithub.com/open-telemetry/opentelemetry-go/issues/5072)) - Add `Empty` function in `go.opentelemetry.io/otel/log` to return a `KeyValue` for an empty value. ([#​5076](https://togithub.com/open-telemetry/opentelemetry-go/issues/5076)) - Add `go.opentelemetry.io/otel/log/global` to manage the global `LoggerProvider`. This package is provided with the anticipation that all functionality will be migrate to `go.opentelemetry.io/otel` when `go.opentelemetry.io/otel/log` stabilizes. At which point, users will be required to migrage their code, and this package will be deprecated then removed. ([#​5085](https://togithub.com/open-telemetry/opentelemetry-go/issues/5085)) - Add support for `Summary` metrics in the `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` and `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` exporters. ([#​5100](https://togithub.com/open-telemetry/opentelemetry-go/issues/5100)) - Add `otel.scope.name` and `otel.scope.version` tags to spans exported by `go.opentelemetry.io/otel/exporters/zipkin`. ([#​5108](https://togithub.com/open-telemetry/opentelemetry-go/issues/5108)) - Add support for `AddLink` to `go.opentelemetry.io/otel/bridge/opencensus`. ([#​5116](https://togithub.com/open-telemetry/opentelemetry-go/issues/5116)) - Add `String` method to `Value` and `KeyValue` in `go.opentelemetry.io/otel/log`. ([#​5117](https://togithub.com/open-telemetry/opentelemetry-go/issues/5117)) - Add Exemplar support to `go.opentelemetry.io/otel/exporters/prometheus`. ([#​5111](https://togithub.com/open-telemetry/opentelemetry-go/issues/5111)) - Add metric semantic conventions to `go.opentelemetry.io/otel/semconv/v1.24.0`. Future `semconv` packages will include metric semantic conventions as well. ([#​4528](https://togithub.com/open-telemetry/opentelemetry-go/issues/4528)) ##### Changed - `SpanFromContext` and `SpanContextFromContext` in `go.opentelemetry.io/otel/trace` no longer make a heap allocation when the passed context has no span. ([#​5049](https://togithub.com/open-telemetry/opentelemetry-go/issues/5049)) - `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` and `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` now create a gRPC client in idle mode and with "dns" as the default resolver using [`grpc.NewClient`](https://pkg.go.dev/google.golang.org/grpc#NewClient). ([#​5151](https://togithub.com/open-telemetry/opentelemetry-go/issues/5151)) Because of that `WithDialOption` ignores [`grpc.WithBlock`](https://pkg.go.dev/google.golang.org/grpc#WithBlock), [`grpc.WithTimeout`](https://pkg.go.dev/google.golang.org/grpc#WithTimeout), and [`grpc.WithReturnConnectionError`](https://pkg.go.dev/google.golang.org/grpc#WithReturnConnectionError). Notice that [`grpc.DialContext`](https://pkg.go.dev/google.golang.org/grpc#DialContext) which was used before is now deprecated. ##### Fixed - Clarify the documentation about equivalence guarantees for the `Set` and `Distinct` types in `go.opentelemetry.io/otel/attribute`. ([#​5027](https://togithub.com/open-telemetry/opentelemetry-go/issues/5027)) - Prevent default `ErrorHandler` self-delegation. ([#​5137](https://togithub.com/open-telemetry/opentelemetry-go/issues/5137)) - Update all dependencies to address [GO-2024-2687]. ([#​5139](https://togithub.com/open-telemetry/opentelemetry-go/issues/5139)) ##### Removed - Drop support for [Go 1.20]. ([#​4967](https://togithub.com/open-telemetry/opentelemetry-go/issues/4967)) ##### Deprecated - Deprecate `go.opentelemetry.io/otel/attribute.Sortable` type. ([#​4734](https://togithub.com/open-telemetry/opentelemetry-go/issues/4734)) - Deprecate `go.opentelemetry.io/otel/attribute.NewSetWithSortable` function. ([#​4734](https://togithub.com/open-telemetry/opentelemetry-go/issues/4734)) - Deprecate `go.opentelemetry.io/otel/attribute.NewSetWithSortableFiltered` function. ([#​4734](https://togithub.com/open-telemetry/opentelemetry-go/issues/4734)) [Go 1.20]: https://go.dev/doc/go1.20 [GO-2024-2687]: https://pkg.go.dev/vuln/GO-2024-2687 #### New Contributors - [@​tgolang](https://togithub.com/tgolang) made their first contribution in [https://github.com/open-telemetry/opentelemetry-go/pull/5048](https://togithub.com/open-telemetry/opentelemetry-go/pull/5048) - [@​MickaelAlliel](https://togithub.com/MickaelAlliel) made their first contribution in [https://github.com/open-telemetry/opentelemetry-go/pull/4906](https://togithub.com/open-telemetry/opentelemetry-go/pull/4906) - [@​s4s7](https://togithub.com/s4s7) made their first contribution in [https://github.com/open-telemetry/opentelemetry-go/pull/5096](https://togithub.com/open-telemetry/opentelemetry-go/pull/5096) - [@​Kielek](https://togithub.com/Kielek) made their first contribution in [https://github.com/open-telemetry/opentelemetry-go/pull/5108](https://togithub.com/open-telemetry/opentelemetry-go/pull/5108) - [@​q-cheng](https://togithub.com/q-cheng) made their first contribution in [https://github.com/open-telemetry/opentelemetry-go/pull/5032](https://togithub.com/open-telemetry/opentelemetry-go/pull/5032) - [@​carrbs](https://togithub.com/carrbs) made their first contribution in [https://github.com/open-telemetry/opentelemetry-go/pull/4880](https://togithub.com/open-telemetry/opentelemetry-go/pull/4880) **Full Changelog**: https://github.com/open-telemetry/opentelemetry-go/compare/v1.24.0...v1.25.0
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * [docs] update roadmap document (#9899) This document now contains the current focus of the maintainers of the collector project. --------- Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> Co-authored-by: Pablo Baeyens * [service] Validate pipeline type against component types (#9257) **Description:** This change adds another layer of validation to pipelines. It validates that all the components in a pipeline are of the same type as the pipeline. For example, if a `metrics` pipeline contains a `traces`-only receiver, the `otelcol validate -config ...` command will fail. **Link to tracking Issue:** Fixes #8007. **Testing:** Added unit test + existing tests are passing. **Documentation:** godoc. --------- Co-authored-by: Pablo Baeyens * Add length limit to component (#9901) Changes component.Type validation regex to only allow a max of 63 characters in a type name. Fixes #9872 --------- Co-authored-by: Pablo Baeyens * [chore] Prepare release v1.5.0/v0.98.0 (#9935) The following commands were run to prepare this release: - make chlog-update VERSION=v1.5.0/v0.98.0 - make prepare-release PREVIOUS_VERSION=1.4.0 RELEASE_CANDIDATE=1.5.0 MODSET=stable - make prepare-release PREVIOUS_VERSION=0.97.0 RELEASE_CANDIDATE=0.98.0 MODSET=beta * [chore] Cleanup changelog (#9937) - Remove an entry for sync/atomic usage as it's an internal change - Fix a typo - Move pdata/testdata from Deprecations to Enhancements since `internal/testdata` wasn't avalable from outside of the repo * [chore] missed updating the makefile with new module (#9939) Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] Remove unreachable deprecated internal/testdata (#9938) No changelog entry needed since it's an internal module * [chore] [exporterhelper] Update stale batchSender comments (#9884) Update comment as fields may have been renamed. * Update module github.com/golangci/golangci-lint to v1.57.2 (#9840) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [github.com/golangci/golangci-lint](https://togithub.com/golangci/golangci-lint) | `v1.56.2` -> `v1.57.2` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fgolangci%2fgolangci-lint/v1.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/github.com%2fgolangci%2fgolangci-lint/v1.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/github.com%2fgolangci%2fgolangci-lint/v1.56.2/v1.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fgolangci%2fgolangci-lint/v1.56.2/v1.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
golangci/golangci-lint (github.com/golangci/golangci-lint) ### [`v1.57.2`](https://togithub.com/golangci/golangci-lint/compare/v1.57.1...v1.57.2) [Compare Source](https://togithub.com/golangci/golangci-lint/compare/v1.57.1...v1.57.2) ### [`v1.57.1`](https://togithub.com/golangci/golangci-lint/releases/tag/v1.57.1) [Compare Source](https://togithub.com/golangci/golangci-lint/compare/v1.57.0...v1.57.1) #### Changelog - [`87b6bf1`](https://togithub.com/golangci/golangci-lint/commit/87b6bf17) build(deps): bump github.com/golangci/plugin-module-register from 0.1.0 to 0.1.1 ([#​4549](https://togithub.com/golangci/golangci-lint/issues/4549)) - [`921d535`](https://togithub.com/golangci/golangci-lint/commit/921d5357) build(deps): bump github.com/pelletier/go-toml/v2 from 2.1.1 to 2.2.0 ([#​4548](https://togithub.com/golangci/golangci-lint/issues/4548)) - [`cd890db`](https://togithub.com/golangci/golangci-lint/commit/cd890db2) fix: filter invalid issues before other processors ([#​4552](https://togithub.com/golangci/golangci-lint/issues/4552)) ### [`v1.57.0`](https://togithub.com/golangci/golangci-lint/compare/v1.56.2...v1.57.0) [Compare Source](https://togithub.com/golangci/golangci-lint/compare/v1.56.2...v1.57.0)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * Update module google.golang.org/grpc to v1.63.2 (#9928) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [google.golang.org/grpc](https://togithub.com/grpc/grpc-go) | `v1.62.1` -> `v1.63.2` | [![age](https://developer.mend.io/api/mc/badges/age/go/google.golang.org%2fgrpc/v1.63.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/google.golang.org%2fgrpc/v1.63.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/google.golang.org%2fgrpc/v1.62.1/v1.63.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/google.golang.org%2fgrpc/v1.62.1/v1.63.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [google.golang.org/grpc](https://togithub.com/grpc/grpc-go) | `v1.63.0` -> `v1.63.2` | [![age](https://developer.mend.io/api/mc/badges/age/go/google.golang.org%2fgrpc/v1.63.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/google.golang.org%2fgrpc/v1.63.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/google.golang.org%2fgrpc/v1.63.0/v1.63.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/google.golang.org%2fgrpc/v1.63.0/v1.63.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
grpc/grpc-go (google.golang.org/grpc) ### [`v1.63.2`](https://togithub.com/grpc/grpc-go/releases/tag/v1.63.2): Release 1.63.2 [Compare Source](https://togithub.com/grpc/grpc-go/compare/v1.63.1...v1.63.2) ### Bugs - Fix the user agent string ### [`v1.63.1`](https://togithub.com/grpc/grpc-go/releases/tag/v1.63.1): Release 1.63.1 [Compare Source](https://togithub.com/grpc/grpc-go/compare/v1.63.0...v1.63.1) - grpc: un-deprecate Dial and DialContext and cherry-pick ### [`v1.63.0`](https://togithub.com/grpc/grpc-go/releases/tag/v1.63.0): Release 1.63.0 [Compare Source](https://togithub.com/grpc/grpc-go/compare/v1.62.2...v1.63.0) ### Behavior Changes - grpc: Return canonical target string from `resolver.Address.String()` (experimental) ([#​6923](https://togithub.com/grpc/grpc-go/issues/6923)) - client & server: when using write buffer pooling, use input value for buffer size instead of size\*2 ([#​6983](https://togithub.com/grpc/grpc-go/issues/6983)) - Special Thanks: [@​raghav-stripe](https://togithub.com/raghav-stripe) ### New Features - grpc: add `ClientConn.CanonicalTarget()` to return the canonical target string. ([#​7006](https://togithub.com/grpc/grpc-go/issues/7006)) - xds: implement LRS named metrics support ([gRFC A64](https://togithub.com/grpc/proposal/blob/master/A64-lrs-custom-metrics.md)) ([#​7027](https://togithub.com/grpc/grpc-go/issues/7027)) - Special Thanks: [@​danielzhaotongliu](https://togithub.com/danielzhaotongliu) - grpc: introduce `grpc.NewClient` to allow users to create new clients in idle mode and with "dns" as the default resolver ([#​7010](https://togithub.com/grpc/grpc-go/issues/7010)) - Special Thanks: [@​bruuuuuuuce](https://togithub.com/bruuuuuuuce) ### API Changes - grpc: stabilize experimental method `ClientConn.Target()` ([#​7006](https://togithub.com/grpc/grpc-go/issues/7006)) ### Bug Fixes - xds: fix an issue that would cause the client to send an empty list of resources for LDS/CDS upon reconnecting with the management server ([#​7026](https://togithub.com/grpc/grpc-go/issues/7026)) - server: Fix some errors returned by a server when using a `grpc.Server` as an `http.Handler` with the Go stdlib HTTP server ([#​6989](https://togithub.com/grpc/grpc-go/issues/6989)) - resolver/dns: add `SetResolvingTimeout` to allow configuring the DNS resolver's global timeout ([#​6917](https://togithub.com/grpc/grpc-go/issues/6917)) - Special Thanks: [@​and1truong](https://togithub.com/and1truong) - Set the security level of Windows named pipes to NoSecurity ([#​6956](https://togithub.com/grpc/grpc-go/issues/6956)) - Special Thanks: [@​irsl](https://togithub.com/irsl) ### [`v1.62.2`](https://togithub.com/grpc/grpc-go/releases/tag/v1.62.2): Release 1.62.2 [Compare Source](https://togithub.com/grpc/grpc-go/compare/v1.62.1...v1.62.2) ### Dependencies - Update http2 library to address vulnerability [CVE-2023-45288](https://www.kb.cert.org/vuls/id/421644)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * Update module github.com/prometheus/common to v0.52.3 (#9694) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [github.com/prometheus/common](https://togithub.com/prometheus/common) | `v0.48.0` -> `v0.52.3` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fprometheus%2fcommon/v0.52.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/github.com%2fprometheus%2fcommon/v0.52.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/github.com%2fprometheus%2fcommon/v0.48.0/v0.52.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fprometheus%2fcommon/v0.48.0/v0.52.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
prometheus/common (github.com/prometheus/common) ### [`v0.52.3`](https://togithub.com/prometheus/common/compare/v0.52.2...v0.52.3) [Compare Source](https://togithub.com/prometheus/common/compare/v0.52.2...v0.52.3) ### [`v0.52.2`](https://togithub.com/prometheus/common/releases/tag/v0.52.2) [Compare Source](https://togithub.com/prometheus/common/compare/v0.51.1...v0.52.2) #### What's Changed - Drop support for Go older than 1.18 by [@​SuperQ](https://togithub.com/SuperQ) in [https://github.com/prometheus/common/pull/612](https://togithub.com/prometheus/common/pull/612) - fix(protobuf): Correctly decode multi-messages streams by [@​srebhan](https://togithub.com/srebhan) in [https://github.com/prometheus/common/pull/616](https://togithub.com/prometheus/common/pull/616) - Bump github.com/aws/aws-sdk-go from 1.50.31 to 1.51.11 in /sigv4 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/prometheus/common/pull/615](https://togithub.com/prometheus/common/pull/615) #### New Contributors - [@​srebhan](https://togithub.com/srebhan) made their first contribution in [https://github.com/prometheus/common/pull/616](https://togithub.com/prometheus/common/pull/616) **Full Changelog**: https://github.com/prometheus/common/compare/v0.51.1...v0.52.2 ### [`v0.51.1`](https://togithub.com/prometheus/common/releases/tag/v0.51.1) [Compare Source](https://togithub.com/prometheus/common/compare/v0.51.0...v0.51.1) #### What's Changed - Synchronize common files from prometheus/prometheus by [@​prombot](https://togithub.com/prombot) in [https://github.com/prometheus/common/pull/606](https://togithub.com/prometheus/common/pull/606) - Synchronize common files from prometheus/prometheus by [@​prombot](https://togithub.com/prombot) in [https://github.com/prometheus/common/pull/609](https://togithub.com/prometheus/common/pull/609) - Retract v0.50.0 by [@​SuperQ](https://togithub.com/SuperQ) in [https://github.com/prometheus/common/pull/610](https://togithub.com/prometheus/common/pull/610) **Full Changelog**: https://github.com/prometheus/common/compare/v0.51.0...v0.51.1 ### [`v0.51.0`](https://togithub.com/prometheus/common/releases/tag/v0.51.0) [Compare Source](https://togithub.com/prometheus/common/compare/v0.50.0...v0.51.0) #### What's Changed - Synchronize common files from prometheus/prometheus by [@​prombot](https://togithub.com/prombot) in [https://github.com/prometheus/common/pull/604](https://togithub.com/prometheus/common/pull/604) - expfmt: Add a way to generate different OpenMetrics Formats by [@​ywwg](https://togithub.com/ywwg) in [https://github.com/prometheus/common/pull/596](https://togithub.com/prometheus/common/pull/596) - Fix string slice definition for FormatFlagOptions. by [@​gizmoguy](https://togithub.com/gizmoguy) in [https://github.com/prometheus/common/pull/607](https://togithub.com/prometheus/common/pull/607) - Correct logic in sample naming for counters, add new test by [@​vesari](https://togithub.com/vesari) in [https://github.com/prometheus/common/pull/608](https://togithub.com/prometheus/common/pull/608) #### New Contributors - [@​gizmoguy](https://togithub.com/gizmoguy) made their first contribution in [https://github.com/prometheus/common/pull/607](https://togithub.com/prometheus/common/pull/607) **Full Changelog**: https://github.com/prometheus/common/compare/v0.50.0...v0.51.0 ### [`v0.50.0`](https://togithub.com/prometheus/common/releases/tag/v0.50.0) [Compare Source](https://togithub.com/prometheus/common/compare/v0.49.0...v0.50.0) #### What's Changed - Synchronize common files from prometheus/prometheus by [@​prombot](https://togithub.com/prombot) in [https://github.com/prometheus/common/pull/594](https://togithub.com/prometheus/common/pull/594) - Bump github.com/stretchr/testify from 1.8.4 to 1.9.0 in /sigv4 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/prometheus/common/pull/593](https://togithub.com/prometheus/common/pull/593) - Bump github.com/aws/aws-sdk-go from 1.50.27 to 1.50.29 in /sigv4 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/prometheus/common/pull/592](https://togithub.com/prometheus/common/pull/592) - Bump github.com/aws/aws-sdk-go from 1.50.29 to 1.50.31 in /sigv4 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/prometheus/common/pull/595](https://togithub.com/prometheus/common/pull/595) - Remove unused 'Host' member from HTTPClientConfig by [@​bboreham](https://togithub.com/bboreham) in [https://github.com/prometheus/common/pull/597](https://togithub.com/prometheus/common/pull/597) - Add OpenMetrics unit support by [@​vesari](https://togithub.com/vesari) in [https://github.com/prometheus/common/pull/544](https://togithub.com/prometheus/common/pull/544) - Remove deprecated version function by [@​SuperQ](https://togithub.com/SuperQ) in [https://github.com/prometheus/common/pull/591](https://togithub.com/prometheus/common/pull/591) - Synchronize common files from prometheus/prometheus by [@​prombot](https://togithub.com/prombot) in [https://github.com/prometheus/common/pull/599](https://togithub.com/prometheus/common/pull/599) - Bump golang.org/x/oauth2 from 0.17.0 to 0.18.0 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/prometheus/common/pull/600](https://togithub.com/prometheus/common/pull/600) - Bump google.golang.org/protobuf from 1.32.0 to 1.33.0 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/prometheus/common/pull/601](https://togithub.com/prometheus/common/pull/601) **Full Changelog**: https://github.com/prometheus/common/compare/v0.49.0...v0.50.0 ### [`v0.49.0`](https://togithub.com/prometheus/common/releases/tag/v0.49.0) [Compare Source](https://togithub.com/prometheus/common/compare/v0.48.0...v0.49.0) #### What's Changed - Synchronize common files from prometheus/prometheus by [@​prombot](https://togithub.com/prombot) in [https://github.com/prometheus/common/pull/574](https://togithub.com/prometheus/common/pull/574) - Bump github.com/aws/aws-sdk-go from 1.49.13 to 1.50.8 in /sigv4 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/prometheus/common/pull/571](https://togithub.com/prometheus/common/pull/571) - Synchronize common files from prometheus/prometheus by [@​prombot](https://togithub.com/prombot) in [https://github.com/prometheus/common/pull/581](https://togithub.com/prometheus/common/pull/581) - Update Go by [@​SuperQ](https://togithub.com/SuperQ) in [https://github.com/prometheus/common/pull/588](https://togithub.com/prometheus/common/pull/588) - Deprecate version.NewCollector by [@​SuperQ](https://togithub.com/SuperQ) in [https://github.com/prometheus/common/pull/579](https://togithub.com/prometheus/common/pull/579) - Bump github.com/aws/aws-sdk-go from 1.50.8 to 1.50.27 in /sigv4 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/prometheus/common/pull/587](https://togithub.com/prometheus/common/pull/587) - Avoid off-spec openmetrics exposition when exemplars have empty labels by [@​orls](https://togithub.com/orls) in [https://github.com/prometheus/common/pull/569](https://togithub.com/prometheus/common/pull/569) - Bump golang.org/x/oauth2 from 0.16.0 to 0.17.0 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/prometheus/common/pull/585](https://togithub.com/prometheus/common/pull/585) - Write created lines when negotiating OpenMetrics by [@​ArthurSens](https://togithub.com/ArthurSens) in [https://github.com/prometheus/common/pull/504](https://togithub.com/prometheus/common/pull/504) - Upgrade client_model to v.0.6.0 by [@​vesari](https://togithub.com/vesari) in [https://github.com/prometheus/common/pull/589](https://togithub.com/prometheus/common/pull/589) - http_config: Add host by [@​jkroepke](https://togithub.com/jkroepke) in [https://github.com/prometheus/common/pull/549](https://togithub.com/prometheus/common/pull/549) - LabelSet: Fix alphabetical sorting for prometheus LabelSet by [@​wasim-nihal](https://togithub.com/wasim-nihal) in [https://github.com/prometheus/common/pull/575](https://togithub.com/prometheus/common/pull/575) - labelset: optimise String() function by [@​bboreham](https://togithub.com/bboreham) in [https://github.com/prometheus/common/pull/590](https://togithub.com/prometheus/common/pull/590) #### New Contributors - [@​orls](https://togithub.com/orls) made their first contribution in [https://github.com/prometheus/common/pull/569](https://togithub.com/prometheus/common/pull/569) - [@​vesari](https://togithub.com/vesari) made their first contribution in [https://github.com/prometheus/common/pull/589](https://togithub.com/prometheus/common/pull/589) **Full Changelog**: https://github.com/prometheus/common/compare/v0.48.0...v0.49.0
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * [cmd/mdatagen] Move component config test from cmd/builder (#9940) The tests generated by cmd/builder are skipped in contrib because they cause the CI timeouts. We moved the lifecycle tests to the tests generated by mdatagen, but the config/factory smoke tests are still part of the files generated by cmd/builder. Recently, the loadbalancing exporter got an invalid camelCase config field because of this coverage gap. This change moves the config/factory tests from cmd/builder to cmd/mdatagen. So, they are always generated for every component, even if not used in any collector bundle. * [chore] fix deprecation godoc (#9947) Not prefixing the Deprecated godoc with a newline (or it being the only godoc) appears to cause intellisense/linters some pain. Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [mdatagen] allow filtering out metrics based on resource attributes (#9660) **Description:** This PR allows filtering out metrics based on resource attributes. For example: ``` resource_attributes: k8s.pod.name: enabled: true exclude: #- strict: "kube-apiserver-kind-control-plane" - regexp: "kube-.*" - regexp: "coredns-.*" - strict: "coredns" - strict: "kindnet-mpb2p" ``` Would remove metrics that match regex or strict rules on resource attributes. **Link to tracking Issue:** https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/25134 **Testing:** - Tested with k8scluster receiver in kind cluster. - unit tests added **Documentation:** --------- Co-authored-by: Dmitrii Anoshin * Promote @atoulme, @TylerHelmuth and @songy23 to approvers (#9954) :tada: fixes #9946, fixes #9949, fixes #9953 * [chore] Remove dead link (#9955) Follows #9874 and #9797 * [chore] Fix component name in changelog (#9948) s/metadatagen/mdatagen/ * [confighttp] deprecate ToClientContext, ToServerContext, ToListenerContext (#9944) Replaced by ToClient, ToServer, ToListener Related to #9807 --------- Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Update module go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc to v0.50.0 (#9918) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc](https://togithub.com/open-telemetry/opentelemetry-go-contrib) | `v0.49.0` -> `v0.50.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fgoogle.golang.org%2fgrpc%2fotelgrpc/v0.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fgoogle.golang.org%2fgrpc%2fotelgrpc/v0.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fgoogle.golang.org%2fgrpc%2fotelgrpc/v0.49.0/v0.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fgoogle.golang.org%2fgrpc%2fotelgrpc/v0.49.0/v0.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * Update module go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp to v0.50.0 (#9919) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://togithub.com/open-telemetry/opentelemetry-go-contrib) | `v0.49.0` -> `v0.50.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fnet%2fhttp%2fotelhttp/v0.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fnet%2fhttp%2fotelhttp/v0.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fnet%2fhttp%2fotelhttp/v0.49.0/v0.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fnet%2fhttp%2fotelhttp/v0.49.0/v0.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * [chore] these top level ignores are no longer needed (#9958) Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [cmd/mdatagen] [chore] Small fixes for new resource attributes filter (#9950) - Make sure we always pass a string to the filter.Match even if the attribute value has a different type. Otherwise, it panics. - Make sure we show the if_configured warning if the user sets include/exclude without enabled. - Simplify generated tests Follow up to https://github.com/open-telemetry/opentelemetry-collector/pull/9660 * Disable concurrency in zstd and add Benchmark tests for it (#9749) **Description:** zstd benchmark tests added The goal of this PR is to disable concurrency in zstd compression to reduce its memory footprint and avoid a known issue with goroutine leaks. Please see - https://github.com/klauspost/compress/issues/264 **Link to tracking Issue:** https://github.com/open-telemetry/opentelemetry-collector/issues/8216 **Testing:** Benchmark test results below ``` BenchmarkCompression/zstdWithConcurrency/compress-10 21392 55855 ns/op 187732.88 MB/s 2329164 B/op 28 allocs/op BenchmarkCompression/zstdNoConcurrency/compress-10 29526 39902 ns/op 262787.42 MB/s 1758988 B/op 15 allocs/op input => 10.00 MB ``` * Update module go.opentelemetry.io/contrib/config to v0.5.0 (#9934) Replace https://github.com/open-telemetry/opentelemetry-collector/pull/9917 because of a merge conflict --------- Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * [chore] remove usage of deprecated funcs (#9965) DialContext was marked as deprecated https://github.com/grpc/grpc-go/releases/tag/v1.63.1 Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [configtls] Deprecate *Context funcs (#9945) Works towards https://github.com/open-telemetry/opentelemetry-collector/issues/9811 * [configtls] Add NewDefault* funcs (#9658) Adds new `NewDefault*` funcs for all 3 config structs. In anticipation of the name changes from https://github.com/open-telemetry/opentelemetry-collector/pull/9495 I've named the functions using the new, preferred name. Closes https://github.com/open-telemetry/opentelemetry-collector/issues/9657 * [chore] update filter dep (#9966) Makes updating contrib easier. Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore][exporter/debug] refactor code to make independent from Logging exporter (#9922) This PR is the first part of this draft PR: https://github.com/open-telemetry/opentelemetry-collector/pull/9298. This refactoring is needed to implement [[exporter/debug] change behavior of "normal" verbosity to be different from "basic" #7806](https://github.com/open-telemetry/opentelemetry-collector/issues/7806). I want to change the behavior of the Debug exporter, but leave the behavior of the Logging exporter unchanged. **Link to tracking Issue:** - https://github.com/open-telemetry/opentelemetry-collector/issues/7806 * [chore] [mdatagen] Fix generated tests for include/exclude capability (#9970) To unblock https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/32394 * [service] fix bug in sampler (#9968) The configuration for the recordSampler has multiple configurations for the RemoteParentSampler which doesn't appear to make any sense. I suspect the original intent was to configure both local and remote samplers with sampled and not sampled. --------- Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] Move logging out of meter provider initialization (#9729) **Description:** Moves logging messages about the meter provider outside of the meter provider initialization. While working on https://github.com/open-telemetry/opentelemetry-collector/issues/4970#issuecomment-1911978462, I realized there is an implicit dependency in the initialization order of the different telemetry components. I tried making this work and make the factory have a single `CreateTelemetrySettings`, but this results in an awkward API, so I am trying the alternative here: don't log during the meter provider initialization, but do so outside of it. **Link to tracking Issue:** Relates to #4970 --------- Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Update module go.opentelemetry.io/collector/confmap to v0.98.0 (#9972) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/collector/confmap](https://togithub.com/open-telemetry/opentelemetry-collector) | `v0.96.0` -> `v0.98.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcollector%2fconfmap/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcollector%2fconfmap/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcollector%2fconfmap/v0.96.0/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcollector%2fconfmap/v0.96.0/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-collector (go.opentelemetry.io/collector/confmap) ### [`v0.98.0`](https://togithub.com/open-telemetry/opentelemetry-collector/blob/HEAD/CHANGELOG.md#v150v0980) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-collector/compare/v0.97.0...v0.98.0) ##### 🛑 Breaking changes 🛑 - `service`: emit internal collector metrics with \_ instead of / with OTLP export ([#​9774](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9774)) This is addressing an issue w/ the names of the metrics generated by the Collector for its internal metrics. Note that this change only impacts users that emit telemetry using OTLP, which is currently still in experimental support. The prometheus metrics already replaced `/` with `_` and they will do the same with `_`. ##### 💡 Enhancements 💡 - `mdatagen`: Adds unsupported platforms to the README header ([#​9794](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9794)) - `confmap`: Clarify the use of embedded structs to make unmarshaling composable ([#​7101](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7101)) - `nopexporter`: Promote the nopexporter to beta ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) - `nopreceiver`: Promote the nopreceiver to beta ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) - `otlpexporter`: Checks for port in the config validation for the otlpexporter ([#​9505](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9505)) - `service`: Validate pipeline type against component types ([#​8007](https://togithub.com/open-telemetry/opentelemetry-collector/issues/8007)) ##### 🧰 Bug fixes 🧰 - `configtls`: Fix issue where `IncludeSystemCACertsPool` was not consistently used between `ServerConfig` and `ClientConfig`. ([#​9835](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9835)) - `component`: Fix issue where the `components` command wasn't properly printing the component type. ([#​9856](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9856)) - `otelcol`: Fix issue where the `validate` command wasn't properly printing valid component type. ([#​9866](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9866)) - `receiver/otlp`: Fix bug where the otlp receiver did not properly respond with a retryable error code when possible for http ([#​9357](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9357)) ### [`v0.97.0`](https://togithub.com/open-telemetry/opentelemetry-collector/blob/HEAD/CHANGELOG.md#v140v0970) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-collector/compare/v0.96.0...v0.97.0) ##### 🛑 Breaking changes 🛑 - `telemetry`: Remove telemetry.useOtelForInternalMetrics stable feature gate ([#​9752](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9752)) ##### 🚀 New components 🚀 - `exporter/nop`: Add the `nopexporter` to serve as a placeholder exporter in a pipeline ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) This is primarily useful for starting the Collector with only extensions enabled or to test Collector pipeline throughput. - `receiver/nop`: Add the `nopreceiver` to serve as a placeholder receiver in a pipeline ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) This is primarily useful for starting the Collector with only extensions enabled. ##### 💡 Enhancements 💡 - `configtls`: Validates TLS min_version and max_version ([#​9475](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9475)) Introduces `Validate()` method in TLSSetting. - `configcompression`: Mark module as Stable. ([#​9571](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9571)) - `cmd/mdatagen`: Use go package name for the scope name by default and add an option to provide the scope name in metadata.yaml. ([#​9693](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9693)) - `cmd/mdatagen`: Generate the lifecycle tests for components by default. ([#​9683](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9683)) It's encouraged to have lifecycle tests for all components enadled, but they can be disabled if needed in metadata.yaml with `skip_lifecycle: true` and `skip_shutdown: true` under `tests` section. - `cmd/mdatagen`: optimize the mdatagen for the case like batchprocessor which use a common struct to implement consumer.Traces, consumer.Metrics, consumer.Logs in the meantime. ([#​9688](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9688)) ##### 🧰 Bug fixes 🧰 - `exporterhelper`: Fix persistent queue size backup on reads. ([#​9740](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9740)) - `processor/batch`: Prevent starting unnecessary goroutines. ([#​9739](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9739)) - `otlphttpexporter`: prevent error on empty response body when content type is application/json ([#​9666](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9666)) - `confmap`: confmap honors `Unmarshal` methods on config embedded structs. ([#​6671](https://togithub.com/open-telemetry/opentelemetry-collector/issues/6671)) - `otelcol`: Respect telemetry configuration when running as a Windows service ([#​5300](https://togithub.com/open-telemetry/opentelemetry-collector/issues/5300))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update module go.opentelemetry.io/collector/exporter/otlphttpexporter to v0.98.0 (#9974) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/collector/exporter/otlphttpexporter](https://togithub.com/open-telemetry/opentelemetry-collector) | `v0.97.0` -> `v0.98.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.97.0/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.97.0/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-collector (go.opentelemetry.io/collector/exporter/otlphttpexporter) ### [`v0.98.0`](https://togithub.com/open-telemetry/opentelemetry-collector/blob/HEAD/CHANGELOG.md#v150v0980) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-collector/compare/v0.97.0...v0.98.0) ##### 🛑 Breaking changes 🛑 - `service`: emit internal collector metrics with \_ instead of / with OTLP export ([#​9774](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9774)) This is addressing an issue w/ the names of the metrics generated by the Collector for its internal metrics. Note that this change only impacts users that emit telemetry using OTLP, which is currently still in experimental support. The prometheus metrics already replaced `/` with `_` and they will do the same with `_`. ##### 💡 Enhancements 💡 - `mdatagen`: Adds unsupported platforms to the README header ([#​9794](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9794)) - `confmap`: Clarify the use of embedded structs to make unmarshaling composable ([#​7101](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7101)) - `nopexporter`: Promote the nopexporter to beta ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) - `nopreceiver`: Promote the nopreceiver to beta ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) - `otlpexporter`: Checks for port in the config validation for the otlpexporter ([#​9505](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9505)) - `service`: Validate pipeline type against component types ([#​8007](https://togithub.com/open-telemetry/opentelemetry-collector/issues/8007)) ##### 🧰 Bug fixes 🧰 - `configtls`: Fix issue where `IncludeSystemCACertsPool` was not consistently used between `ServerConfig` and `ClientConfig`. ([#​9835](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9835)) - `component`: Fix issue where the `components` command wasn't properly printing the component type. ([#​9856](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9856)) - `otelcol`: Fix issue where the `validate` command wasn't properly printing valid component type. ([#​9866](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9866)) - `receiver/otlp`: Fix bug where the otlp receiver did not properly respond with a retryable error code when possible for http ([#​9357](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9357))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update module go.opentelemetry.io/collector/receiver/otlpreceiver to v0.98.0 (#9976) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/collector/receiver/otlpreceiver](https://togithub.com/open-telemetry/opentelemetry-collector) | `v0.97.0` -> `v0.98.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.97.0/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.97.0/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-collector (go.opentelemetry.io/collector/receiver/otlpreceiver) ### [`v0.98.0`](https://togithub.com/open-telemetry/opentelemetry-collector/blob/HEAD/CHANGELOG.md#v150v0980) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-collector/compare/v0.97.0...v0.98.0) ##### 🛑 Breaking changes 🛑 - `service`: emit internal collector metrics with \_ instead of / with OTLP export ([#​9774](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9774)) This is addressing an issue w/ the names of the metrics generated by the Collector for its internal metrics. Note that this change only impacts users that emit telemetry using OTLP, which is currently still in experimental support. The prometheus metrics already replaced `/` with `_` and they will do the same with `_`. ##### 💡 Enhancements 💡 - `mdatagen`: Adds unsupported platforms to the README header ([#​9794](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9794)) - `confmap`: Clarify the use of embedded structs to make unmarshaling composable ([#​7101](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7101)) - `nopexporter`: Promote the nopexporter to beta ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) - `nopreceiver`: Promote the nopreceiver to beta ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) - `otlpexporter`: Checks for port in the config validation for the otlpexporter ([#​9505](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9505)) - `service`: Validate pipeline type against component types ([#​8007](https://togithub.com/open-telemetry/opentelemetry-collector/issues/8007)) ##### 🧰 Bug fixes 🧰 - `configtls`: Fix issue where `IncludeSystemCACertsPool` was not consistently used between `ServerConfig` and `ClientConfig`. ([#​9835](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9835)) - `component`: Fix issue where the `components` command wasn't properly printing the component type. ([#​9856](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9856)) - `otelcol`: Fix issue where the `validate` command wasn't properly printing valid component type. ([#​9866](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9866)) - `receiver/otlp`: Fix bug where the otlp receiver did not properly respond with a retryable error code when possible for http ([#​9357](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9357))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update github-actions deps (#9971) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [Wandalen/wretry.action](https://togithub.com/Wandalen/wretry.action) | action | minor | `v3.2.0` -> `v3.4.0` | | [github/codeql-action](https://togithub.com/github/codeql-action) | action | minor | `v3.24.10` -> `v3.25.0` | --- ### Release Notes
Wandalen/wretry.action (Wandalen/wretry.action) ### [`v3.4.0`](https://togithub.com/Wandalen/wretry.action/compare/v3.3.0...v3.4.0) [Compare Source](https://togithub.com/Wandalen/wretry.action/compare/v3.3.0...v3.4.0) ### [`v3.3.0`](https://togithub.com/Wandalen/wretry.action/compare/v3.2.0...v3.3.0) [Compare Source](https://togithub.com/Wandalen/wretry.action/compare/v3.2.0...v3.3.0)
github/codeql-action (github/codeql-action) ### [`v3.25.0`](https://togithub.com/github/codeql-action/compare/v3.24.10...v3.25.0) [Compare Source](https://togithub.com/github/codeql-action/compare/v3.24.10...v3.25.0)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update module go.opentelemetry.io/collector/exporter/otlpexporter to v0.98.0 (#9973) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/collector/exporter/otlpexporter](https://togithub.com/open-telemetry/opentelemetry-collector) | `v0.97.0` -> `v0.98.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.97.0/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.97.0/v0.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-collector (go.opentelemetry.io/collector/exporter/otlpexporter) ### [`v0.98.0`](https://togithub.com/open-telemetry/opentelemetry-collector/blob/HEAD/CHANGELOG.md#v150v0980) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-collector/compare/v0.97.0...v0.98.0) ##### 🛑 Breaking changes 🛑 - `service`: emit internal collector metrics with \_ instead of / with OTLP export ([#​9774](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9774)) This is addressing an issue w/ the names of the metrics generated by the Collector for its internal metrics. Note that this change only impacts users that emit telemetry using OTLP, which is currently still in experimental support. The prometheus metrics already replaced `/` with `_` and they will do the same with `_`. ##### 💡 Enhancements 💡 - `mdatagen`: Adds unsupported platforms to the README header ([#​9794](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9794)) - `confmap`: Clarify the use of embedded structs to make unmarshaling composable ([#​7101](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7101)) - `nopexporter`: Promote the nopexporter to beta ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) - `nopreceiver`: Promote the nopreceiver to beta ([#​7316](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7316)) - `otlpexporter`: Checks for port in the config validation for the otlpexporter ([#​9505](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9505)) - `service`: Validate pipeline type against component types ([#​8007](https://togithub.com/open-telemetry/opentelemetry-collector/issues/8007)) ##### 🧰 Bug fixes 🧰 - `configtls`: Fix issue where `IncludeSystemCACertsPool` was not consistently used between `ServerConfig` and `ClientConfig`. ([#​9835](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9835)) - `component`: Fix issue where the `components` command wasn't properly printing the component type. ([#​9856](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9856)) - `otelcol`: Fix issue where the `validate` command wasn't properly printing valid component type. ([#​9866](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9866)) - `receiver/otlp`: Fix bug where the otlp receiver did not properly respond with a retryable error code when possible for http ([#​9357](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9357))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * update to use the config package to configure tracer provider (#9967) Restore the functionality to use the OTel Go Contrib package to configure the SDK for Tracer Providers. Fixes #9715 --------- Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] [mdatagen] Fix generated tests for include/exclude capability (#9978) Unblocking https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/32394, again * Distribute internal metrics across different levels (#9767) **Description:** This change distributes the reported internal metrics across available levels and updates the level set by default: 1. The default level is changed from `basic` to `normal`, which can be overridden with `service::telmetry::metrics::level` configuration. 2. The following batch processor metrics are updated to be reported starting from `normal` level instead of `basic` level: - `processor_batch_batch_send_size` - `processor_batch_metadata_cardinality` - `processor_batch_timeout_trigger_send` - `processor_batch_size_trigger_send` 3. The following GRPC/HTTP server and client metrics are updated to be reported starting from `detailed` level: - `http.client.*` metrics - `http.server.*` metrics - `rpc.server.*` metrics - `rpc.client.*` metrics **Link to tracking Issue:** https://github.com/open-telemetry/opentelemetry-collector/issues/7890 * Update module golang.org/x/vuln to v1.1.0 (#9980) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | golang.org/x/vuln | `v1.0.4` -> `v1.1.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fvuln/v1.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/golang.org%2fx%2fvuln/v1.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/golang.org%2fx%2fvuln/v1.0.4/v1.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fvuln/v1.0.4/v1.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * [mdatagen] generate goleak package test (#9959) This automates the generation of package_test.go for any component that uses mdatagen. The following configuration can be used to skip or ignore certain funcs: ```yaml tests: goleak: skip: true tests: goleak: ignore: top: - "go.opencensus.io/stats/view.(*worker).start" ``` --------- Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [builder] Add strict versioning (#9897) **Description:** Adds strict version checking in the builder. This enables users to ensure that the versions specified in the builder config are the versions used in the go.mod when building the collector binary. This can be disabled with --skip-strict-versioning. **Link to tracking Issue:** #9896 **Testing:** Added unit tests **Documentation:** Added to builder README --------- Co-authored-by: Pablo Baeyens * [chore] change @astencel-sumo to @andrzej-stencel (#9990) I have changed my GitHub username following https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-user-account-settings/changing-your-github-username. * [confmap] Add converter and provider settings to confmap.ResolverSettings (#9516) **Description:** Follows https://github.com/open-telemetry/opentelemetry-collector/pull/9443, relates to https://github.com/open-telemetry/opentelemetry-collector/pull/9513. This builds on https://github.com/open-telemetry/opentelemetry-collector/pull/9228 to demonstrate the concept. This shows one way of extending the otelcol APIs to allow passing converters and providers from the builder with the new settings structs for each type. I think this approach has a few advantages: 1. This follows our pattern of passing in "factory" functions instead of instances to the object that actually uses the instances. 2. Makes the API more declarative: the settings specify which modules to instantiate and which settings to instantiate them with, but don't require the caller to actually do this. 3. Compared to the current state, this allows us to update the config at different layers. A distribution's `main.go` file can specify the providers/converters it wants and leave the settings to be created by `otelcol.Collector`. The primary drawbacks I see here are: 1. This is a little more opinionated since you don't have access to the converter/provider instances or control how they are instantiated. I think this is acceptable and provides good encapsulation. 2. The scheme->provider map can now only be specified by the providers' schemes, which is how it is currently done by default. I would want to hear what use cases we see for more complex control here that necessitates using schemes not specified by the providers. cc @mx-psi --------- Co-authored-by: Evan Bradley * [mdatagen] add setup/teardown configuration (#9993) This allows components with existing TestMain funcs to use the auto generated goleak checks Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] update package test template (#9994) Ensure setup/teardown are respected even when goleak is skipped. Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Added default functions for configauth (#9850) Description: Added NewDefault methods for structs in `configauth` package Link to tracking Issue: Closes https://github.com/open-telemetry/opentelemetry-collector/issues/9821 Testing: Tests were added for the NewDefault functions --------- Co-authored-by: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] Clean up pull request template (#9995) #### Description Mainly to save myself a little effort when opening PRs. :slightly_smiling_face: I don't think the paragraph at the top is enforced, so I removed it. This probably depends on some output from https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/32491, so I tried to keep the changes hopefully somewhat unopinionated (the resulting description looks similar to how it does now). Happy to wait on that, reduce scope, or open follow-ups. cc @codeboten @crobert-1 --------- Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> Co-authored-by: Curtis Robert * [chore] Double Windows unit tests timeout (#9992) Bump the timeout for the Windows unit tests from 120s to 240s. The tests currently are brushing up very close to this limit and are becoming flaky as a result. [Example run](https://github.com/open-telemetry/opentelemetry-collector/actions/runs/8739137193/job/23984602883?pr=9516#step:5:19): ``` ok go.opentelemetry.io/collector/cmd/builder/internal/builder 116.086s ``` * Update go.opentelemetry.io/proto/otlp to v1.2.0 (#9985) Update the OTLP proto dependency and generated code. I plan to use the metric.metadata field to support additional prometheus types per https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/compatibility/prometheus_and_openmetrics.md#metric-metadata * OTLP HTTP Exporter: Propagate HTTP 429s (#9905) Changes otlphttp status code handling to propagate the error code as a grpc status code. This follows the logic that was implemented for the http receiver [here](https://github.com/open-telemetry/opentelemetry-collector/pull/9893/files). Fixes #9892 **Testing:** local tests were updated, going to test a local build. * [confmap] Return error when decoding negative values into uints (#9169) **Description:** This adds a decode hook for unmarshalling negative integers into uint types. This will now return an error instead of converting negative values into large uint values. **Link to tracking Issue:** Fixes #9060 **Testing:** Added unit tests for confmap functionality, functional tests in memory limiter processor (the original component this issue was filed against) * [cmd/builder] Improve TestVersioning (#10000) #### Description Improves `TestVersioning` added on #9897. The configurations were not what one would usually find, since when running the builder we do some validation and setup. This makes it closer to the real case. In the process I removed the 'invalid' cases, since these error out today already * [cmd/builder] Remove undocumented strictness check (#9999) Partially reverts #9897. This was not documented on the original PR and is IMO too strict. We likely want to allow for some skew between versions. Mentioned on https://github.com/open-telemetry/opentelemetry-collector/pull/9513#issuecomment-2065586307 --------- Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Support metric.metadata in pdata/pmetric (#10006) #### Description After https://github.com/open-telemetry/opentelemetry-collector/pull/9985, add support for the new metric.metadata field in the pmetric package. I plan to use the metric.metadata field to support additional prometheus types per https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/compatibility/prometheus_and_openmetrics.md#metric-metadata * [builder] only compare major and minor versions from gomod (#9997) #### Description When building from a commit hash, I got this error: ``` Error: mismatch in go.mod and builder configuration versions: core collector version calculated by component dependencies "v0.98.1-0.20240416174005-d0f15e2463f8" does not match configured version "v0.98.0". Use --skip-strict-versioning to temporarily disable this check. This flag will be removed in a future minor version ``` It may be more useful to only compare the major and minor versions #### Link to tracking issue https://github.com/open-telemetry/opentelemetry-collector/issues/9896 Found in https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/32544 #### Testing Manually tested new build #### Documentation updated readme * [cmd/builder] Allow configuring confmap providers (#9513) **Description:** Allow configuring confmap providers in the builder's config. If the field isn't set, the default set of providers is used. **Link to tracking Issue:** Resolves https://github.com/open-telemetry/opentelemetry-collector/issues/4759. **Testing:** Extended unit tests. **Documentation:** Updated the readme to include the new options in the example manifest file. cc @mx-psi --------- Co-authored-by: Evan Bradley Co-authored-by: Pablo Baeyens * Remove `GetExporters` from component.Host (#9987) **Description:** Remove the deprecated `GetExporters` function from `component.Host` **Link to tracking Issue:** Related to https://github.com/open-telemetry/opentelemetry-collector/issues/7370 * [exporter/otlp] Allow DNS scheme to be used in endpoint (#10010) Fixes #4274 Signed-off-by: Juraci Paixão Kröhling * [mdatagen] Rename include/exclude config options (#9960) The `include` and `exclude ` options in the resource attributes group sound confusing. It's easy to assume that matching filters will include or exclude resource attributes themselves while they control emitted resource metrics. The proposal is to change the include/exclude options to `metrics_include`/`metrics_exclude` with detailed comments. These names make it cleaner that matching rules limit the emitted metrics, not resource attributes. Updates https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/25134 * [chore][cmd/builder] Include replaces in builder versioning tests (#10016) #### Description This is necessary when testing the builder with unreleased versions of Collector modules. #### Link to tracking issue Fixes https://github.com/open-telemetry/opentelemetry-collector/issues/10014 * [chore] Prepare release v1.6.0/v0.99.0 (#10018) The following commands were run to prepare this release: - make chlog-update VERSION=v1.6.0/v0.99.0 - make prepare-release PREVIOUS_VERSION=1.5.0 RELEASE_CANDIDATE=1.6.0 MODSET=stable - make prepare-release PREVIOUS_VERSION=0.98.0 RELEASE_CANDIDATE=0.99.0 MODSET=beta * Update module go.opentelemetry.io/collector/receiver/otlpreceiver to v0.99.0 (#10024) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/collector/receiver/otlpreceiver](https://togithub.com/open-telemetry/opentelemetry-collector) | `v0.98.0` -> `v0.99.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.99.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.99.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.98.0/v0.99.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcollector%2freceiver%2fotlpreceiver/v0.98.0/v0.99.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-collector (go.opentelemetry.io/collector/receiver/otlpreceiver) ### [`v0.99.0`](https://togithub.com/open-telemetry/opentelemetry-collector/blob/HEAD/CHANGELOG.md#v160v0990) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-collector/compare/v0.98.0...v0.99.0) ##### 🛑 Breaking changes 🛑 - `builder`: Add strict version checking when using the builder. Add the temporary flag ` --skip-strict-versioning `for skipping this check. ([#​9896](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9896)) Strict version checking will error on major and minor version mismatches between the `otelcol_version` configured and the builder version or versions in the go.mod. This check can be temporarily disabled by using the `--skip-strict-versioning` flag. This flag will be removed in a future minor version. - `telemetry`: Distributed internal metrics across different levels. ([#​7890](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7890)) The internal metrics levels are updated along with reported metrics: - The default level is changed from `basic` to `normal`, which can be overridden with `service::telmetry::metrics::level` configuration. - Batch processor metrics are updated to be reported starting from `normal` level: - `processor_batch_batch_send_size` - `processor_batch_metadata_cardinality` - `processor_batch_timeout_trigger_send` - `processor_batch_size_trigger_send` - GRPC/HTTP server and client metrics are updated to be reported starting from `detailed` level: - http.client.\* metrics - http.server.\* metrics - rpc.server.\* metrics - rpc.client.\* metrics ##### 💡 Enhancements 💡 - `confighttp`: Disable concurrency in zstd compression ([#​8216](https://togithub.com/open-telemetry/opentelemetry-collector/issues/8216)) - `cmd/builder`: Allow configuring `confmap.Provider`s in the builder. ([#​4759](https://togithub.com/open-telemetry/opentelemetry-collector/issues/4759)) If no providers are specified, the defaults are used. The default providers are: env, file, http, https, and yaml. To configure providers, use the `providers` key in your OCB build manifest with a list of Go modules for your providers. The modules will work the same as other Collector components. - `mdatagen`: enable goleak tests by default via mdatagen ([#​9959](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9959)) - `cmd/mdatagen`: support excluding some metrics based on string and regexes in resource_attributes ([#​9661](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9661)) - `cmd/mdatagen`: Generate config and factory tests covering their requirements. ([#​9940](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9940)) The tests are moved from cmd/builder. - `confmap`: Add `ProviderSettings`, `ConverterSettings`, `ProviderFactories`, and `ConverterFactories` fields to `confmap.ResolverSettings` ([#​9516](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9516)) This allows configuring providers and converters, which are instantiated by `NewResolver` using the given factories. ##### 🧰 Bug fixes 🧰 - `exporter/otlp`: Allow DNS scheme to be used in endpoint ([#​4274](https://togithub.com/open-telemetry/opentelemetry-collector/issues/4274)) - `service`: fix record sampler configuration ([#​9968](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9968)) - `service`: ensure the tracer provider is configured via go.opentelemetry.io/contrib/config ([#​9967](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9967)) - `otlphttpexporter`: Fixes a bug that was preventing the otlp http exporter from propagating status. ([#​9892](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9892)) - `confmap`: Fix decoding negative configuration values into uints ([#​9060](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9060))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update module go.opentelemetry.io/collector/exporter/otlpexporter to v0.99.0 (#10022) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/collector/exporter/otlpexporter](https://togithub.com/open-telemetry/opentelemetry-collector) | `v0.98.0` -> `v0.99.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.99.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.99.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.98.0/v0.99.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlpexporter/v0.98.0/v0.99.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-collector (go.opentelemetry.io/collector/exporter/otlpexporter) ### [`v0.99.0`](https://togithub.com/open-telemetry/opentelemetry-collector/blob/HEAD/CHANGELOG.md#v160v0990) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-collector/compare/v0.98.0...v0.99.0) ##### 🛑 Breaking changes 🛑 - `builder`: Add strict version checking when using the builder. Add the temporary flag ` --skip-strict-versioning `for skipping this check. ([#​9896](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9896)) Strict version checking will error on major and minor version mismatches between the `otelcol_version` configured and the builder version or versions in the go.mod. This check can be temporarily disabled by using the `--skip-strict-versioning` flag. This flag will be removed in a future minor version. - `telemetry`: Distributed internal metrics across different levels. ([#​7890](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7890)) The internal metrics levels are updated along with reported metrics: - The default level is changed from `basic` to `normal`, which can be overridden with `service::telmetry::metrics::level` configuration. - Batch processor metrics are updated to be reported starting from `normal` level: - `processor_batch_batch_send_size` - `processor_batch_metadata_cardinality` - `processor_batch_timeout_trigger_send` - `processor_batch_size_trigger_send` - GRPC/HTTP server and client metrics are updated to be reported starting from `detailed` level: - http.client.\* metrics - http.server.\* metrics - rpc.server.\* metrics - rpc.client.\* metrics ##### 💡 Enhancements 💡 - `confighttp`: Disable concurrency in zstd compression ([#​8216](https://togithub.com/open-telemetry/opentelemetry-collector/issues/8216)) - `cmd/builder`: Allow configuring `confmap.Provider`s in the builder. ([#​4759](https://togithub.com/open-telemetry/opentelemetry-collector/issues/4759)) If no providers are specified, the defaults are used. The default providers are: env, file, http, https, and yaml. To configure providers, use the `providers` key in your OCB build manifest with a list of Go modules for your providers. The modules will work the same as other Collector components. - `mdatagen`: enable goleak tests by default via mdatagen ([#​9959](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9959)) - `cmd/mdatagen`: support excluding some metrics based on string and regexes in resource_attributes ([#​9661](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9661)) - `cmd/mdatagen`: Generate config and factory tests covering their requirements. ([#​9940](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9940)) The tests are moved from cmd/builder. - `confmap`: Add `ProviderSettings`, `ConverterSettings`, `ProviderFactories`, and `ConverterFactories` fields to `confmap.ResolverSettings` ([#​9516](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9516)) This allows configuring providers and converters, which are instantiated by `NewResolver` using the given factories. ##### 🧰 Bug fixes 🧰 - `exporter/otlp`: Allow DNS scheme to be used in endpoint ([#​4274](https://togithub.com/open-telemetry/opentelemetry-collector/issues/4274)) - `service`: fix record sampler configuration ([#​9968](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9968)) - `service`: ensure the tracer provider is configured via go.opentelemetry.io/contrib/config ([#​9967](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9967)) - `otlphttpexporter`: Fixes a bug that was preventing the otlp http exporter from propagating status. ([#​9892](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9892)) - `confmap`: Fix decoding negative configuration values into uints ([#​9060](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9060))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update github-actions deps (#10019) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [actions/checkout](https://togithub.com/actions/checkout) | action | patch | `v4.1.1` -> `v4.1.3` | | [actions/upload-artifact](https://togithub.com/actions/upload-artifact) | action | patch | `v4.3.1` -> `v4.3.3` | | [github/codeql-action](https://togithub.com/github/codeql-action) | action | patch | `v3.25.0` -> `v3.25.2` | --- ### Release Notes
actions/checkout (actions/checkout) ### [`v4.1.3`](https://togithub.com/actions/checkout/releases/tag/v4.1.3) [Compare Source](https://togithub.com/actions/checkout/compare/v4.1.2...v4.1.3) #### What's Changed - Update `actions/checkout` version in `update-main-version.yml` by [@​jww3](https://togithub.com/jww3) in [https://github.com/actions/checkout/pull/1650](https://togithub.com/actions/checkout/pull/1650) - Check git version before attempting to disable `sparse-checkout` by [@​jww3](https://togithub.com/jww3) in [https://github.com/actions/checkout/pull/1656](https://togithub.com/actions/checkout/pull/1656) - Add SSH user parameter by [@​cory-miller](https://togithub.com/cory-miller) in [https://github.com/actions/checkout/pull/1685](https://togithub.com/actions/checkout/pull/1685) **Full Changelog**: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3 ### [`v4.1.2`](https://togithub.com/actions/checkout/blob/HEAD/CHANGELOG.md#v412) [Compare Source](https://togithub.com/actions/checkout/compare/v4.1.1...v4.1.2) - Fix: Disable sparse checkout whenever `sparse-checkout` option is not present [@​dscho](https://togithub.com/dscho) in [https://github.com/actions/checkout/pull/1598](https://togithub.com/actions/checkout/pull/1598)
actions/upload-artifact (actions/upload-artifact) ### [`v4.3.3`](https://togithub.com/actions/upload-artifact/releases/tag/v4.3.3) [Compare Source](https://togithub.com/actions/upload-artifact/compare/v4.3.2...v4.3.3) ##### What's Changed - updating `@actions/artifact` dependency to v2.1.6 by [@​eggyhead](https://togithub.com/eggyhead) in [https://github.com/actions/upload-artifact/pull/565](https://togithub.com/actions/upload-artifact/pull/565) **Full Changelog**: https://github.com/actions/upload-artifact/compare/v4.3.2...v4.3.3 ### [`v4.3.2`](https://togithub.com/actions/upload-artifact/releases/tag/v4.3.2) [Compare Source](https://togithub.com/actions/upload-artifact/compare/v4.3.1...v4.3.2) #### What's Changed - Update release-new-action-version.yml by [@​konradpabjan](https://togithub.com/konradpabjan) in [https://github.com/actions/upload-artifact/pull/516](https://togithub.com/actions/upload-artifact/pull/516) - Minor fix to the migration readme by [@​andrewakim](https://togithub.com/andrewakim) in [https://github.com/actions/upload-artifact/pull/523](https://togithub.com/actions/upload-artifact/pull/523) - Update readme with v3/v2/v1 deprecation notice by [@​robherley](https://togithub.com/robherley) in [https://github.com/actions/upload-artifact/pull/561](https://togithub.com/actions/upload-artifact/pull/561) - updating `@actions/artifact` dependency to v2.1.5 and `@actions/core` to v1.0.1 by [@​eggyhead](https://togithub.com/eggyhead) in [https://github.com/actions/upload-artifact/pull/562](https://togithub.com/actions/upload-artifact/pull/562) #### New Contributors - [@​andrewakim](https://togithub.com/andrewakim) made their first contribution in [https://github.com/actions/upload-artifact/pull/523](https://togithub.com/actions/upload-artifact/pull/523) **Full Changelog**: https://github.com/actions/upload-artifact/compare/v4.3.1...v4.3.2
github/codeql-action (github/codeql-action) ### [`v3.25.2`](https://togithub.com/github/codeql-action/compare/v3.25.1...v3.25.2) [Compare Source](https://togithub.com/github/codeql-action/compare/v3.25.1...v3.25.2) ### [`v3.25.1`](https://togithub.com/github/codeql-action/compare/v3.25.0...v3.25.1) [Compare Source](https://togithub.com/github/codeql-action/compare/v3.25.0...v3.25.1)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update module go.opentelemetry.io/collector/exporter/otlphttpexporter to v0.99.0 (#10023) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/collector/exporter/otlphttpexporter](https://togithub.com/open-telemetry/opentelemetry-collector) | `v0.98.0` -> `v0.99.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.99.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.99.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.98.0/v0.99.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcollector%2fexporter%2fotlphttpexporter/v0.98.0/v0.99.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-collector (go.opentelemetry.io/collector/exporter/otlphttpexporter) ### [`v0.99.0`](https://togithub.com/open-telemetry/opentelemetry-collector/blob/HEAD/CHANGELOG.md#v160v0990) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-collector/compare/v0.98.0...v0.99.0) ##### 🛑 Breaking changes 🛑 - `builder`: Add strict version checking when using the builder. Add the temporary flag ` --skip-strict-versioning `for skipping this check. ([#​9896](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9896)) Strict version checking will error on major and minor version mismatches between the `otelcol_version` configured and the builder version or versions in the go.mod. This check can be temporarily disabled by using the `--skip-strict-versioning` flag. This flag will be removed in a future minor version. - `telemetry`: Distributed internal metrics across different levels. ([#​7890](https://togithub.com/open-telemetry/opentelemetry-collector/issues/7890)) The internal metrics levels are updated along with reported metrics: - The default level is changed from `basic` to `normal`, which can be overridden with `service::telmetry::metrics::level` configuration. - Batch processor metrics are updated to be reported starting from `normal` level: - `processor_batch_batch_send_size` - `processor_batch_metadata_cardinality` - `processor_batch_timeout_trigger_send` - `processor_batch_size_trigger_send` - GRPC/HTTP server and client metrics are updated to be reported starting from `detailed` level: - http.client.\* metrics - http.server.\* metrics - rpc.server.\* metrics - rpc.client.\* metrics ##### 💡 Enhancements 💡 - `confighttp`: Disable concurrency in zstd compression ([#​8216](https://togithub.com/open-telemetry/opentelemetry-collector/issues/8216)) - `cmd/builder`: Allow configuring `confmap.Provider`s in the builder. ([#​4759](https://togithub.com/open-telemetry/opentelemetry-collector/issues/4759)) If no providers are specified, the defaults are used. The default providers are: env, file, http, https, and yaml. To configure providers, use the `providers` key in your OCB build manifest with a list of Go modules for your providers. The modules will work the same as other Collector components. - `mdatagen`: enable goleak tests by default via mdatagen ([#​9959](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9959)) - `cmd/mdatagen`: support excluding some metrics based on string and regexes in resource_attributes ([#​9661](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9661)) - `cmd/mdatagen`: Generate config and factory tests covering their requirements. ([#​9940](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9940)) The tests are moved from cmd/builder. - `confmap`: Add `ProviderSettings`, `ConverterSettings`, `ProviderFactories`, and `ConverterFactories` fields to `confmap.ResolverSettings` ([#​9516](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9516)) This allows configuring providers and converters, which are instantiated by `NewResolver` using the given factories. ##### 🧰 Bug fixes 🧰 - `exporter/otlp`: Allow DNS scheme to be used in endpoint ([#​4274](https://togithub.com/open-telemetry/opentelemetry-collector/issues/4274)) - `service`: fix record sampler configuration ([#​9968](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9968)) - `service`: ensure the tracer provider is configured via go.opentelemetry.io/contrib/config ([#​9967](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9967)) - `otlphttpexporter`: Fixes a bug that was preventing the otlp http exporter from propagating status. ([#​9892](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9892)) - `confmap`: Fix decoding negative configuration values into uints ([#​9060](https://togithub.com/open-telemetry/opentelemetry-collector/issues/9060))
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update module github.com/prometheus/common to v0.53.0 (#10021) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [github.com/prometheus/common](https://togithub.com/prometheus/common) | `v0.52.3` -> `v0.53.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fprometheus%2fcommon/v0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/github.com%2fprometheus%2fcommon/v0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/github.com%2fprometheus%2fcommon/v0.52.3/v0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fprometheus%2fcommon/v0.52.3/v0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
prometheus/common (github.com/prometheus/common) ### [`v0.53.0`](https://togithub.com/prometheus/common/releases/tag/v0.53.0) [Compare Source](https://togithub.com/prometheus/common/compare/v0.52.3...v0.53.0) #### What's Changed - Add StatusAt method for Alert struct by [@​grobinson-grafana](https://togithub.com/grobinson-grafana) in [https://github.com/prometheus/common/pull/618](https://togithub.com/prometheus/common/pull/618) - config: allow exposing real secret value through marshal by [@​GiedriusS](https://togithub.com/GiedriusS) in [https://github.com/prometheus/common/pull/487](https://togithub.com/prometheus/common/pull/487) - Fix up config test by [@​SuperQ](https://togithub.com/SuperQ) in [https://github.com/prometheus/common/pull/621](https://togithub.com/prometheus/common/pull/621) - LabelSet.String: restore faster sort call by [@​bboreham](https://togithub.com/bboreham) in [https://github.com/prometheus/common/pull/619](https://togithub.com/prometheus/common/pull/619) - LabelSet: add unit test for String method by [@​bboreham](https://togithub.com/bboreham) in [https://github.com/prometheus/common/pull/620](https://togithub.com/prometheus/common/pull/620) #### New Contributors - [@​grobinson-grafana](https://togithub.com/grobinson-grafana) made their first contribution in [https://github.com/prometheus/common/pull/618](https://togithub.com/prometheus/common/pull/618) - [@​GiedriusS](https://togithub.com/GiedriusS) made their first contribution in [https://github.com/prometheus/common/pull/487](https://togithub.com/prometheus/common/pull/487) **Full Changelog**: https://github.com/prometheus/common/compare/v0.52.3...v0.53.0
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * [builder] remove ambigious import codepath (#10015) This code was added to handled an ambiguous import caused by a dependency that has been updated since v0.98.0. --------- Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * chore: fix function names in comment (#10027) fix function names in comment Signed-off-by: dockercui Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Support parsing metric.metadata from OTLP JSON (#10026) Follow-up to https://github.com/open-telemetry/opentelemetry-collector/pull/10006, which added metric.metadata to pmetric. I forgot to add support for parsing the field from JSON in that PR. This PR adds the missing support. #### Testing Unit tests * Added default funcs for configgrpc (#9969) Description: Added newDefault methods for structs in configgrpc package Closes https://github.com/open-telemetry/opentelemetry-collector/issues/9654 Testing: Tests were added for the NewDefault functions --------- Co-authored-by: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [mdatagen] move telemetry into its own file (#10037) This is in preparation for using mdatagen for component telemetry. --------- Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] Remove GO111MODULE references (#10039) This has been set to `on` by default since Go 1.16: https://go.dev/doc/go1.16#go-command. Co-authored-by: Evan Bradley * chore(deps): update github-actions deps (#10044) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [actions/checkout](https://togithub.com/actions/checkout) | action | patch | `v4.1.3` -> `v4.1.4` | | [github/codeql-action](https://togithub.com/github/codeql-action) | action | patch | `v3.25.2` -> `v3.25.3` | --- ### Release Notes
actions/checkout (actions/checkout) ### [`v4.1.4`](https://togithub.com/actions/checkout/blob/HEAD/CHANGELOG.md#v414) [Compare Source](https://togithub.com/actions/checkout/compare/v4.1.3...v4.1.4) - Disable `extensions.worktreeConfig` when disabling `sparse-checkout` by [@​jww3](https://togithub.com/jww3) in [https://github.com/actions/checkout/pull/1692](https://togithub.com/actions/checkout/pull/1692) - Add dependabot config by [@​cory-miller](https://togithub.com/cory-miller) in [https://github.com/actions/checkout/pull/1688](https://togithub.com/actions/checkout/pull/1688) - Bump the minor-actions-dependencies group with 2 updates by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/actions/checkout/pull/1693](https://togithub.com/actions/checkout/pull/1693) - Bump word-wrap from 1.2.3 to 1.2.5 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/actions/checkout/pull/1643](https://togithub.com/actions/checkout/pull/1643)
github/codeql-action (github/codeql-action) ### [`v3.25.3`](https://togithub.com/github/codeql-action/compare/v3.25.2...v3.25.3) [Compare Source](https://togithub.com/github/codeql-action/compare/v3.25.2...v3.25.3)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update module go.opentelemetry.io/contrib/propagators/b3 to v1.26.0 (#10049) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/contrib/propagators/b3](https://togithub.com/open-telemetry/opentelemetry-go-contrib) | `v1.25.0` -> `v1.26.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcontrib%2fpropagators%2fb3/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcontrib%2fpropagators%2fb3/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcontrib%2fpropagators%2fb3/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcontrib%2fpropagators%2fb3/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-go-contrib (go.opentelemetry.io/contrib/propagators/b3) ### [`v1.26.0`](https://togithub.com/open-telemetry/opentelemetry-go-contrib/releases/tag/v1.26.0): /v0.51.0/v0.20.0/v0.6.0/v0.1.0 [Compare Source](https://togithub.com/open-telemetry/opentelemetry-go-contrib/compare/v1.25.0...v1.26.0) ##### Added - `NewSDK` in `go.opentelemetry.io/contrib/config` now returns a configured SDK with a valid `MeterProvider`. ([#​4804](https://togithub.com/open-telemetry/opentelemetry-go-contrib/issues/4804)) ##### Changed - Change the scope name for the prometheus bridge to `go.opentelemetry.io/contrib/bridges/prometheus` to match the package. ([#​5396](https://togithub.com/open-telemetry/opentelemetry-go-contrib/issues/5396)) ##### Fixed - Fix bug where an empty exemplar was added to counters in `go.opentelemetry.io/contrib/bridges/prometheus`. ([#​5395](https://togithub.com/open-telemetry/opentelemetry-go-contrib/issues/5395)) - Fix bug where the last histogram bucket was missing in `go.opentelemetry.io/contrib/bridges/prometheus`. ([#​5395](https://togithub.com/open-telemetry/opentelemetry-go-contrib/issues/5395)) **Full Changelog**: https://github.com/open-telemetry/opentelemetry-go-contrib/compare/v1.25.0...v1.26.0
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * fix(deps): update module go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc to v0.51.0 (#10047) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc](https://togithub.com/open-telemetry/opentelemetry-go-contrib) | `v0.50.0` -> `v0.51.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fgoogle.golang.org%2fgrpc%2fotelgrpc/v0.51.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fgoogle.golang.org%2fgrpc%2fotelgrpc/v0.51.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fgoogle.golang.org%2fgrpc%2fotelgrpc/v0.50.0/v0.51.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fgoogle.golang.org%2fgrpc%2fotelgrpc/v0.50.0/v0.51.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * fix(deps): update module google.golang.org/protobuf to v1.34.0 (#10051) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [google.golang.org/protobuf](https://togithub.com/protocolbuffers/protobuf-go) | `v1.33.0` -> `v1.34.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/google.golang.org%2fprotobuf/v1.34.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/google.golang.org%2fprotobuf/v1.34.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/google.golang.org%2fprotobuf/v1.33.0/v1.34.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/google.golang.org%2fprotobuf/v1.33.0/v1.34.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
protocolbuffers/protobuf-go (google.golang.org/protobuf) ### [`v1.34.0`](https://togithub.com/protocolbuffers/protobuf-go/compare/v1.33.0...v1.34.0) [Compare Source](https://togithub.com/protocolbuffers/protobuf-go/compare/v1.33.0...v1.34.0)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * [chore] group contrib packages (#10053) This follows the monorepo preset pattern here: https://docs.renovatebot.com/presets-monorepo/#monorepoopentelemetry-go Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * fix(deps): update opentelemetry-go monorepo (#10052) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/otel](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.25.0` -> `v1.26.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/bridge/opencensus](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.25.0` -> `v1.26.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fbridge%2fopencensus/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fbridge%2fopencensus/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fbridge%2fopencensus/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fbridge%2fopencensus/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.25.0` -> `v1.26.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetricgrpc/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetricgrpc/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetricgrpc/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetricgrpc/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.25.0` -> `v1.26.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetrichttp/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetrichttp/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetrichttp/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fexporters%2fotlp%2fotlpmetric%2fotlpmetrichttp/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/exporters/prometheus](https://togithub.com/open-telemetry/opentelemetry-go) | `v0.47.0` -> `v0.48.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fexporters%2fprometheus/v0.48.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fexporters%2fprometheus/v0.48.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fexporters%2fprometheus/v0.47.0/v0.48.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fexporters%2fprometheus/v0.47.0/v0.48.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/exporters/stdout/stdoutmetric](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.25.0` -> `v1.26.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fexporters%2fstdout%2fstdoutmetric/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fexporters%2fstdout%2fstdoutmetric/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fexporters%2fstdout%2fstdoutmetric/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fexporters%2fstdout%2fstdoutmetric/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/metric](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.25.0` -> `v1.26.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fmetric/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fmetric/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fmetric/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fmetric/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/sdk](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.25.0` -> `v1.26.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fsdk/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fsdk/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fsdk/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fsdk/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/sdk/metric](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.25.0` -> `v1.26.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2fsdk%2fmetric/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2fsdk%2fmetric/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2fsdk%2fmetric/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2fsdk%2fmetric/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/otel/trace](https://togithub.com/open-telemetry/opentelemetry-go) | `v1.25.0` -> `v1.26.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fotel%2ftrace/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fotel%2ftrace/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fotel%2ftrace/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fotel%2ftrace/v1.25.0/v1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-go (go.opentelemetry.io/otel) ### [`v1.26.0`](https://togithub.com/open-telemetry/opentelemetry-go/releases/tag/v1.26.0): /v0.48.0/v0.2.0-alpha [Compare Source](https://togithub.com/open-telemetry/opentelemetry-go/compare/v1.25.0...v1.26.0) ##### Added - Add `Recorder` in `go.opentelemetry.io/otel/log/logtest` to facilitate testing the log bridge implementations. ([#​5134](https://togithub.com/open-telemetry/opentelemetry-go/issues/5134)) - Add span flags to OTLP spans and links exported by `go.opentelemetry.io/otel/exporters/otlp/otlptrace`. ([#​5194](https://togithub.com/open-telemetry/opentelemetry-go/issues/5194)) - Make the initial alpha release of `go.opentelemetry.io/otel/sdk/log`. This new module contains the Go implementation of the OpenTelemetry Logs SDK. This module is unstable and breaking changes may be introduced. See our [versioning policy](VERSIONING.md) for more information about these stability guarantees. ([#​5240](https://togithub.com/open-telemetry/opentelemetry-go/issues/5240)) - Make the initial alpha release of `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. This new module contains an OTLP exporter that transmits log telemetry using HTTP. This module is unstable and breaking changes may be introduced. See our [versioning policy](VERSIONING.md) for more information about these stability guarantees. ([#​5240](https://togithub.com/open-telemetry/opentelemetry-go/issues/5240)) - Make the initial alpha release of `go.opentelemetry.io/otel/exporters/stdout/stdoutlog`. This new module contains an exporter prints log records to STDOUT. This module is unstable and breaking changes may be introduced. See our [versioning policy](VERSIONING.md) for more information about these stability guarantees. ([#​5240](https://togithub.com/open-telemetry/opentelemetry-go/issues/5240)) - The `go.opentelemetry.io/otel/semconv/v1.25.0` package. The package contains semantic conventions from the `v1.25.0` version of the OpenTelemetry Semantic Conventions. ([#​5254](https://togithub.com/open-telemetry/opentelemetry-go/issues/5254)) ##### Changed - Update `go.opentelemetry.io/proto/otlp` from v1.1.0 to v1.2.0. ([#​5177](https://togithub.com/open-telemetry/opentelemetry-go/issues/5177)) - Improve performance of baggage member character validation in `go.opentelemetry.io/otel/baggage`. ([#​5214](https://togithub.com/open-telemetry/opentelemetry-go/issues/5214)) **Full Changelog**: https://github.com/open-telemetry/opentelemetry-go/compare/v1.25.0...v1.26.0
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * [docs/rfc] RFC about environment variables (#9854) **Description:** Adds an RFC about how environment variable resolution should work **Link to tracking Issue:** Fixes #9515, relates to: - #8215 - #8565 - #9162 - #9531 - #9532 --------- Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> Co-authored-by: Evan Bradley <11745660+evan-bradley@users.noreply.github.com> * fix(deps): update all opentelemetry-go-contrib packages (#10055) [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [go.opentelemetry.io/contrib/config](https://togithub.com/open-telemetry/opentelemetry-go-contrib) | `v0.5.0` -> `v0.6.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcontrib%2fconfig/v0.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcontrib%2fconfig/v0.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcontrib%2fconfig/v0.5.0/v0.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcontrib%2fconfig/v0.5.0/v0.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://togithub.com/open-telemetry/opentelemetry-go-contrib) | `v0.50.0` -> `v0.51.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fnet%2fhttp%2fotelhttp/v0.51.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fnet%2fhttp%2fotelhttp/v0.51.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fnet%2fhttp%2fotelhttp/v0.50.0/v0.51.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcontrib%2finstrumentation%2fnet%2fhttp%2fotelhttp/v0.50.0/v0.51.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [go.opentelemetry.io/contrib/zpages](https://togithub.com/open-telemetry/opentelemetry-go-contrib) | `v0.50.0` -> `v0.51.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.opentelemetry.io%2fcontrib%2fzpages/v0.51.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/go.opentelemetry.io%2fcontrib%2fzpages/v0.51.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/go.opentelemetry.io%2fcontrib%2fzpages/v0.50.0/v0.51.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.opentelemetry.io%2fcontrib%2fzpages/v0.50.0/v0.51.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
open-telemetry/opentelemetry-go-contrib (go.opentelemetry.io/contrib/config) ### [`v0.6.0`](https://togithub.com/open-telemetry/opentelemetry-go-contrib/releases/tag/v0.6.0) Initial Release. Compatibility with [the opentelemetry-go v0.6.0 release](https://togithub.com/open-telemetry/opentelemetry-go/releases/tag/v0.6.0) added for the following: - [exporters/metric/datadog](https://togithub.com/open-telemetry/opentelemetry-go-contrib/releases/tag/exporters%2Fmetric%2Fdatadog%2Fv0.6.0) - [exporters/metric/dogstatsd](https://togithub.com/open-telemetry/opentelemetry-go-contrib/releases/tag/exporters%2Fmetric%2Fdogstatsd%2Fv0.6.0) - [instrumentation/gin-gonic/gin](https://togithub.com/open-telemetry/opentelemetry-go-contrib/releases/tag/instrumentation%2Fgin-gonic%2Fgin%2Fv0.6.0) - [instrumentation/go.mongodb.org/mongo-driver](https://togithub.com/open-telemetry/opentelemetry-go-contrib/releases/tag/instrumentation%2Fgo.mongodb.org%2Fmongo-driver%2Fv0.6.0) - [instrumentation/gorilla/mux](https://togithub.com/open-telemetry/opentelemetry-go-contrib/releases/tag/instrumentation%2Fgorilla%2Fmux%2Fv0.6.0) - [instrumentation/labstack/echo](https://togithub.com/open-telemetry/opentelemetry-go-contrib/releases/tag/instrumentation%2Flabstack%2Fecho%2Fv0.6.0) - [instrumentation/macaron](https://togithub.com/open-telemetry/opentelemetry-go-contrib/releases/tag/instrumentation%2Fmacaron%2Fv0.6.0) - [instrumentation/runtime](https://togithub.com/open-telemetry/opentelemetry-go-contrib/releases/tag/instrumentation%2Fruntime%2Fv0.6.0)
--- ### Configuration 📅 **Schedule**: Branch creation - "on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/open-telemetry/opentelemetry-collector). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com> * [chore] only run unit tests for actuated on a single version (#10062) We do the same for the contrib repo. cc @atoulme Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] Allow sometimes skipping deprecation process when adding variadic arguments (#10041) Call out that unnamed types, e.g. the function signature of an exported function, should not be relied upon by API consumers. In particular, updating a function to be variadic will break users who were depending on that function's signature. #### Link to tracking issue Helps https://github.com/open-telemetry/opentelemetry-collector/pull/9041 Co-authored-by: Evan Bradley Co-authored-by: Pablo Baeyens Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] pin version of npm package (#10063) this addresses a security concern around the version of the package installed Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] go version didn't match check (#10067) Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * add semantic convention v1.25.0 (#10075) Include attribute_group as requested. Fixes #10072 --------- Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Documentation improvements - Comments in key functions (#10029) #### Documentation I wrote comments on a bunch of important functions that helped me understand how the collector works. I also created some other documentation in https://github.com/open-telemetry/opentelemetry-collector/pull/10068 - but split it up from this PR. * Allow receivers/processors to know when the queue is full (#10070) Marked as experimental as it is the Queue. --------- Signed-off-by: Bogdan Drutu Co-authored-by: Dmitrii Anoshin Co-authored-by: Yang Song * [builder] make retries configurable for faster tests (#10035) #### Description When running tests, waiting for `downloadModules()` to fail 3 times when that's expected adds time to the test run. This updates tests to only attempt downloading once. Note: if there's a network failure that could cause `downloadModules()` to fail when it should normally succeed. Also the wording here is `retries` when in actuality it's the number of attempts. I didn't change this to keep the log wording the same, but I can change the wording if that's preferable. #### Link to tracking issue this will help for adding tests for https://github.com/open-telemetry/opentelemetry-collector/issues/9252 and https://github.com/open-telemetry/opentelemetry-collector/issues/9896 #### Testing Tests ran --------- Co-authored-by: Pablo Baeyens * [exporterhelper] Fix `enabled` config option for batch sender (#10076) `enabled` config option for batch sender was ignored. This PR fixes it. * mdatagen: Call connectors with routers to be the same as the service graph (#10079) * [chore] remove multierr use in mdatagen (#10080) Use errors.Join instead. Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * Revert pipeline type validation (#10078) #### Description This PR reverts the change made in https://github.com/open-telemetry/opentelemetry-collector/pull/9257 due to problems reported in https://github.com/open-telemetry/opentelemetry-collector/issues/10031. #### Link to tracking issue Fixes #10031. * [chore] [exporterhelper] Integrate capacity limiting into the communication channel (#9232) Integrate capacity limiting into internal channels used by both memory and persistent queues. Otherwise, with the independent capacity limiter, it's hard to ensure that queue size is always accurate going forward. Benchmarks before: ``` goos: darwin goarch: arm64 Benchmark_QueueUsage_1000_requests-10 3252 325010 ns/op 246059 B/op 10 allocs/op Benchmark_QueueUsage_100000_requests-10 39 29811116 ns/op 24002870 B/op 10 allocs/op Benchmark_QueueUsage_10000_items-10 3404 349753 ns/op 246052 B/op 10 allocs/op Benchmark_QueueUsage_1M_items-10 40 29415583 ns/op 24002858 B/op 10 allocs/op BenchmarkPersistentQueue_TraceSpans BenchmarkPersistentQueue_TraceSpans/#traces:_1_#spansPerTrace:_1-10 338180 3836 ns/op 2851 B/op 78 allocs/op BenchmarkPersistentQueue_TraceSpans/#traces:_1_#spansPerTrace:_10-10 81369 15822 ns/op 14598 B/op 289 allocs/op BenchmarkPersistentQueue_TraceSpans/#traces:_10_#spansPerTrace:_10-10 13066 90155 ns/op 130087 B/op 2417 allocs/op ``` Benchmarks after: ``` Benchmark_QueueUsage_1000_requests-10 4210 278175 ns/op 246055 B/op 10 allocs/op Benchmark_QueueUsage_100000_requests-10 42 25835945 ns/op 24002968 B/op 10 allocs/op Benchmark_QueueUsage_10000_items-10 4376 279571 ns/op 246056 B/op 10 allocs/op Benchmark_QueueUsage_1M_items-10 42 26483907 ns/op 24002995 B/op 10 allocs/op BenchmarkPersistentQueue_TraceSpans BenchmarkPersistentQueue_TraceSpans/#traces:_1_#spansPerTrace:_1-10 328268 4251 ns/op 2854 B/op 78 allocs/op BenchmarkPersistentQueue_TraceSpans/#traces:_1_#spansPerTrace:_10-10 101683 12238 ns/op 14582 B/op 289 allocs/op BenchmarkPersistentQueue_TraceSpans/#traces:_10_#spansPerTrace:_10-10 13382 86464 ns/op 130154 B/op 2417 allocs/op ``` * [chore] fix import orders in mdatagen templates (#10081) Signed-off-by: Bogdan Drutu * [otelcol] rfc for how to log during startup (#10066) #### Description This is an RFC to help us decide how we want `otelcol` to provide a logger before the primary logger is created. As we discuss I will update the doc. Before this is merged we should have decided on a solution and the Accepted Solution section must be updated. Related to https://github.com/open-telemetry/opentelemetry-collector/pull/10056 #### Link to tracking issue This unblocks: - https://github.com/open-telemetry/opentelemetry-collector/issues/9162 - https://github.com/open-telemetry/opentelemetry-collector/issues/5615 --------- Co-authored-by: Pablo Baeyens Co-authored-by: Evan Bradley <11745660+evan-bradley@users.noreply.github.com> * [chore] remove duplicate code from the connector (#10082) Signed-off-by: Bogdan Drutu Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] try to fix coverage step (#10085) It's unclear why the retry action is failing to pass in the secret, trying to standard codecov action with a token as per codecov documentation. --------- Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> * [chore] Prepare release v1.7.0/v0.100.0 (#10087) The following commands were run to prepare this release: - make chlog-update VERSION=v1.7.0/v0.100.0 - make prepare-release PREVIOUS_VERSION=1.6.0 RELEASE_CANDIDATE=1.7.0 MODSET=stable - make prepare-release PREVIOUS_VERSION=0.99.0 RELEASE_CANDIDATE=0.100.0 MODSET=beta --------- Co-authored-by: Bogdan Drutu * Fix ratelimit tests * Apply changes in diff from upstream * Fix unused parameters (linter) * Fix import spacing (linting) * gotidy for changed mod --------- Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> Signed-off-by: Ziqi Zhao Signed-off-by: Bogdan Drutu Signed-off-by: Juraci Paixão Kröhling Signed-off-by: dockercui Co-authored-by: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com> Co-authored-by: Dmitrii Anoshin Co-authored-by: Pablo Baeyens Co-authored-by: OpenTelemetry Bot <107717825+opentelemetrybot@users.noreply.github.com> Co-authored-by: Alex Boten <223565+codeboten@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Paulo Janotti Co-authored-by: Sanket Teli <104385297+Sanket-0510@users.noreply.github.com> Co-authored-by: Pablo Baeyens Co-authored-by: Antoine Toulme Co-authored-by: molejnik88 Co-authored-by: Ziqi Zhao Co-authored-by: Carson Ip Co-authored-by: Curtis Robert Co-authored-by: David Ashpole Co-authored-by: Evan Bradley <11745660+evan-bradley@users.noreply.github.com> Co-authored-by: Andrey Babushkin Co-authored-by: Antoine Toulme Co-authored-by: KIMBOH LOVETTE <37558983+Kimbohlovette@users.noreply.github.com> Co-authored-by: Joshua Jones Co-authored-by: Bogdan Drutu Co-authored-by: Daniel Jaglowski Co-authored-by: Tomás Mota Co-authored-by: Andrzej Stencel Co-authored-by: Ben Mask Co-authored-by: Lavish Pal Co-authored-by: Akhigbe Eromosele David Co-authored-by: Ankit Patel <8731662+ankitpatel96@users.noreply.github.com> Co-authored-by: Shaunak Kashyap Co-authored-by: Povilas Versockas Co-authored-by: Raj Nishtala <113392743+rnishtala-sumo@users.noreply.github.com> Co-authored-by: Kristina Pathak Co-authored-by: Evan Bradley Co-authored-by: Jacob Aronoff Co-authored-by: Juraci Paixão Kröhling Co-authored-by: dockercui <167661769+dockercui@users.noreply.github.com> Co-authored-by: Yang Song Co-authored-by: Kristina Pathak --- .chloggen/use-sync/atomic.yaml | 16 - .github/ISSUE_TEMPLATE/feature_request.md | 8 +- .github/ISSUE_TEMPLATE/release.md | 3 +- .github/pull_request_template.md | 21 +- .github/workflows/api-compatibility.yml | 4 +- .github/workflows/build-and-test-windows.yaml | 43 +- .github/workflows/build-and-test.yml | 78 +- .../workflows/builder-integration-test.yaml | 2 +- .github/workflows/builder-release.yaml | 2 +- .github/workflows/changelog.yml | 4 +- .github/workflows/check-links.yaml | 6 +- .github/workflows/check_links_config.json | 3 + .github/workflows/codeql-analysis.yml | 8 +- .github/workflows/contrib-tests.yml | 2 +- .../generate-semantic-conventions-pr.yaml | 6 +- .github/workflows/perf.yml | 2 +- .github/workflows/prepare-release.yml | 10 +- .github/workflows/scorecard.yml | 6 +- .github/workflows/shellcheck.yml | 2 +- .github/workflows/tidy-dependencies.yml | 6 +- CHANGELOG-API.md | 80 + CHANGELOG.md | 130 + CONTRIBUTING.md | 22 +- Makefile | 11 +- Makefile.Common | 3 +- README.md | 10 +- client/client.go | 17 +- cmd/builder/Makefile | 2 +- cmd/builder/README.md | 37 +- cmd/builder/go.mod | 5 +- cmd/builder/go.sum | 10 +- cmd/builder/internal/builder/config.go | 104 +- cmd/builder/internal/builder/config_test.go | 83 +- cmd/builder/internal/builder/main.go | 147 +- cmd/builder/internal/builder/main_test.go | 312 +- cmd/builder/internal/builder/templates.go | 4 - .../builder/templates/components_test.go.tmpl | 39 - .../internal/builder/templates/go.mod.tmpl | 6 + .../internal/builder/templates/main.go.tmpl | 28 +- cmd/builder/internal/command.go | 8 +- cmd/builder/internal/command_test.go | 43 +- cmd/builder/internal/config/default.yaml | 35 +- cmd/builder/test/core.builder.yaml | 9 +- cmd/mdatagen/doc.go | 7 - cmd/mdatagen/embeded_templates_test.go | 3 + cmd/mdatagen/go.mod | 56 +- cmd/mdatagen/go.sum | 68 +- .../internal/metadata/generated_status.go | 29 - .../internal/metadata/testdata/config.yaml | 55 - .../internal/samplereceiver/README.md | 22 + cmd/mdatagen/internal/samplereceiver/doc.go | 10 + .../samplereceiver}/documentation.md | 20 +- .../internal/samplereceiver/factory.go | 42 + .../generated_component_test.go | 85 + .../samplereceiver/generated_package_test.go | 5 +- .../internal}/metadata/generated_config.go | 22 +- .../metadata/generated_config_test.go | 2 + .../internal}/metadata/generated_metrics.go | 141 +- .../metadata/generated_metrics_test.go | 90 +- .../internal}/metadata/generated_resource.go | 0 .../metadata/generated_resource_test.go | 0 .../internal/metadata/generated_status.go | 17 + .../internal/metadata/generated_telemetry.go | 18 + .../metadata/generated_telemetry_test.go | 63 + .../internal/metadata/testdata/config.yaml | 127 + .../samplereceiver/metadata.yaml} | 21 +- .../internal/samplereceiver/metrics_test.go | 20 + cmd/mdatagen/lint_test.go | 2 +- cmd/mdatagen/loader.go | 68 +- cmd/mdatagen/loader_test.go | 41 +- cmd/mdatagen/main.go | 30 +- cmd/mdatagen/main_test.go | 224 +- cmd/mdatagen/metadata-schema.yaml | 14 + cmd/mdatagen/metricdata.go | 4 +- .../mdatagen}/package_test.go | 2 +- cmd/mdatagen/statusdata.go | 60 +- cmd/mdatagen/templates/component_test.go.tmpl | 205 +- cmd/mdatagen/templates/config.go.tmpl | 19 +- cmd/mdatagen/templates/metrics.go.tmpl | 35 +- cmd/mdatagen/templates/metrics_test.go.tmpl | 57 +- cmd/mdatagen/templates/package_test.go.tmpl | 25 + cmd/mdatagen/templates/readme.md.tmpl | 9 +- cmd/mdatagen/templates/status.go.tmpl | 15 +- cmd/mdatagen/templates/telemetry.go.tmpl | 17 + cmd/mdatagen/templates/telemetry_test.go.tmpl | 63 + .../templates/testdata/config.yaml.tmpl | 22 + cmd/mdatagen/testdata/metrics_and_type.yaml | 4 + .../testdata/resource_attributes_only.yaml | 4 + cmd/mdatagen/testdata/status_only.yaml | 4 + .../testdata/with_goleak_ignores.yaml | 14 + cmd/mdatagen/testdata/with_goleak_setup.yaml | 10 + cmd/mdatagen/testdata/with_goleak_skip.yaml | 10 + .../testdata/with_goleak_teardown.yaml | 10 + .../testdata/with_tests_connector.yaml | 3 - .../testdata/with_tests_exporter.yaml | 3 - .../testdata/with_tests_extension.yaml | 3 - .../testdata/with_tests_processor.yaml | 3 - .../testdata/with_tests_receiver.yaml | 3 - cmd/mdatagen/validate.go | 59 +- cmd/mdatagen/validate_test.go | 4 +- cmd/otelcorecol/builder-config.yaml | 38 +- cmd/otelcorecol/components.go | 4 + cmd/otelcorecol/components_test.go | 41 - cmd/otelcorecol/go.mod | 169 +- cmd/otelcorecol/go.sum | 173 +- cmd/otelcorecol/main.go | 30 +- cmd/otelcorecol/package_test.go | 5 +- component/component.go | 6 - component/componenttest/nop_host_test.go | 1 - .../componenttest/otelprometheuschecker.go | 2 +- component/config.go | 31 +- component/config_test.go | 32 +- component/doc.go | 2 +- component/go.mod | 37 +- component/go.sum | 66 +- component/host.go | 20 - component/telemetry.go | 2 +- config/configauth/configauth.go | 5 + config/configauth/configauth_test.go | 6 + config/configauth/go.mod | 33 +- config/configauth/go.sum | 66 +- config/configcompression/compressiontype.go | 20 +- config/configcompression/go.mod | 2 +- config/configcompression/go.sum | 4 +- config/configgrpc/configgrpc.go | 74 +- .../configgrpc/configgrpc_benchmark_test.go | 2 +- config/configgrpc/configgrpc_test.go | 135 +- config/configgrpc/go.mod | 65 +- config/configgrpc/go.sum | 82 +- config/configgrpc/package_test.go | 5 +- config/confighttp/README.md | 2 +- config/confighttp/compression_test.go | 3 +- config/confighttp/compressor.go | 7 +- config/confighttp/compressor_test.go | 96 + config/confighttp/confighttp.go | 59 +- config/confighttp/confighttp_test.go | 89 +- config/confighttp/go.mod | 63 +- config/confighttp/go.sum | 74 +- config/confighttp/ratelimit_test.go | 25 +- config/confignet/confignet.go | 97 +- config/confignet/confignet_test.go | 50 +- config/confignet/go.mod | 2 +- config/confignet/go.sum | 4 +- config/configopaque/go.mod | 7 +- config/configopaque/go.sum | 10 +- config/configretry/go.mod | 4 +- config/configretry/go.sum | 8 +- config/configtelemetry/go.mod | 2 +- config/configtelemetry/go.sum | 4 +- config/configtls/configtls.go | 85 +- config/configtls/configtls_test.go | 176 +- config/configtls/go.mod | 4 +- config/configtls/go.sum | 10 +- config/internal/go.mod | 8 +- config/internal/go.sum | 4 +- config/internal/warning.go | 2 +- confmap/confmap.go | 108 +- confmap/confmap_test.go | 335 +- confmap/confmaptest/provider_settings.go | 14 + confmap/converter.go | 13 +- confmap/converter/expandconverter/expand.go | 48 +- .../converter/expandconverter/expand_test.go | 105 +- confmap/converter/expandconverter/go.mod | 7 +- confmap/converter/expandconverter/go.sum | 10 +- confmap/doc_test.go | 97 + confmap/expand_test.go | 22 +- confmap/go.mod | 6 +- confmap/go.sum | 11 +- confmap/provider.go | 23 +- confmap/provider/envprovider/go.mod | 7 +- confmap/provider/envprovider/go.sum | 10 +- confmap/provider/envprovider/provider.go | 30 +- confmap/provider/envprovider/provider_test.go | 83 +- confmap/provider/fileprovider/go.mod | 7 +- confmap/provider/fileprovider/go.sum | 10 +- confmap/provider/fileprovider/provider.go | 11 +- .../provider/fileprovider/provider_test.go | 18 +- confmap/provider/httpprovider/go.mod | 7 +- confmap/provider/httpprovider/go.sum | 10 +- confmap/provider/httpprovider/provider.go | 9 +- .../provider/httpprovider/provider_test.go | 4 +- confmap/provider/httpsprovider/go.mod | 7 +- confmap/provider/httpsprovider/go.sum | 10 +- confmap/provider/httpsprovider/provider.go | 11 +- .../provider/httpsprovider/provider_test.go | 4 +- .../configurablehttpprovider/provider_test.go | 22 +- confmap/provider/yamlprovider/go.mod | 7 +- confmap/provider/yamlprovider/go.sum | 10 +- confmap/provider/yamlprovider/provider.go | 9 +- .../provider/yamlprovider/provider_test.go | 23 +- confmap/resolver.go | 70 +- confmap/resolver_test.go | 150 +- connector/connectortest/connector.go | 4 +- .../generated_component_test.go | 88 + ...kage_test.go => generated_package_test.go} | 3 +- connector/forwardconnector/go.mod | 48 +- connector/forwardconnector/go.sum | 68 +- .../internal/metadata/generated_status.go | 14 +- .../internal/metadata/generated_telemetry.go | 18 + .../metadata/generated_telemetry_test.go | 63 + connector/go.mod | 47 +- connector/go.sum | 68 +- connector/logs_router.go | 16 +- connector/logs_router_test.go | 2 +- connector/metrics_router.go | 45 +- connector/metrics_router_test.go | 2 +- connector/router.go | 55 + connector/traces_router.go | 49 +- connector/traces_router_test.go | 2 +- consumer/consumererror/signalerrors_test.go | 2 +- consumer/consumertest/sink_test.go | 2 +- consumer/go.mod | 29 +- consumer/go.sum | 30 +- docs/design.md | 205 - docs/ga-roadmap.md | 216 +- docs/images/design-collector-agent.png | Bin 98922 -> 0 bytes docs/images/design-collector-service.png | Bin 109843 -> 0 bytes docs/images/design-exporters.png | Bin 36684 -> 0 bytes docs/images/design-pipelines.png | Bin 19661 -> 0 bytes docs/images/design-processors.png | Bin 46883 -> 0 bytes docs/images/design-receivers.png | Bin 47509 -> 0 bytes ...pentelemetry-service-deployment-models.png | Bin 78430 -> 0 bytes docs/images/zpages-example.png | Bin 373980 -> 0 bytes docs/platform-support.md | 5 +- docs/release.md | 24 +- docs/rfcs/README.md | 10 + docs/rfcs/env-vars.md | 222 + docs/rfcs/logging-before-config-resolution.md | 66 + docs/{ => rfcs}/processing.md | 0 docs/security-best-practices.md | 5 +- examples/k8s/otel-config.yaml | 2 +- exporter/debugexporter/exporter.go | 87 + exporter/debugexporter/factory.go | 58 +- .../debugexporter/generated_component_test.go | 151 + ...kage_test.go => generated_package_test.go} | 3 +- exporter/debugexporter/go.mod | 58 +- exporter/debugexporter/go.sum | 72 +- .../internal/metadata/generated_status.go | 14 +- .../internal/metadata/generated_telemetry.go | 18 + .../metadata/generated_telemetry_test.go | 63 + exporter/exporterbatcher/batch_func.go | 24 + exporter/exporterbatcher/config.go | 70 + exporter/exporterbatcher/config_test.go | 30 + exporter/exporterhelper/README.md | 32 +- exporter/exporterhelper/batch_sender.go | 223 + exporter/exporterhelper/batch_sender_test.go | 448 ++ exporter/exporterhelper/common.go | 131 +- exporter/exporterhelper/common_test.go | 19 +- exporter/exporterhelper/logs.go | 9 +- exporter/exporterhelper/logs_batch.go | 137 + exporter/exporterhelper/logs_batch_test.go | 159 + exporter/exporterhelper/logs_test.go | 2 +- exporter/exporterhelper/metrics.go | 9 +- exporter/exporterhelper/metrics_batch.go | 236 + exporter/exporterhelper/metrics_batch_test.go | 166 + exporter/exporterhelper/metrics_test.go | 2 +- exporter/exporterhelper/obsexporter.go | 20 +- exporter/exporterhelper/queue_sender.go | 6 +- exporter/exporterhelper/request.go | 6 +- exporter/exporterhelper/request_test.go | 108 +- exporter/exporterhelper/retry_sender_test.go | 2 +- exporter/exporterhelper/traces.go | 9 +- exporter/exporterhelper/traces_batch.go | 139 + exporter/exporterhelper/traces_batch_test.go | 159 + exporter/exporterhelper/traces_test.go | 2 +- exporter/exporterqueue/config.go | 6 +- exporter/exporterqueue/queue.go | 23 +- exporter/exportertest/nop_exporter.go | 4 +- exporter/go.mod | 55 +- exporter/go.sum | 72 +- exporter/internal/common/logging_exporter.go | 4 + .../internal/common/logging_exporter_test.go | 2 +- exporter/internal/otlptext/logs_test.go | 2 +- exporter/internal/otlptext/metrics_test.go | 2 +- exporter/internal/otlptext/traces_test.go | 2 +- .../internal/queue/bounded_memory_queue.go | 23 +- .../queue/bounded_memory_queue_test.go | 10 +- exporter/internal/queue/persistent_queue.go | 204 +- .../internal/queue/persistent_queue_test.go | 124 +- exporter/internal/queue/queue.go | 23 + exporter/internal/queue/queue_capacity.go | 74 - .../internal/queue/queue_capacity_test.go | 58 - exporter/internal/queue/sized_channel.go | 104 + exporter/internal/queue/sized_channel_test.go | 44 + .../generated_component_test.go | 151 + ...kage_test.go => generated_package_test.go} | 3 +- exporter/loggingexporter/go.mod | 56 +- exporter/loggingexporter/go.sum | 72 +- .../internal/metadata/generated_status.go | 14 +- .../internal/metadata/generated_telemetry.go | 18 + .../metadata/generated_telemetry_test.go | 63 + exporter/nopexporter/Makefile | 1 + exporter/nopexporter/README.md | 27 + exporter/nopexporter/doc.go | 7 + .../nopexporter/generated_component_test.go | 151 + .../nopexporter/generated_package_test.go | 5 +- exporter/nopexporter/go.mod | 80 + exporter/nopexporter/go.sum | 124 + .../internal/metadata/generated_status.go | 17 + .../internal/metadata/generated_telemetry.go | 18 + .../metadata/generated_telemetry_test.go | 63 + exporter/nopexporter/metadata.yaml | 7 + exporter/nopexporter/nop_exporter.go | 46 + exporter/nopexporter/nop_exporter_test.go | 45 + exporter/otlpexporter/config.go | 30 +- exporter/otlpexporter/config_test.go | 25 +- exporter/otlpexporter/factory_test.go | 4 +- .../otlpexporter/generated_component_test.go | 151 + .../otlpexporter/generated_package_test.go | 13 + exporter/otlpexporter/go.mod | 96 +- exporter/otlpexporter/go.sum | 134 +- .../internal/metadata/generated_status.go | 14 +- .../internal/metadata/generated_telemetry.go | 18 + .../metadata/generated_telemetry_test.go | 63 + exporter/otlpexporter/metadata.yaml | 4 + exporter/otlpexporter/otlp_test.go | 2 +- .../testdata/invalid_configs.yaml | 48 + exporter/otlphttpexporter/config_test.go | 2 +- exporter/otlphttpexporter/factory_test.go | 4 +- .../generated_component_test.go | 151 + ...kage_test.go => generated_package_test.go} | 3 +- exporter/otlphttpexporter/go.mod | 95 +- exporter/otlphttpexporter/go.sum | 126 +- .../internal/metadata/generated_status.go | 14 +- .../internal/metadata/generated_telemetry.go | 18 + .../metadata/generated_telemetry_test.go | 63 + exporter/otlphttpexporter/metadata.yaml | 5 + exporter/otlphttpexporter/otlp.go | 20 +- exporter/otlphttpexporter/otlp_test.go | 340 +- extension/auth/go.mod | 41 +- extension/auth/go.sum | 66 +- .../generated_component_test.go | 51 + ...kage_test.go => generated_package_test.go} | 3 +- extension/ballastextension/go.mod | 50 +- extension/ballastextension/go.sum | 78 +- .../internal/metadata/generated_status.go | 14 +- .../internal/metadata/generated_telemetry.go | 18 + .../metadata/generated_telemetry_test.go | 63 + extension/extensiontest/nop_extension.go | 4 +- extension/go.mod | 40 +- extension/go.sum | 68 +- .../generated_component_test.go | 45 + .../generated_package_test.go | 13 + extension/memorylimiterextension/go.mod | 51 +- extension/memorylimiterextension/go.sum | 78 +- .../internal/metadata/generated_status.go | 14 +- .../internal/metadata/generated_telemetry.go | 18 + .../metadata/generated_telemetry_test.go | 63 + .../memorylimiterextension/metadata.yaml | 8 + .../generated_component_test.go | 51 + ...kage_test.go => generated_package_test.go} | 3 +- extension/zpagesextension/go.mod | 71 +- extension/zpagesextension/go.sum | 122 +- .../internal/metadata/generated_status.go | 14 +- .../internal/metadata/generated_telemetry.go | 18 + .../metadata/generated_telemetry_test.go | 63 + featuregate/go.mod | 2 +- featuregate/go.sum | 4 +- filter/Makefile | 1 + filter/config.go | 72 + filter/config_test.go | 113 + filter/doc.go | 5 + filter/filter.go | 11 + filter/go.mod | 24 + filter/go.sum | 28 + filter/testdata/config.yaml | 8 + filter/testdata/config_invalid.yaml | 12 + go.mod | 71 +- go.sum | 126 +- internal/e2e/go.mod | 108 +- internal/e2e/go.sum | 142 +- internal/e2e/otlphttp_test.go | 2 +- internal/fanoutconsumer/logs_test.go | 2 +- internal/fanoutconsumer/metrics_test.go | 2 +- internal/fanoutconsumer/traces_test.go | 2 +- internal/httphelper/helper.go | 36 + internal/httphelper/helper_test.go | 83 + internal/localhostgate/featuregate.go | 8 +- internal/localhostgate/featuregate_test.go | 2 +- internal/memorylimiter/config_test.go | 10 + .../negative_unsigned_limits_config.yaml | 13 + .../obsmetrics/obs_exporter.go | 9 +- .../obsmetrics/obs_processor.go | 2 +- .../obsmetrics/obs_receiver.go | 9 +- .../obsreportconfig/obsmetrics/obs_scraper.go | 5 +- .../obsreportconfig/obsmetrics/obsmetrics.go | 5 +- internal/obsreportconfig/obsreportconfig.go | 8 - internal/tools/go.mod | 117 +- internal/tools/go.sum | 241 +- obsreport/doc.go | 105 - obsreport/obsreporttest/deprecated.go | 29 - obsreport/obsreporttest/package_test.go | 14 - otelcol/collector.go | 13 +- otelcol/collector_test.go | 39 +- otelcol/collector_windows.go | 30 +- otelcol/collector_windows_service_test.go | 185 + otelcol/command.go | 3 +- otelcol/command_components.go | 85 +- otelcol/command_components_test.go | 57 +- otelcol/command_test.go | 20 +- otelcol/command_validate_test.go | 6 +- otelcol/config.go | 10 +- otelcol/config_test.go | 13 + otelcol/configprovider.go | 26 +- otelcol/configprovider_test.go | 15 +- otelcol/factories_test.go | 3 +- otelcol/go.mod | 109 +- otelcol/go.sum | 148 +- otelcol/internal/configunmarshaler/configs.go | 7 +- .../configunmarshaler/configs_test.go | 2 +- otelcol/otelcoltest/config.go | 22 +- otelcol/testdata/components-output.yaml | 43 + otelcol/testdata/otel-log-to-file.yaml | 30 + .../otelcol-invalid-receiver-type.yaml | 18 + otelcol/unmarshaler.go | 2 +- pdata/go.mod | 13 +- pdata/go.sum | 30 +- .../cmd/pdatagen/internal/pmetric_package.go | 4 + .../data/protogen/metrics/v1/metrics.pb.go | 259 +- .../data/protogen/trace/v1/trace.pb.go | 195 +- pdata/pmetric/generated_metric.go | 7 + pdata/pmetric/generated_metric_test.go | 9 + pdata/pmetric/json.go | 5 + pdata/pmetric/json_test.go | 6 +- pdata/testdata/Makefile | 1 + {internal => pdata}/testdata/common.go | 0 pdata/testdata/go.mod | 21 + pdata/testdata/go.sum | 68 + {internal => pdata}/testdata/log.go | 0 {internal => pdata}/testdata/metric.go | 0 {internal => pdata}/testdata/resource.go | 0 {internal => pdata}/testdata/trace.go | 0 processor/batchprocessor/batch_processor.go | 13 +- .../batchprocessor/batch_processor_test.go | 2 +- .../generated_component_test.go | 150 + ...kage_test.go => generated_package_test.go} | 3 +- processor/batchprocessor/go.mod | 49 +- processor/batchprocessor/go.sum | 68 +- .../internal/metadata/generated_status.go | 14 +- .../internal/metadata/generated_telemetry.go | 18 + .../metadata/generated_telemetry_test.go | 63 + processor/batchprocessor/metadata.yaml | 2 + processor/batchprocessor/metrics.go | 24 +- processor/batchprocessor/splitlogs_test.go | 2 +- processor/batchprocessor/splitmetrics_test.go | 2 +- processor/batchprocessor/splittraces_test.go | 2 +- processor/go.mod | 47 +- processor/go.sum | 68 +- .../generated_component_test.go | 144 + ...kage_test.go => generated_package_test.go} | 3 +- processor/memorylimiterprocessor/go.mod | 53 +- processor/memorylimiterprocessor/go.sum | 78 +- .../internal/metadata/generated_status.go | 14 +- .../internal/metadata/generated_telemetry.go | 18 + .../metadata/generated_telemetry_test.go | 63 + .../internal/mock_exporter.go | 39 +- .../memorylimiter_test.go | 6 +- .../memorylimiterprocessor/metadata.yaml | 8 + processor/processorhelper/obsreport.go | 28 +- processor/processorhelper/obsreport_test.go | 4 +- processor/processortest/nop_processor.go | 4 +- processor/processortest/shutdown_verifier.go | 2 +- receiver/go.mod | 46 +- receiver/go.sum | 68 +- receiver/nopreceiver/Makefile | 1 + receiver/nopreceiver/README.md | 26 + receiver/nopreceiver/doc.go | 7 + .../nopreceiver/generated_component_test.go | 84 + .../nopreceiver/generated_package_test.go | 13 + receiver/nopreceiver/go.mod | 73 + receiver/nopreceiver/go.sum | 122 + .../internal/metadata/generated_status.go | 17 + .../internal/metadata/generated_telemetry.go | 18 + .../metadata/generated_telemetry_test.go | 63 + receiver/nopreceiver/metadata.yaml | 7 + receiver/nopreceiver/nop_receiver.go | 42 + receiver/nopreceiver/nop_receiver_test.go | 40 + receiver/otlpreceiver/README.md | 2 +- receiver/otlpreceiver/config_test.go | 8 +- receiver/otlpreceiver/factory.go | 2 +- receiver/otlpreceiver/factory_test.go | 12 +- .../otlpreceiver/generated_component_test.go | 84 + .../otlpreceiver/generated_package_test.go | 13 + receiver/otlpreceiver/go.mod | 98 +- receiver/otlpreceiver/go.sum | 142 +- .../otlpreceiver/internal/errors/errors.go | 20 + .../internal/errors/errors_test.go | 31 + .../otlpreceiver/internal/logs/otlp_test.go | 4 +- .../internal/metadata/generated_status.go | 14 +- .../internal/metadata/generated_telemetry.go | 18 + .../metadata/generated_telemetry_test.go | 63 + .../internal/metrics/otlp_test.go | 4 +- .../otlpreceiver/internal/trace/otlp_test.go | 4 +- receiver/otlpreceiver/otlp.go | 10 +- receiver/otlpreceiver/otlp_test.go | 140 +- receiver/otlpreceiver/otlphttp.go | 18 +- receiver/otlpreceiver/package_test.go | 17 - receiver/receiverhelper/obsreport.go | 14 +- receiver/receivertest/contract_checker.go | 2 +- receiver/receivertest/nop_receiver.go | 37 +- receiver/scraperhelper/config.go | 15 - receiver/scraperhelper/obsreport.go | 4 +- receiver/scraperhelper/scrapercontroller.go | 4 +- renovate.json | 15 +- semconv/go.mod | 2 +- semconv/go.sum | 4 +- semconv/v1.25.0/doc.go | 9 + semconv/v1.25.0/generated_attribute_group.go | 4796 +++++++++++++++++ semconv/v1.25.0/generated_event.go | 105 + semconv/v1.25.0/generated_resource.go | 242 + semconv/v1.25.0/generated_trace.go | 245 + semconv/v1.25.0/schema.go | 9 + service/go.mod | 100 +- service/go.sum | 148 +- service/host.go | 6 + .../capabilityconsumer/capabilities_test.go | 2 +- service/internal/graph/graph.go | 22 +- service/internal/graph/graph_test.go | 2 +- service/internal/proctelemetry/config.go | 147 - service/internal/proctelemetry/config_test.go | 357 -- service/internal/resource/config_test.go | 67 + service/internal/status/status.go | 19 - .../testcomponents/example_connector.go | 2 +- .../testcomponents/example_router_test.go | 2 +- service/service.go | 33 +- service/telemetry.go | 29 +- service/telemetry/otel_trace_sampler.go | 28 - service/telemetry/telemetry.go | 71 +- service/telemetry/telemetry_test.go | 26 + service/telemetry_test.go | 62 +- versions.yaml | 10 +- 531 files changed, 20884 insertions(+), 6193 deletions(-) delete mode 100755 .chloggen/use-sync/atomic.yaml delete mode 100644 cmd/builder/internal/builder/templates/components_test.go.tmpl delete mode 100644 cmd/mdatagen/doc.go delete mode 100644 cmd/mdatagen/internal/metadata/generated_status.go delete mode 100644 cmd/mdatagen/internal/metadata/testdata/config.yaml create mode 100644 cmd/mdatagen/internal/samplereceiver/README.md create mode 100644 cmd/mdatagen/internal/samplereceiver/doc.go rename cmd/mdatagen/{ => internal/samplereceiver}/documentation.md (81%) create mode 100644 cmd/mdatagen/internal/samplereceiver/factory.go create mode 100644 cmd/mdatagen/internal/samplereceiver/generated_component_test.go rename exporter/exportertest/package_test.go => cmd/mdatagen/internal/samplereceiver/generated_package_test.go (51%) rename cmd/mdatagen/internal/{ => samplereceiver/internal}/metadata/generated_config.go (78%) rename cmd/mdatagen/internal/{ => samplereceiver/internal}/metadata/generated_config_test.go (97%) rename cmd/mdatagen/internal/{ => samplereceiver/internal}/metadata/generated_metrics.go (69%) rename cmd/mdatagen/internal/{ => samplereceiver/internal}/metadata/generated_metrics_test.go (74%) rename cmd/mdatagen/internal/{ => samplereceiver/internal}/metadata/generated_resource.go (100%) rename cmd/mdatagen/internal/{ => samplereceiver/internal}/metadata/generated_resource_test.go (100%) create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_status.go create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry.go create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry_test.go create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/metadata/testdata/config.yaml rename cmd/mdatagen/{metadata-sample.yaml => internal/samplereceiver/metadata.yaml} (85%) create mode 100644 cmd/mdatagen/internal/samplereceiver/metrics_test.go rename {exporter/otlpexporter => cmd/mdatagen}/package_test.go (89%) create mode 100644 cmd/mdatagen/templates/package_test.go.tmpl create mode 100644 cmd/mdatagen/templates/telemetry.go.tmpl create mode 100644 cmd/mdatagen/templates/telemetry_test.go.tmpl create mode 100644 cmd/mdatagen/testdata/with_goleak_ignores.yaml create mode 100644 cmd/mdatagen/testdata/with_goleak_setup.yaml create mode 100644 cmd/mdatagen/testdata/with_goleak_skip.yaml create mode 100644 cmd/mdatagen/testdata/with_goleak_teardown.yaml delete mode 100644 cmd/otelcorecol/components_test.go create mode 100644 config/confighttp/compressor_test.go create mode 100644 confmap/confmaptest/provider_settings.go create mode 100644 confmap/doc_test.go create mode 100644 connector/forwardconnector/generated_component_test.go rename connector/forwardconnector/{package_test.go => generated_package_test.go} (62%) create mode 100644 connector/forwardconnector/internal/metadata/generated_telemetry.go create mode 100644 connector/forwardconnector/internal/metadata/generated_telemetry_test.go create mode 100644 connector/router.go delete mode 100644 docs/design.md delete mode 100644 docs/images/design-collector-agent.png delete mode 100644 docs/images/design-collector-service.png delete mode 100644 docs/images/design-exporters.png delete mode 100644 docs/images/design-pipelines.png delete mode 100644 docs/images/design-processors.png delete mode 100644 docs/images/design-receivers.png delete mode 100644 docs/images/opentelemetry-service-deployment-models.png delete mode 100644 docs/images/zpages-example.png create mode 100644 docs/rfcs/README.md create mode 100644 docs/rfcs/env-vars.md create mode 100644 docs/rfcs/logging-before-config-resolution.md rename docs/{ => rfcs}/processing.md (100%) create mode 100644 exporter/debugexporter/exporter.go create mode 100644 exporter/debugexporter/generated_component_test.go rename exporter/debugexporter/{package_test.go => generated_package_test.go} (62%) create mode 100644 exporter/debugexporter/internal/metadata/generated_telemetry.go create mode 100644 exporter/debugexporter/internal/metadata/generated_telemetry_test.go create mode 100644 exporter/exporterbatcher/batch_func.go create mode 100644 exporter/exporterbatcher/config.go create mode 100644 exporter/exporterbatcher/config_test.go create mode 100644 exporter/exporterhelper/batch_sender.go create mode 100644 exporter/exporterhelper/batch_sender_test.go create mode 100644 exporter/exporterhelper/logs_batch.go create mode 100644 exporter/exporterhelper/logs_batch_test.go create mode 100644 exporter/exporterhelper/metrics_batch.go create mode 100644 exporter/exporterhelper/metrics_batch_test.go create mode 100644 exporter/exporterhelper/traces_batch.go create mode 100644 exporter/exporterhelper/traces_batch_test.go delete mode 100644 exporter/internal/queue/queue_capacity.go delete mode 100644 exporter/internal/queue/queue_capacity_test.go create mode 100644 exporter/internal/queue/sized_channel.go create mode 100644 exporter/internal/queue/sized_channel_test.go create mode 100644 exporter/loggingexporter/generated_component_test.go rename exporter/loggingexporter/{package_test.go => generated_package_test.go} (62%) create mode 100644 exporter/loggingexporter/internal/metadata/generated_telemetry.go create mode 100644 exporter/loggingexporter/internal/metadata/generated_telemetry_test.go create mode 100644 exporter/nopexporter/Makefile create mode 100644 exporter/nopexporter/README.md create mode 100644 exporter/nopexporter/doc.go create mode 100644 exporter/nopexporter/generated_component_test.go rename extension/extensiontest/package_test.go => exporter/nopexporter/generated_package_test.go (51%) create mode 100644 exporter/nopexporter/go.mod create mode 100644 exporter/nopexporter/go.sum create mode 100644 exporter/nopexporter/internal/metadata/generated_status.go create mode 100644 exporter/nopexporter/internal/metadata/generated_telemetry.go create mode 100644 exporter/nopexporter/internal/metadata/generated_telemetry_test.go create mode 100644 exporter/nopexporter/metadata.yaml create mode 100644 exporter/nopexporter/nop_exporter.go create mode 100644 exporter/nopexporter/nop_exporter_test.go create mode 100644 exporter/otlpexporter/generated_component_test.go create mode 100644 exporter/otlpexporter/generated_package_test.go create mode 100644 exporter/otlpexporter/internal/metadata/generated_telemetry.go create mode 100644 exporter/otlpexporter/internal/metadata/generated_telemetry_test.go create mode 100644 exporter/otlphttpexporter/generated_component_test.go rename exporter/otlphttpexporter/{package_test.go => generated_package_test.go} (62%) create mode 100644 exporter/otlphttpexporter/internal/metadata/generated_telemetry.go create mode 100644 exporter/otlphttpexporter/internal/metadata/generated_telemetry_test.go create mode 100644 extension/ballastextension/generated_component_test.go rename extension/ballastextension/{package_test.go => generated_package_test.go} (62%) create mode 100644 extension/ballastextension/internal/metadata/generated_telemetry.go create mode 100644 extension/ballastextension/internal/metadata/generated_telemetry_test.go create mode 100644 extension/memorylimiterextension/generated_component_test.go create mode 100644 extension/memorylimiterextension/generated_package_test.go create mode 100644 extension/memorylimiterextension/internal/metadata/generated_telemetry.go create mode 100644 extension/memorylimiterextension/internal/metadata/generated_telemetry_test.go create mode 100644 extension/zpagesextension/generated_component_test.go rename extension/zpagesextension/{package_test.go => generated_package_test.go} (62%) create mode 100644 extension/zpagesextension/internal/metadata/generated_telemetry.go create mode 100644 extension/zpagesextension/internal/metadata/generated_telemetry_test.go create mode 100644 filter/Makefile create mode 100644 filter/config.go create mode 100644 filter/config_test.go create mode 100644 filter/doc.go create mode 100644 filter/filter.go create mode 100644 filter/go.mod create mode 100644 filter/go.sum create mode 100644 filter/testdata/config.yaml create mode 100644 filter/testdata/config_invalid.yaml create mode 100644 internal/httphelper/helper.go create mode 100644 internal/httphelper/helper_test.go create mode 100644 internal/memorylimiter/testdata/negative_unsigned_limits_config.yaml delete mode 100644 obsreport/doc.go delete mode 100644 obsreport/obsreporttest/deprecated.go delete mode 100644 obsreport/obsreporttest/package_test.go create mode 100644 otelcol/collector_windows_service_test.go create mode 100644 otelcol/testdata/components-output.yaml create mode 100644 otelcol/testdata/otel-log-to-file.yaml create mode 100644 otelcol/testdata/otelcol-invalid-receiver-type.yaml create mode 100644 pdata/testdata/Makefile rename {internal => pdata}/testdata/common.go (100%) create mode 100644 pdata/testdata/go.mod create mode 100644 pdata/testdata/go.sum rename {internal => pdata}/testdata/log.go (100%) rename {internal => pdata}/testdata/metric.go (100%) rename {internal => pdata}/testdata/resource.go (100%) rename {internal => pdata}/testdata/trace.go (100%) create mode 100644 processor/batchprocessor/generated_component_test.go rename processor/batchprocessor/{package_test.go => generated_package_test.go} (62%) create mode 100644 processor/batchprocessor/internal/metadata/generated_telemetry.go create mode 100644 processor/batchprocessor/internal/metadata/generated_telemetry_test.go create mode 100644 processor/memorylimiterprocessor/generated_component_test.go rename processor/memorylimiterprocessor/{package_test.go => generated_package_test.go} (63%) create mode 100644 processor/memorylimiterprocessor/internal/metadata/generated_telemetry.go create mode 100644 processor/memorylimiterprocessor/internal/metadata/generated_telemetry_test.go create mode 100644 receiver/nopreceiver/Makefile create mode 100644 receiver/nopreceiver/README.md create mode 100644 receiver/nopreceiver/doc.go create mode 100644 receiver/nopreceiver/generated_component_test.go create mode 100644 receiver/nopreceiver/generated_package_test.go create mode 100644 receiver/nopreceiver/go.mod create mode 100644 receiver/nopreceiver/go.sum create mode 100644 receiver/nopreceiver/internal/metadata/generated_status.go create mode 100644 receiver/nopreceiver/internal/metadata/generated_telemetry.go create mode 100644 receiver/nopreceiver/internal/metadata/generated_telemetry_test.go create mode 100644 receiver/nopreceiver/metadata.yaml create mode 100644 receiver/nopreceiver/nop_receiver.go create mode 100644 receiver/nopreceiver/nop_receiver_test.go create mode 100644 receiver/otlpreceiver/generated_component_test.go create mode 100644 receiver/otlpreceiver/generated_package_test.go create mode 100644 receiver/otlpreceiver/internal/metadata/generated_telemetry.go create mode 100644 receiver/otlpreceiver/internal/metadata/generated_telemetry_test.go delete mode 100644 receiver/otlpreceiver/package_test.go create mode 100644 semconv/v1.25.0/doc.go create mode 100644 semconv/v1.25.0/generated_attribute_group.go create mode 100644 semconv/v1.25.0/generated_event.go create mode 100644 semconv/v1.25.0/generated_resource.go create mode 100644 semconv/v1.25.0/generated_trace.go create mode 100644 semconv/v1.25.0/schema.go delete mode 100644 service/telemetry/otel_trace_sampler.go diff --git a/.chloggen/use-sync/atomic.yaml b/.chloggen/use-sync/atomic.yaml deleted file mode 100755 index 35d3a11fefc..00000000000 --- a/.chloggen/use-sync/atomic.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: all - -# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: "replacing uber-go/atomic by sync/atomic" - -# One or more tracking issues or pull requests related to the change -issues: [7160] - -# (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/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 17843187e81..951330bb93b 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -15,15 +15,15 @@ not be prioritized. _Delete this paragraph before submitting._ **Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + **Describe the solution you'd like** -A clear and concise description of what you want to happen. + **Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. + **Additional context** -Add any other context or screenshots about the feature request here. + _Please delete paragraphs that you did not use before submitting._ diff --git a/.github/ISSUE_TEMPLATE/release.md b/.github/ISSUE_TEMPLATE/release.md index 1a5c7366c9c..7ac68b668d3 100644 --- a/.github/ISSUE_TEMPLATE/release.md +++ b/.github/ISSUE_TEMPLATE/release.md @@ -7,7 +7,7 @@ assignees: '' --- -Like #4522, but for vX.X.X +Like #9601, but for vX.X.X **Performed by collector release manager** @@ -19,6 +19,7 @@ Like #4522, but for vX.X.X - [ ] Tag and release contrib vX.X.X - [ ] Prepare otelcol-releases vX.X.X - [ ] Release binaries and container images vX.X.X +- [ ] Update the release schedule in docs/RELEASE.md **Performed by operator maintainers** diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index cde4e56a1c5..785a666f0eb 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,18 +1,15 @@ -## 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 and are not aimed at stabilizing and preparing the Collector for the release will -not be accepted. - -_Delete the preceding paragraph before submitting._ - -**Description:** +#### Description -**Link to tracking Issue:** + +#### Link to tracking issue +Fixes # -**Testing:** + +#### Testing -**Documentation:** + +#### 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 8bed13f01a8..cd2fda2aaab 100644 --- a/.github/workflows/api-compatibility.yml +++ b/.github/workflows/api-compatibility.yml @@ -22,13 +22,13 @@ jobs: steps: - name: Checkout-Main - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: ref: ${{ github.base_ref }} path: ${{ github.base_ref }} - name: Checkout-HEAD - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: path: ${{ github.head_ref }} diff --git a/.github/workflows/build-and-test-windows.yaml b/.github/workflows/build-and-test-windows.yaml index 4fca5f3ffc6..09124dfab02 100644 --- a/.github/workflows/build-and-test-windows.yaml +++ b/.github/workflows/build-and-test-windows.yaml @@ -18,14 +18,14 @@ jobs: runs-on: windows-latest steps: - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: ~1.21.5 cache: false - name: Cache Go - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 env: cache-name: cache-go-modules with: @@ -35,3 +35,42 @@ jobs: key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - name: Run Unit Tests run: make gotest + + windows-service-test: + runs-on: windows-latest + steps: + - name: Checkout Repo + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - name: Setup Go + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + with: + go-version: ~1.21.5 + cache: false + - name: Cache Go + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + env: + cache-name: cache-go-modules + with: + path: | + ~\go\pkg\mod + ~\AppData\Local\go-build + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + + - name: Make otelcorecol + run: make otelcorecol + + - name: Install otelcorecol as a service + run: | + New-Service -Name "otelcorecol" -StartupType "Manual" -BinaryPathName "${PWD}\bin\otelcorecol_windows_amd64 --config ${PWD}\examples\local\otel-config.yaml" + eventcreate.exe /t information /id 1 /l application /d "Creating event provider for 'otelcorecol'" /so otelcorecol + + - name: Test otelcorecol service + working-directory: ${{ github.workspace }}/otelcol + run: | + go test -timeout 90s -run ^TestCollectorAsService$ -v -tags=win32service + + - name: Remove otelcorecol service + if: always() + run: | + Remove-Service otelcorecol + Remove-Item HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\Application\otelcorecol diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index a9421cb4976..b7ed51a68e4 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -15,15 +15,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.21.5 + go-version: ~1.21.9 cache: false - name: Cache Go id: go-cache - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: | ~/go/bin @@ -38,15 +38,15 @@ jobs: needs: [setup-environment] steps: - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.21.5 + go-version: ~1.21.9 cache: false - name: Cache Go id: go-cache - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: | ~/go/bin @@ -62,15 +62,15 @@ jobs: timeout-minutes: 30 steps: - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.21.5 + go-version: ~1.21.9 cache: false - name: Cache Go id: go-cache - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: | ~/go/bin @@ -87,15 +87,15 @@ jobs: needs: [setup-environment] steps: - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.21.5 + go-version: ~1.21.9 cache: false - name: Cache Go id: go-cache - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: | ~/go/bin @@ -137,12 +137,23 @@ jobs: unittest-matrix: strategy: matrix: - go-version: ["~1.22", "~1.21.5"] # 1.20 needs quotes otherwise it's interpreted as 1.2 - runs-on: ubuntu-latest + runner: [ubuntu-latest, actuated-arm64-4cpu-4gb] + exclude: + - go-version: "~1.21.9" + runner: actuated-arm64-4cpu-4gb + go-version: ["~1.22", "~1.21.9"] # 1.20 needs quotes otherwise it's interpreted as 1.2 + runs-on: ${{ matrix.runner }} needs: [setup-environment] steps: + - name: Set up arkade + uses: alexellis/setup-arkade@v3 + - name: Install vmmeter + run: | + sudo -E arkade oci install ghcr.io/openfaasltd/vmmeter:latest --path /usr/local/bin/ + - name: Run vmmeter + uses: self-actuated/vmmeter-action@v1 - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: @@ -150,19 +161,20 @@ jobs: cache: false - name: Cache Go id: go-cache - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: | ~/go/bin ~/go/pkg/mod - key: go-cache-${{ runner.os }}-${{ hashFiles('**/go.sum') }} + key: go-cache-${{ runner.os }}-${{ matrix.runner }}-${{ hashFiles('**/go.sum') }} - name: Cache Build - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ~/.cache/go-build - key: unittest-${{ runner.os }}-go-build-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }} + key: unittest-${{ runner.os }}-${{ matrix.runner }}-go-build-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }} - name: Run Unit Tests - run: make gotest + run: | + make -j4 gotest unittest: if: always() runs-on: ubuntu-latest @@ -185,37 +197,31 @@ jobs: needs: [setup-environment] steps: - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.21.5 + go-version: ~1.21.9 cache: false - name: Cache Go id: go-cache - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: | ~/go/bin ~/go/pkg/mod key: go-cache-${{ runner.os }}-${{ hashFiles('**/go.sum') }} - name: Cache Build - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 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@0ef67d343938e879e0a9bb37c107a55731e8ed35 # v1.4.5 - with: - action: codecov/codecov-action@v3 - with: | - file: ./coverage.txt - fail_ci_if_error: true - verbose: true - attempt_limit: 10 - attempt_delay: 15000 + uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # 4.3.1 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} cross-build-collector: needs: [setup-environment] @@ -253,15 +259,15 @@ jobs: steps: - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.21.5 + go-version: ~1.21.9 cache: false - name: Cache Go id: go-cache - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: | ~/go/bin diff --git a/.github/workflows/builder-integration-test.yaml b/.github/workflows/builder-integration-test.yaml index 840fe378de3..94ed1a3179b 100644 --- a/.github/workflows/builder-integration-test.yaml +++ b/.github/workflows/builder-integration-test.yaml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: diff --git a/.github/workflows/builder-release.yaml b/.github/workflows/builder-release.yaml index 12b128e8d17..86f0717b0f2 100644 --- a/.github/workflows/builder-release.yaml +++ b/.github/workflows/builder-release.yaml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: fetch-depth: 0 - name: Setup Go diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 7a57b9421d5..1838f6f3caf 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -26,7 +26,7 @@ jobs: PR_HEAD: ${{ github.event.pull_request.head.sha }} steps: - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: fetch-depth: 0 - name: Setup Go @@ -35,7 +35,7 @@ jobs: go-version: ~1.21.5 - name: Cache Go id: go-cache - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: | ~/go/bin diff --git a/.github/workflows/check-links.yaml b/.github/workflows/check-links.yaml index 338e0718131..93a407948ad 100644 --- a/.github/workflows/check-links.yaml +++ b/.github/workflows/check-links.yaml @@ -21,7 +21,7 @@ jobs: md: ${{ steps.changes.outputs.md }} steps: - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: fetch-depth: 0 - name: Get changed files @@ -34,12 +34,12 @@ jobs: if: ${{needs.changedfiles.outputs.md}} steps: - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: fetch-depth: 0 - name: Install markdown-link-check - run: npm install -g markdown-link-check + run: npm install -g markdown-link-check@3.11.2 - name: Run markdown-link-check run: | diff --git a/.github/workflows/check_links_config.json b/.github/workflows/check_links_config.json index 82ca9c0c33d..84c68f6fdf3 100644 --- a/.github/workflows/check_links_config.json +++ b/.github/workflows/check_links_config.json @@ -8,6 +8,9 @@ }, { "pattern": "http(s)?://example.com" + }, + { + "pattern": "#warnings" } ], "aliveStatusCodes": [429, 200], diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c49d7dc19af..70dc2f95c98 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 @@ -30,12 +30,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 + uses: github/codeql-action/init@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: languages: go - name: Autobuild - uses: github/codeql-action/autobuild@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 + uses: github/codeql-action/autobuild@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 + uses: github/codeql-action/analyze@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 diff --git a/.github/workflows/contrib-tests.yml b/.github/workflows/contrib-tests.yml index d17bfb6f9a8..0c8b11b8996 100644 --- a/.github/workflows/contrib-tests.yml +++ b/.github/workflows/contrib-tests.yml @@ -38,7 +38,7 @@ jobs: - other steps: - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: diff --git a/.github/workflows/generate-semantic-conventions-pr.yaml b/.github/workflows/generate-semantic-conventions-pr.yaml index ad3275a2123..8bc7c691698 100644 --- a/.github/workflows/generate-semantic-conventions-pr.yaml +++ b/.github/workflows/generate-semantic-conventions-pr.yaml @@ -14,7 +14,7 @@ jobs: already-added: ${{ steps.check-versions.outputs.already-added }} already-opened: ${{ steps.check-versions.outputs.already-opened }} steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - id: check-versions name: Check versions @@ -56,9 +56,9 @@ jobs: needs: - check-versions steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Checkout semantic-convention - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: repository: open-telemetry/semantic-convention path: tmp-semantic-conventions diff --git a/.github/workflows/perf.yml b/.github/workflows/perf.yml index cc103bafcea..432cebcb13f 100644 --- a/.github/workflows/perf.yml +++ b/.github/workflows/perf.yml @@ -11,7 +11,7 @@ jobs: runperf: runs-on: ubuntu-latest steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 6ff746ec06a..5bed593e28b 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -6,18 +6,18 @@ on: # the minor version number and set the patch number to 0. inputs: candidate-stable: - description: Release candidate version (stable, like 1.0.0-rcv0014). Don't include a leading `v`. + description: Release candidate version (stable, like 1.3.0). Don't include a leading `v`. current-stable: required: true - description: Current version (stable, like 1.0.0-rcv0014). Don't include a leading `v`. + description: Current version (stable, like 1.2.0). Don't include a leading `v`. candidate-beta: - description: Release candidate version (beta, like 0.70.0). Don't include `v`. + description: Release candidate version (beta, like 0.96.0). Don't include `v`. current-beta: required: true - description: Current version (beta, like 0.69.1). Don't include `v`. + description: Current version (beta, like 0.95.1). Don't include `v`. jobs: #validate-version format validate-versions: @@ -54,7 +54,7 @@ jobs: - validate-versions runs-on: ubuntu-latest steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 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. diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 2b8b2e72658..3cfdee49ed5 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -29,7 +29,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: persist-credentials: false @@ -56,7 +56,7 @@ jobs: # 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 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: SARIF file path: results.sarif @@ -64,6 +64,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@8a470fddafa5cbb6266ee11b37ef4d8aae19c571 # v3.24.6 + uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: sarif_file: results.sarif diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index 92446e0fbda..aa59846bea5 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -13,6 +13,6 @@ jobs: name: Shellcheck runs-on: ubuntu-latest steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Run ShellCheck uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0 diff --git a/.github/workflows/tidy-dependencies.yml b/.github/workflows/tidy-dependencies.yml index 28752e3a56d..7427464d9a3 100644 --- a/.github/workflows/tidy-dependencies.yml +++ b/.github/workflows/tidy-dependencies.yml @@ -16,16 +16,16 @@ jobs: runs-on: ubuntu-latest 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@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: ref: ${{ github.head_ref }} - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: ~1.21.5 + go-version: ~1.21.9 cache: false - name: Cache Go id: go-cache - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: | ~/go/bin diff --git a/CHANGELOG-API.md b/CHANGELOG-API.md index 6ebdddf897f..a727efcbae1 100644 --- a/CHANGELOG-API.md +++ b/CHANGELOG-API.md @@ -7,6 +7,86 @@ If you are looking for user-facing changes, check out [CHANGELOG.md](./CHANGELOG +## v1.7.0/v0.100.0 + +### 💡 Enhancements 💡 + +- `configgrpc`: Adds `NewDefault*` functions for all the config structs. (#9654) +- `exporterqueue`: Expose ErrQueueIsFull so upstream components can retry or apply backpressure. (#10070) + +### 🧰 Bug fixes 🧰 + +- `mdatagen`: Call connectors with routers to be the same as the service graph (#10079) + +## v1.6.0/v0.99.0 + +### 🛑 Breaking changes 🛑 + +- `component`: Removed deprecated function `GetExporters` from `component.Host` interface (#9987) + +### 🚩 Deprecations 🚩 + +- `confighttp`: deprecate ToClientContext, ToServerContext, ToListenerContext, replaced by ToClient, ToServer, ToListener (#9807) +- `configtls`: Deprecates `ClientConfig.LoadTLSConfigContext` and `ServerConfig.LoadTLSConfigContext`, use `ClientConfig.LoadTLSConfig` and `ServerConfig.LoadTLSConfig` instead. (#9945) + +### 💡 Enhancements 💡 + +- `configauth`: Adds `NewDefault*` functions for all the config structs. (#9821) +- `configtls`: Adds `NewDefault*` functions for all the config structs. (#9658) +- `pmetric`: Support metric.metadata in pdata/pmetric (#10006) + +## v1.5.0/v0.98.0 + +### 🛑 Breaking changes 🛑 + +- `component`: Restricts maximum length for `component.Type` to 63 characters. (#9872) +- `configgrpc`: Remove deprecated `ToServerContext`, use `ToServer` instead. (#9836) +- `configgrpc`: Remove deprecated `SanitizedEndpoint`. (#9836) +- `configtls`: Remove Deprecated `TLSSetting`, `TLSClientSetting`, and `TLSServerSetting`. (#9786) +- `configtls`: Rename `TLSSetting` to `Config` on `ClientConfig` and `ServerConfig`. (#9786) + +### 🚩 Deprecations 🚩 + +- `confighttp`: Deprecate `ToClient`,`ToListener`and `ToServer` use `ToClientContext`,`ToListenerContext` and `ToServerContext`instead. (#9807) +- `configtls`: Deprecate `ClientConfig.LoadTLSConfig` and `ServerConfig.LoadTLSConfig`, use `ClientConfig.LoadTLSConfigContext` and `ServerConfig.LoadTLSConfigContext` instead. (#9811) + +### 💡 Enhancements 💡 + +- Introduce new module for generating pdata: pdata/testdata (#9886) +- `exporterhelper`: Make the `WithBatcher` option available for regular exporter helpers based on OTLP data type. (#8122) + Now, `WithBatcher` can be used with both regular exporter helper (e.g. NewTracesExporter) and the request-based exporter + helper (e.g. NewTracesRequestExporter). The request-based exporter helpers require `WithRequestBatchFuncs` option + providing batching functions. + +- `confmap`: Creates a logger in the confmap.ProviderSettings and uses it to log when there is a missing or blank environment variable referenced in config. For now the noop logger is used everywhere except tests. (#5615) + +## v1.4.0/v0.97.0 + +### 🛑 Breaking changes 🛑 + +- `configgrpc`: Remove deprecated `ToServer` function. (#9787) +- `confignet`: Change `Transport` field from `string` to `TransportType` (#9385) +- `component`: Change underlying type of `component.Type` to an opaque struct. (#9208) +- `obsreport`: Remove deprecated obsreport/obsreporttest package. (#9724) +- `component`: Remove deprecated error `ErrNilNextConsumer` (#9322) +- `connector`: Remove `LogsRouter`, `MetricsRouter` and `TracesRouter`. Use `LogsRouterAndConsumer`, `MetricsRouterAndConsumer`, `TracesRouterAndConsumer` respectively instead. (#9095) +- `receiver`: Remove deprecated struct `ScraperControllerSettings` and function `NewDefaultScraperControllerSettings` (#6767) +- `confmap`: Remove deprecated `provider.New` methods, use `NewWithSettings` moving forward. (#9443) + +### 🚩 Deprecations 🚩 + +- `configgrpc`: Deprecated `ToServerContext`, use `ToServer` instead. (#9787) +- `configgrpc`: Deprecate `SanitizedEndpoint` (#9788) + +### 💡 Enhancements 💡 + +- `exporterhelper`: Add experimental batching capabilities to the exporter helper (#8122) +- `confignet`: Adds `NewDefault*` functions for all the config structs. (#9656) +- `configtls`: Validates TLS min_version and max_version (#9475) + Introduces `Validate()` method in TLSSetting. +- `exporterhelper`: Invalid exporterhelper options now make the exporter creation error out instead of panicking. (#9717) +- `components`: Give NoOp components a unique name (#9637) + ## v1.3.0/v0.96.0 ### 🚩 Deprecations 🚩 diff --git a/CHANGELOG.md b/CHANGELOG.md index f1238d56c8b..b37709193bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,136 @@ If you are looking for developer-facing changes, check out [CHANGELOG-API.md](./ +## v1.7.0/v0.100.0 + +### 🛑 Breaking changes 🛑 + +- `service`: The `validate` sub-command no longer validates that each pipeline's type is the same as its component types (#10031) + +### 💡 Enhancements 💡 + +- `semconv`: Add support for v1.25.0 semantic convention (#10072) +- `builder`: remove the need to go get a module to address ambiguous import paths (#10015) +- `pmetric`: Support parsing metric.metadata from OTLP JSON. (#10026) + +### 🧰 Bug fixes 🧰 + +- `exporterhelper`: Fix enabled config option for batch sender (#10076) + +## v1.6.0/v0.99.0 + +### 🛑 Breaking changes 🛑 + +- `builder`: Add strict version checking when using the builder. Add the temporary flag `--skip-strict-versioning `for skipping this check. (#9896) + Strict version checking will error on major and minor version mismatches + between the `otelcol_version` configured and the builder version or versions + in the go.mod. This check can be temporarily disabled by using the `--skip-strict-versioning` + flag. This flag will be removed in a future minor version. + +- `telemetry`: Distributed internal metrics across different levels. (#7890) + The internal metrics levels are updated along with reported metrics: + - The default level is changed from `basic` to `normal`, which can be overridden with `service::telmetry::metrics::level` configuration. + - Batch processor metrics are updated to be reported starting from `normal` level: + - `processor_batch_batch_send_size` + - `processor_batch_metadata_cardinality` + - `processor_batch_timeout_trigger_send` + - `processor_batch_size_trigger_send` + - GRPC/HTTP server and client metrics are updated to be reported starting from `detailed` level: + - http.client.* metrics + - http.server.* metrics + - rpc.server.* metrics + - rpc.client.* metrics + + +### 💡 Enhancements 💡 + +- `confighttp`: Disable concurrency in zstd compression (#8216) +- `cmd/builder`: Allow configuring `confmap.Provider`s in the builder. (#4759) + If no providers are specified, the defaults are used. + The default providers are: env, file, http, https, and yaml. + + To configure providers, use the `providers` key in your OCB build + manifest with a list of Go modules for your providers. + The modules will work the same as other Collector components. + +- `mdatagen`: enable goleak tests by default via mdatagen (#9959) +- `cmd/mdatagen`: support excluding some metrics based on string and regexes in resource_attributes (#9661) +- `cmd/mdatagen`: Generate config and factory tests covering their requirements. (#9940) + The tests are moved from cmd/builder. + +- `confmap`: Add `ProviderSettings`, `ConverterSettings`, `ProviderFactories`, and `ConverterFactories` fields to `confmap.ResolverSettings` (#9516) + This allows configuring providers and converters, which are instantiated by `NewResolver` using the given factories. + +### 🧰 Bug fixes 🧰 + +- `exporter/otlp`: Allow DNS scheme to be used in endpoint (#4274) +- `service`: fix record sampler configuration (#9968) +- `service`: ensure the tracer provider is configured via go.opentelemetry.io/contrib/config (#9967) +- `otlphttpexporter`: Fixes a bug that was preventing the otlp http exporter from propagating status. (#9892) +- `confmap`: Fix decoding negative configuration values into uints (#9060) + +## v1.5.0/v0.98.0 + +### 🛑 Breaking changes 🛑 + +- `service`: emit internal collector metrics with _ instead of / with OTLP export (#9774) + This is addressing an issue w/ the names of the metrics generated by the Collector for its + internal metrics. Note that this change only impacts users that emit telemetry using OTLP, which + is currently still in experimental support. The prometheus metrics already replaced `/` with `_` + and they will do the same with `_`. + + +### 💡 Enhancements 💡 + +- `mdatagen`: Adds unsupported platforms to the README header (#9794) +- `confmap`: Clarify the use of embedded structs to make unmarshaling composable (#7101) +- `nopexporter`: Promote the nopexporter to beta (#7316) +- `nopreceiver`: Promote the nopreceiver to beta (#7316) +- `otlpexporter`: Checks for port in the config validation for the otlpexporter (#9505) +- `service`: Validate pipeline type against component types (#8007) + +### 🧰 Bug fixes 🧰 + +- `configtls`: Fix issue where `IncludeSystemCACertsPool` was not consistently used between `ServerConfig` and `ClientConfig`. (#9835) +- `component`: Fix issue where the `components` command wasn't properly printing the component type. (#9856) +- `otelcol`: Fix issue where the `validate` command wasn't properly printing valid component type. (#9866) +- `receiver/otlp`: Fix bug where the otlp receiver did not properly respond with a retryable error code when possible for http (#9357) + +## v1.4.0/v0.97.0 + +### 🛑 Breaking changes 🛑 + +- `telemetry`: Remove telemetry.useOtelForInternalMetrics stable feature gate (#9752) + +### 🚀 New components 🚀 + +- `exporter/nop`: Add the `nopexporter` to serve as a placeholder exporter in a pipeline (#7316) + This is primarily useful for starting the Collector with only extensions enabled + or to test Collector pipeline throughput. + +- `receiver/nop`: Add the `nopreceiver` to serve as a placeholder receiver in a pipeline (#7316) + This is primarily useful for starting the Collector with only extensions enabled. + +### 💡 Enhancements 💡 + +- `configtls`: Validates TLS min_version and max_version (#9475) + Introduces `Validate()` method in TLSSetting. +- `configcompression`: Mark module as Stable. (#9571) +- `cmd/mdatagen`: Use go package name for the scope name by default and add an option to provide the scope name in metadata.yaml. (#9693) +- `cmd/mdatagen`: Generate the lifecycle tests for components by default. (#9683) + It's encouraged to have lifecycle tests for all components enadled, but they can be disabled if needed + in metadata.yaml with `skip_lifecycle: true` and `skip_shutdown: true` under `tests` section. + +- `cmd/mdatagen`: optimize the mdatagen for the case like batchprocessor which use a common struct to implement consumer.Traces, consumer.Metrics, consumer.Logs in the meantime. (#9688) + +### 🧰 Bug fixes 🧰 + +- `exporterhelper`: Fix persistent queue size backup on reads. (#9740) +- `processor/batch`: Prevent starting unnecessary goroutines. (#9739) +- `otlphttpexporter`: prevent error on empty response body when content type is application/json (#9666) +- `confmap`: confmap honors `Unmarshal` methods on config embedded structs. (#6671) +- `otelcol`: Respect telemetry configuration when running as a Windows service (#5300) + ## v1.3.0/v0.96.0 ### 🛑 Breaking changes 🛑 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1f99bb80c8c..fb881c33d16 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -147,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.20 and up) +2. [go](https://golang.org/) (version 1.21 and up) 3. [make](https://www.gnu.org/software/make/) 4. [docker](https://www.docker.com/) @@ -204,12 +204,9 @@ before merging (but see above paragraph about writing good commit messages in th ## General Notes -This project uses Go 1.20.* and [Github Actions.](https://github.com/features/actions) +This project uses Go 1.21.* and [Github Actions.](https://github.com/features/actions) -It is recommended to run `make gofmt all` before submitting your PR - -The dependencies are managed with `go mod` if you work with the sources under your -`$GOPATH` you need to set the environment variable `GO111MODULE=on`. +It is recommended to run `make gofmt all` before submitting your PR. ## Coding Guidelines @@ -510,6 +507,19 @@ that each of the following steps is done in a separate version: 1. On `v0.N+2`, we change `func GetFoo() Foo` to `func GetFoo(context.Context) Foo` if desired or remove it entirely if needed. +#### Exceptions + +For changes to modules that do not have a version of `v1` or higher, we may skip the deprecation process described above +for the following situations. Note that these changes should still be recorded as breaking changes in the changelog. + +* **Variadic arguments.** Functions that are not already variadic may have a variadic parameter added as a method of + supporting optional parameters, particularly through the functional options pattern. If a variadic parameter is + added to a function with no change in functionality when no variadic arguments are passed, the deprecation process + may be skipped. Calls to updated functions without the new argument will continue to work before, but users who depend + on the exact function signature as a type, for example as an argument to another function, will experience a + breaking change. For this reason, the deprecation process should only be skipped when it is not expected that + the function is commonly passed as a value. + #### Configuration changes ##### Alpha components diff --git a/Makefile b/Makefile index c2cbc2c0bdb..8fb56bfbdc9 100644 --- a/Makefile +++ b/Makefile @@ -138,7 +138,7 @@ endif # Build the Collector executable. .PHONY: otelcorecol otelcorecol: - pushd cmd/otelcorecol && GO111MODULE=on CGO_ENABLED=0 $(GOCMD) build -trimpath -o ../../bin/otelcorecol_$(GOOS)_$(GOARCH) \ + pushd cmd/otelcorecol && CGO_ENABLED=0 $(GOCMD) build -trimpath -o ../../bin/otelcorecol_$(GOOS)_$(GOARCH) \ -tags $(GO_BUILD_TAGS) ./cmd/otelcorecol && popd .PHONY: genotelcorecol @@ -157,7 +157,7 @@ ocb: OPENTELEMETRY_PROTO_SRC_DIR=pdata/internal/opentelemetry-proto # The branch matching the current version of the proto to use -OPENTELEMETRY_PROTO_VERSION=v1.1.0 +OPENTELEMETRY_PROTO_VERSION=v1.2.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)) @@ -237,6 +237,7 @@ gensemconv: $(SEMCONVGEN) $(SEMCONVKIT) $(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 + $(SEMCONVGEN) -o semconv/${SPECTAG} -t semconv/template.j2 -s ${SPECTAG} -i ${SPECPATH}/model/. --only=attribute_group -p conventionType=attribute_group -f generated_attribute_group.go $(SEMCONVKIT) -output "semconv/$(SPECTAG)" -tag "$(SPECTAG)" # Checks that the HEAD of the contrib repo checked out in CONTRIB_PATH compiles @@ -270,6 +271,7 @@ check-contrib: -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/nopexporter=$(CURDIR)/exporter/nopexporter \ -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 \ @@ -280,10 +282,12 @@ check-contrib: -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/pdata/testdata=$(CURDIR)/pdata/testdata \ -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/nopreceiver=$(CURDIR)/receiver/nopreceiver \ -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" @@ -323,6 +327,7 @@ restore-contrib: -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/nopexporter \ -dropreplace go.opentelemetry.io/collector/exporter/otlpexporter \ -dropreplace go.opentelemetry.io/collector/exporter/otlphttpexporter \ -dropreplace go.opentelemetry.io/collector/extension \ @@ -333,10 +338,12 @@ restore-contrib: -dropreplace go.opentelemetry.io/collector/featuregate \ -dropreplace go.opentelemetry.io/collector/otelcol \ -dropreplace go.opentelemetry.io/collector/pdata \ + -dropreplace go.opentelemetry.io/collector/pdata/testdata \ -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/nopreceiver \ -dropreplace go.opentelemetry.io/collector/receiver/otlpreceiver \ -dropreplace go.opentelemetry.io/collector/semconv \ -dropreplace go.opentelemetry.io/collector/service" diff --git a/Makefile.Common b/Makefile.Common index 195701daf59..ca9b17c56df 100644 --- a/Makefile.Common +++ b/Makefile.Common @@ -4,7 +4,8 @@ ALL_PKGS := $(sort $(shell go list ./...)) # COVER_PKGS is the list of packages to include in the coverage COVER_PKGS := $(shell go list ./... | tr "\n" ",") -GOTEST_OPT?= -race -timeout 120s +GOTEST_TIMEOUT?=240s +GOTEST_OPT?= -race -timeout $(GOTEST_TIMEOUT) GOCMD?= go GOTEST=$(GOCMD) test GOOS := $(shell $(GOCMD) env GOOS) diff --git a/README.md b/README.md index 9736c07a617..7497f7fa4e0 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,6 @@ Vision   •   - Design -   •   Configuration   •   Monitoring @@ -120,11 +118,8 @@ Here is a list of community roles with current and previous members: - Triagers ([@open-telemetry/collector-triagers](https://github.com/orgs/open-telemetry/teams/collector-triagers)): - - [Andrzej Stencel](https://github.com/astencel-sumo), Sumo Logic - - [Antoine Toulme](https://github.com/atoulme), Splunk + - [Andrzej Stencel](https://github.com/andrzej-stencel), Sumo Logic - [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: @@ -137,8 +132,11 @@ Here is a list of community roles with current and previous members: - Approvers ([@open-telemetry/collector-approvers](https://github.com/orgs/open-telemetry/teams/collector-approvers)): - [Anthony Mirabella](https://github.com/Aneurysm9), AWS + - [Antoine Toulme](https://github.com/atoulme), Splunk - [Daniel Jaglowski](https://github.com/djaglowski), observIQ - [Juraci Paixão Kröhling](https://github.com/jpkrohling), Grafana Labs + - [Tyler Helmuth](https://github.com/TylerHelmuth), Honeycomb + - [Yang Song](https://github.com/songy23), Datadog - Emeritus Approvers: diff --git a/client/client.go b/client/client.go index b8775d5a440..fa944cad909 100644 --- a/client/client.go +++ b/client/client.go @@ -98,15 +98,9 @@ type Info struct { Auth AuthData // Metadata is the request metadata from the client connecting to this connector. - // Experimental: *NOTE* this structure is subject to change or removal in the future. Metadata Metadata } -// Metadata is an immutable map, meant to contain request metadata. -type Metadata struct { - data map[string][]string -} - // AuthData represents the authentication data as seen by authenticators tied to // the receivers. type AuthData interface { @@ -116,8 +110,7 @@ type AuthData interface { // "membership" might return a list of strings. GetAttribute(string) any - // GetAttributes returns the names of all attributes in this authentication - // data. + // GetAttributeNames returns the names of all attributes in this authentication data. GetAttributeNames() []string } @@ -139,7 +132,12 @@ func FromContext(ctx context.Context) Info { return c } -// NewMetadata creates a new Metadata object to use in Info. md is used as-is. +// Metadata is an immutable map, meant to contain request metadata. +type Metadata struct { + data map[string][]string +} + +// NewMetadata creates a new Metadata object to use in Info. func NewMetadata(md map[string][]string) Metadata { c := make(map[string][]string, len(md)) for k, v := range md { @@ -151,6 +149,7 @@ func NewMetadata(md map[string][]string) Metadata { } // Get gets the value of the key from metadata, returning a copy. +// The key lookup is case-insensitive. func (m Metadata) Get(key string) []string { if len(m.data) == 0 { return nil diff --git a/cmd/builder/Makefile b/cmd/builder/Makefile index aed509584fa..988ed9e64a5 100644 --- a/cmd/builder/Makefile +++ b/cmd/builder/Makefile @@ -2,7 +2,7 @@ include ../../Makefile.Common .PHONY: ocb ocb: - GO111MODULE=on CGO_ENABLED=0 $(GOCMD) build -trimpath -o ../../bin/ocb_$(GOOS)_$(GOARCH) . + CGO_ENABLED=0 $(GOCMD) build -trimpath -o ../../bin/ocb_$(GOOS)_$(GOARCH) . # Generate the default build config from otelcorecol, by removing the # "replaces" stanza, which is assumed to be at the end of the file. diff --git a/cmd/builder/README.md b/cmd/builder/README.md index 7a4259d59e5..57fd3c4f104 100644 --- a/cmd/builder/README.md +++ b/cmd/builder/README.md @@ -5,21 +5,27 @@ This program generates a custom OpenTelemetry Collector binary based on a given ## TL;DR ```console -$ GO111MODULE=on go install go.opentelemetry.io/collector/cmd/builder@latest +$ go install go.opentelemetry.io/collector/cmd/builder@latest $ cat > otelcol-builder.yaml < /tmp/otelcol.yaml <= 0.86.0") if err != nil { return err @@ -123,6 +147,20 @@ func (c *Config) SetRequireOtelColModule() error { } c.Distribution.RequireOtelColModule = constraint.Check(otelColVersion) + + // check whether confmap factories are supported + constraint, err = version.NewConstraint(">= 0.99.0") + if err != nil { + return err + } + + otelColVersion, err = version.NewVersion(c.Distribution.OtelColVersion) + if err != nil { + return err + } + + c.Distribution.SupportsConfmapFactories = constraint.Check(otelColVersion) + return nil } @@ -155,6 +193,36 @@ func (c *Config) ParseModules() error { return err } + if c.Providers != nil { + providers, err := parseModules(*c.Providers) + if err != nil { + return err + } + c.Providers = &providers + } else { + providers, err := parseModules([]Module{ + { + GoMod: "go.opentelemetry.io/collector/confmap/provider/envprovider v" + c.Distribution.OtelColVersion, + }, + { + GoMod: "go.opentelemetry.io/collector/confmap/provider/fileprovider v" + c.Distribution.OtelColVersion, + }, + { + GoMod: "go.opentelemetry.io/collector/confmap/provider/httpprovider v" + c.Distribution.OtelColVersion, + }, + { + GoMod: "go.opentelemetry.io/collector/confmap/provider/httpsprovider v" + c.Distribution.OtelColVersion, + }, + { + GoMod: "go.opentelemetry.io/collector/confmap/provider/yamlprovider v" + c.Distribution.OtelColVersion, + }, + }) + if err != nil { + return err + } + c.Providers = &providers + } + return nil } diff --git a/cmd/builder/internal/builder/config_test.go b/cmd/builder/internal/builder/config_test.go index dccee464fe4..cd81b9f2887 100644 --- a/cmd/builder/internal/builder/config_test.go +++ b/cmd/builder/internal/builder/config_test.go @@ -220,8 +220,89 @@ func TestRequireOtelColModule(t *testing.T) { t.Run(tt.Version, func(t *testing.T) { cfg := NewDefaultConfig() cfg.Distribution.OtelColVersion = tt.Version - require.NoError(t, cfg.SetRequireOtelColModule()) + require.NoError(t, cfg.SetBackwardsCompatibility()) assert.Equal(t, tt.ExpectedRequireOtelColModule, cfg.Distribution.RequireOtelColModule) }) } } + +func TestConfmapFactoryVersions(t *testing.T) { + testCases := []struct { + version string + supported bool + err bool + }{ + { + version: "x.0.0", + supported: false, + err: true, + }, + { + version: "0.x.0", + supported: false, + err: true, + }, + { + version: "0.0.0", + supported: false, + }, + { + version: "0.98.0", + supported: false, + }, + { + version: "0.98.1", + supported: false, + }, + { + version: "0.99.0", + supported: true, + }, + { + version: "0.99.7", + supported: true, + }, + { + version: "0.100.0", + supported: true, + }, + { + version: "0.100.1", + supported: true, + }, + { + version: "1.0", + supported: true, + }, + { + version: "1.0.0", + supported: true, + }, + } + + for _, tt := range testCases { + t.Run(tt.version, func(t *testing.T) { + cfg := NewDefaultConfig() + cfg.Distribution.OtelColVersion = tt.version + if !tt.err { + require.NoError(t, cfg.SetBackwardsCompatibility()) + assert.Equal(t, tt.supported, cfg.Distribution.SupportsConfmapFactories) + } else { + require.Error(t, cfg.SetBackwardsCompatibility()) + } + }) + } +} + +func TestAddsDefaultProviders(t *testing.T) { + cfg := NewDefaultConfig() + cfg.Providers = nil + assert.NoError(t, cfg.ParseModules()) + assert.Len(t, *cfg.Providers, 5) +} + +func TestSkipsNilFieldValidation(t *testing.T) { + cfg := NewDefaultConfig() + cfg.Providers = nil + assert.NoError(t, cfg.Validate()) +} diff --git a/cmd/builder/internal/builder/main.go b/cmd/builder/internal/builder/main.go index 3b22300be2e..3d36059af36 100644 --- a/cmd/builder/internal/builder/main.go +++ b/cmd/builder/internal/builder/main.go @@ -4,42 +4,52 @@ package builder // import "go.opentelemetry.io/collector/cmd/builder/internal/builder" import ( + "bytes" "errors" "fmt" "os" "os/exec" "path/filepath" + "strings" "text/template" "time" "go.uber.org/zap" - "go.uber.org/zap/zapio" + "golang.org/x/mod/modfile" + "golang.org/x/mod/semver" ) var ( // ErrGoNotFound is returned when a Go binary hasn't been found - ErrGoNotFound = errors.New("go binary not found") + ErrGoNotFound = errors.New("go binary not found") + ErrDepNotFound = errors.New("dependency not found in go mod file") + ErrVersionMismatch = errors.New("mismatch in go.mod and builder configuration versions") + errDownloadFailed = errors.New("failed to download go modules") + errCompileFailed = errors.New("failed to compile the OpenTelemetry Collector distribution") + skipStrictMsg = "Use --skip-strict-versioning to temporarily disable this check. This flag will be removed in a future minor version" ) -func runGoCommand(cfg Config, args ...string) error { - cfg.Logger.Info("Running go subcommand.", zap.Any("arguments", args)) +func runGoCommand(cfg Config, args ...string) ([]byte, error) { + if cfg.Verbose { + 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() - } + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr - if out, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("go subcommand failed with args '%v': %w. Output:\n%s", args, err, out) + if err := cmd.Run(); err != nil { + return nil, fmt.Errorf("go subcommand failed with args '%v': %w, error message: %s", args, err, stderr.String()) + } + if cfg.Verbose && stderr.Len() != 0 { + cfg.Logger.Info("go subcommand error", zap.String("message", stderr.String())) } - return nil + return stdout.Bytes(), nil } // GenerateAndCompile will generate the source files based on the given configuration, update go mod, and will compile into a binary @@ -80,7 +90,6 @@ func Generate(cfg Config) error { mainOthersTemplate, mainWindowsTemplate, componentsTemplate, - componentsTestTemplate, goModTemplate, } { if err := processAndWrite(cfg, tmpl, tmpl.Name(), cfg); err != nil { @@ -115,8 +124,8 @@ func Compile(cfg Config) error { if cfg.Distribution.BuildTags != "" { args = append(args, "-tags", cfg.Distribution.BuildTags) } - if err := runGoCommand(cfg, args...); err != nil { - return fmt.Errorf("failed to compile the OpenTelemetry Collector distribution: %w", err) + if _, err := runGoCommand(cfg, args...); err != nil { + return fmt.Errorf("%w: %s", errCompileFailed, err.Error()) } cfg.Logger.Info("Compiled", zap.String("binary", fmt.Sprintf("%s/%s", cfg.Distribution.OutputPath, cfg.Distribution.Name))) @@ -130,30 +139,67 @@ func GetModules(cfg Config) error { return nil } - // 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) } - if err := runGoCommand(cfg, "mod", "tidy", "-compat=1.21"); err != nil { - return fmt.Errorf("failed to update go.mod: %w", err) + if cfg.SkipStrictVersioning { + return downloadModules(cfg) + } + + // Perform strict version checking. For each component listed and the + // otelcol core dependency, check that the enclosing go module matches. + modulePath, dependencyVersions, err := cfg.readGoModFile() + if err != nil { + return err + } + + corePath, coreVersion := cfg.coreModuleAndVersion() + coreDepVersion, ok := dependencyVersions[corePath] + if !ok { + return fmt.Errorf("core collector %w: '%s'. %s", ErrDepNotFound, corePath, skipStrictMsg) + } + if semver.MajorMinor(coreDepVersion) != semver.MajorMinor(coreVersion) { + return fmt.Errorf( + "%w: core collector version calculated by component dependencies %q does not match configured version %q. %s", + ErrVersionMismatch, coreDepVersion, coreVersion, skipStrictMsg) + } + + for _, mod := range cfg.allComponents() { + module, version, _ := strings.Cut(mod.GoMod, " ") + if module == modulePath { + // No need to check the version of components that are part of the + // module we're building from. + continue + } + + moduleDepVersion, ok := dependencyVersions[module] + if !ok { + return fmt.Errorf("component %w: '%s'. %s", ErrDepNotFound, module, skipStrictMsg) + } + if semver.MajorMinor(moduleDepVersion) != semver.MajorMinor(version) { + return fmt.Errorf( + "%w: component %q version calculated by dependencies %q does not match configured version %q. %s", + ErrVersionMismatch, module, moduleDepVersion, version, skipStrictMsg) + } } + return downloadModules(cfg) +} + +func downloadModules(cfg Config) error { cfg.Logger.Info("Getting go modules") - // basic retry if error from go mod command (in case of transient network error). This could be improved - // retry 3 times with 5 second spacing interval - retries := 3 failReason := "unknown" - for i := 1; i <= retries; i++ { - if err := runGoCommand(cfg, "mod", "download"); err != nil { + for i := 1; i <= cfg.downloadModules.numRetries; i++ { + 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) + cfg.Logger.Info("Failed modules download", zap.String("retry", fmt.Sprintf("%d/%d", i, cfg.downloadModules.numRetries))) + time.Sleep(cfg.downloadModules.wait) continue } return nil } - return fmt.Errorf("failed to download go modules: %s", failReason) + return fmt.Errorf("%w: %s", errDownloadFailed, failReason) } func processAndWrite(cfg Config, tmpl *template.Template, outFile string, tmplParams any) error { @@ -165,3 +211,44 @@ func processAndWrite(cfg Config, tmpl *template.Template, outFile string, tmplPa defer out.Close() return tmpl.Execute(out, tmplParams) } + +func (c *Config) coreModuleAndVersion() (string, string) { + module := "go.opentelemetry.io/collector" + if c.Distribution.RequireOtelColModule { + module += "/otelcol" + } + return module, "v" + c.Distribution.OtelColVersion +} + +func (c *Config) allComponents() []Module { + // TODO: Use slices.Concat when we drop support for Go 1.21 + return append(c.Exporters, + append(c.Receivers, + append(c.Processors, + append(c.Extensions, + append(c.Connectors, + *c.Providers...)...)...)...)...) +} + +func (c *Config) readGoModFile() (string, map[string]string, error) { + var modPath string + stdout, err := runGoCommand(*c, "mod", "edit", "-print") + if err != nil { + return modPath, nil, err + } + parsedFile, err := modfile.Parse("go.mod", stdout, nil) + if err != nil { + return modPath, nil, err + } + if parsedFile != nil && parsedFile.Module != nil { + modPath = parsedFile.Module.Mod.Path + } + dependencies := map[string]string{} + for _, req := range parsedFile.Require { + if req == nil { + continue + } + dependencies[req.Mod.Path] = req.Mod.Version + } + return modPath, dependencies, nil +} diff --git a/cmd/builder/internal/builder/main_test.go b/cmd/builder/internal/builder/main_test.go index 6a237743b29..7ddd7ff7408 100644 --- a/cmd/builder/internal/builder/main_test.go +++ b/cmd/builder/internal/builder/main_test.go @@ -13,29 +13,178 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.uber.org/zap" ) -func TestGenerateDefault(t *testing.T) { - require.NoError(t, Generate(NewDefaultConfig())) -} +var ( + goModTestFile = []byte(`// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 +module go.opentelemetry.io/collector/cmd/builder/internal/tester +go 1.20 +require ( + go.opentelemetry.io/collector/component v0.96.0 + go.opentelemetry.io/collector/connector v0.94.1 + go.opentelemetry.io/collector/exporter v0.94.1 + go.opentelemetry.io/collector/extension v0.94.1 + go.opentelemetry.io/collector/otelcol v0.94.1 + go.opentelemetry.io/collector/processor v0.94.1 + go.opentelemetry.io/collector/receiver v0.94.1 + go.opentelemetry.io/collector v0.96.0 +)`) +) -func TestGenerateInvalidCollectorVersion(t *testing.T) { +func newTestConfig() Config { cfg := NewDefaultConfig() - cfg.Distribution.OtelColVersion = "invalid" - err := Generate(cfg) - require.NoError(t, err) + cfg.downloadModules.wait = 0 + cfg.downloadModules.numRetries = 1 + return cfg +} + +func newInitializedConfig(t *testing.T) Config { + cfg := newTestConfig() + // Validate and ParseModules will be called before the config is + // given to Generate. + assert.NoError(t, cfg.Validate()) + assert.NoError(t, cfg.SetBackwardsCompatibility()) + assert.NoError(t, cfg.ParseModules()) + + return cfg +} + +func TestGenerateDefault(t *testing.T) { + require.NoError(t, Generate(newInitializedConfig(t))) } func TestGenerateInvalidOutputPath(t *testing.T) { - cfg := NewDefaultConfig() + cfg := newInitializedConfig(t) cfg.Distribution.OutputPath = "/:invalid" err := Generate(cfg) require.Error(t, err) require.Contains(t, err.Error(), "failed to create output path") } +func TestVersioning(t *testing.T) { + replaces := generateReplaces() + tests := []struct { + description string + cfgBuilder func() Config + expectedErr error + }{ + { + description: "defaults", + cfgBuilder: func() Config { + cfg := newTestConfig() + cfg.Distribution.Go = "go" + cfg.Replaces = append(cfg.Replaces, replaces...) + return cfg + }, + expectedErr: nil, + }, + { + description: "require otelcol", + cfgBuilder: func() Config { + cfg := newTestConfig() + cfg.Distribution.Go = "go" + cfg.Distribution.RequireOtelColModule = true + cfg.Replaces = append(cfg.Replaces, replaces...) + return cfg + }, + expectedErr: nil, + }, + { + description: "only gomod file, skip generate", + cfgBuilder: func() Config { + cfg := newTestConfig() + tempDir := t.TempDir() + err := makeModule(tempDir, goModTestFile) + require.NoError(t, err) + cfg.Distribution.OutputPath = tempDir + cfg.SkipGenerate = true + cfg.Distribution.Go = "go" + return cfg + }, + expectedErr: ErrDepNotFound, + }, + { + description: "old otel version", + cfgBuilder: func() Config { + cfg := newTestConfig() + cfg.Verbose = true + cfg.Distribution.Go = "go" + cfg.Distribution.OtelColVersion = "0.97.0" + cfg.Distribution.RequireOtelColModule = true + var err error + cfg.Exporters, err = parseModules([]Module{ + { + GoMod: "go.opentelemetry.io/collector/exporter/otlpexporter v0.97.0", + }, + }) + require.NoError(t, err) + cfg.Receivers, err = parseModules([]Module{ + { + GoMod: "go.opentelemetry.io/collector/receiver/otlpreceiver v0.97.0", + }, + }) + require.NoError(t, err) + providers, err := parseModules([]Module{ + { + GoMod: "go.opentelemetry.io/collector/confmap/provider/envprovider v0.97.0", + }, + }) + require.NoError(t, err) + cfg.Providers = &providers + return cfg + }, + expectedErr: nil, + }, + { + description: "old component version", + cfgBuilder: func() Config { + cfg := newTestConfig() + cfg.Distribution.Go = "go" + cfg.Exporters = []Module{ + { + GoMod: "go.opentelemetry.io/collector/exporter/otlpexporter v0.97.0", + }, + } + cfg.Providers = &[]Module{} + cfg.Replaces = append(cfg.Replaces, replaces...) + return cfg + }, + expectedErr: nil, + }, + { + description: "old component version without strict mode", + cfgBuilder: func() Config { + cfg := newTestConfig() + cfg.Distribution.Go = "go" + cfg.SkipStrictVersioning = true + cfg.Exporters = []Module{ + { + GoMod: "go.opentelemetry.io/collector/exporter/otlpexporter v0.97.0", + }, + } + cfg.Providers = &[]Module{} + cfg.Replaces = append(cfg.Replaces, replaces...) + return cfg + }, + expectedErr: nil, + }, + } + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + cfg := tc.cfgBuilder() + require.NoError(t, cfg.SetBackwardsCompatibility()) + require.NoError(t, cfg.Validate()) + require.NoError(t, cfg.ParseModules()) + err := GenerateAndCompile(cfg) + require.ErrorIs(t, err, tc.expectedErr) + }) + } +} + func TestSkipGenerate(t *testing.T) { - cfg := NewDefaultConfig() + cfg := newInitializedConfig(t) cfg.Distribution.OutputPath = t.TempDir() cfg.SkipGenerate = true err := Generate(cfg) @@ -50,43 +199,7 @@ func TestSkipGenerate(t *testing.T) { } func TestGenerateAndCompile(t *testing.T) { - // 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) - workspaceDir := filepath.Dir(filepath.Dir(filepath.Dir(filepath.Dir(filepath.Dir(thisFile))))) - replaces := []string{fmt.Sprintf("go.opentelemetry.io/collector => %s", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/component => %s/component", workspaceDir), - 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), - fmt.Sprintf("go.opentelemetry.io/collector/exporter/debugexporter => %s/exporter/debugexporter", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/exporter/loggingexporter => %s/exporter/loggingexporter", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/exporter/otlpexporter => %s/exporter/otlpexporter", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/exporter/otlphttpexporter => %s/exporter/otlphttpexporter", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/extension => %s/extension", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/extension/ballastextension => %s/extension/ballastextension", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/extension/zpagesextension => %s/extension/zpagesextension", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/featuregate => %s/featuregate", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/processor => %s/processor", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/processor/batchprocessor => %s/processor/batchprocessor", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/processor/memorylimiterprocessor => %s/processor/memorylimiterprocessor", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/receiver => %s/receiver", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/receiver/otlpreceiver => %s/receiver/otlpreceiver", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/otelcol => %s/otelcol", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/pdata => %s/pdata", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/semconv => %s/semconv", workspaceDir), - fmt.Sprintf("go.opentelemetry.io/collector/service => %s/service", workspaceDir), - } - + replaces := generateReplaces() testCases := []struct { testCase string cfgBuilder func(t *testing.T) Config @@ -94,7 +207,7 @@ func TestGenerateAndCompile(t *testing.T) { { testCase: "Default Configuration Compilation", cfgBuilder: func(t *testing.T) Config { - cfg := NewDefaultConfig() + cfg := newTestConfig() cfg.Distribution.OutputPath = t.TempDir() cfg.Replaces = append(cfg.Replaces, replaces...) return cfg @@ -103,7 +216,7 @@ func TestGenerateAndCompile(t *testing.T) { { testCase: "LDFlags Compilation", cfgBuilder: func(t *testing.T) Config { - cfg := NewDefaultConfig() + cfg := newTestConfig() cfg.Distribution.OutputPath = t.TempDir() cfg.Replaces = append(cfg.Replaces, replaces...) cfg.LDFlags = `-X "test.gitVersion=0743dc6c6411272b98494a9b32a63378e84c34da" -X "test.gitTag=local-testing" -X "test.goVersion=go version go1.20.7 darwin/amd64"` @@ -113,13 +226,46 @@ func TestGenerateAndCompile(t *testing.T) { { testCase: "Debug Compilation", cfgBuilder: func(t *testing.T) Config { - cfg := NewDefaultConfig() + cfg := newTestConfig() cfg.Distribution.OutputPath = t.TempDir() cfg.Replaces = append(cfg.Replaces, replaces...) + cfg.Logger = zap.NewNop() cfg.Distribution.DebugCompilation = true return cfg }, }, + { + testCase: "No providers", + cfgBuilder: func(t *testing.T) Config { + cfg := newTestConfig() + cfg.Distribution.OutputPath = t.TempDir() + cfg.Replaces = append(cfg.Replaces, replaces...) + cfg.Providers = &[]Module{} + return cfg + }, + }, + { + testCase: "Pre-confmap factories", + cfgBuilder: func(t *testing.T) Config { + cfg := newTestConfig() + cfg.Distribution.OutputPath = t.TempDir() + cfg.Replaces = append(cfg.Replaces, replaces...) + cfg.Distribution.OtelColVersion = "0.98.0" + cfg.SkipStrictVersioning = true + return cfg + }, + }, + { + testCase: "With confmap factories", + cfgBuilder: func(t *testing.T) Config { + cfg := newTestConfig() + cfg.Distribution.OutputPath = t.TempDir() + cfg.Replaces = append(cfg.Replaces, replaces...) + cfg.Distribution.OtelColVersion = "0.99.0" + cfg.SkipStrictVersioning = true + return cfg + }, + }, } for _, tt := range testCases { @@ -127,7 +273,75 @@ func TestGenerateAndCompile(t *testing.T) { cfg := tt.cfgBuilder(t) assert.NoError(t, cfg.Validate()) assert.NoError(t, cfg.SetGoPath()) + assert.NoError(t, cfg.ParseModules()) require.NoError(t, GenerateAndCompile(cfg)) }) } } + +func makeModule(dir string, fileContents []byte) error { + // if the file does not exist, try to create it + if _, err := os.Stat(dir); os.IsNotExist(err) { + if err = os.Mkdir(dir, 0750); err != nil { + return fmt.Errorf("failed to create output path: %w", err) + } + } else if err != nil { + return fmt.Errorf("failed to create output path: %w", err) + } + + err := os.WriteFile(filepath.Clean(filepath.Join(dir, "go.mod")), fileContents, 0600) + if err != nil { + return fmt.Errorf("failed to write go.mod file: %w", err) + } + return nil +} + +func generateReplaces() []string { + // 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) + workspaceDir := filepath.Dir(filepath.Dir(filepath.Dir(filepath.Dir(filepath.Dir(thisFile))))) + return []string{fmt.Sprintf("go.opentelemetry.io/collector => %s", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/component => %s/component", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/config/configauth => %s/config/configauth", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/config/configcompression => %s/config/configcompression", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/config/configgrpc => %s/config/configgrpc", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/config/confignet => %s/config/confignet", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/config/configopaque => %s/config/configopaque", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/config/configretry => %s/config/configretry", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/config/configtelemetry => %s/config/configtelemetry", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/config/configtls => %s/config/configtls", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/config/internal => %s/config/internal", 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), + fmt.Sprintf("go.opentelemetry.io/collector/exporter/debugexporter => %s/exporter/debugexporter", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/exporter/loggingexporter => %s/exporter/loggingexporter", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/exporter/nopexporter => %s/exporter/nopexporter", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/exporter/otlpexporter => %s/exporter/otlpexporter", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/exporter/otlphttpexporter => %s/exporter/otlphttpexporter", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/extension => %s/extension", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/extension/auth => %s/extension/auth", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/extension/ballastextension => %s/extension/ballastextension", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/extension/zpagesextension => %s/extension/zpagesextension", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/featuregate => %s/featuregate", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/processor => %s/processor", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/processor/batchprocessor => %s/processor/batchprocessor", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/processor/memorylimiterprocessor => %s/processor/memorylimiterprocessor", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/receiver => %s/receiver", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/receiver/nopreceiver => %s/receiver/nopreceiver", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/receiver/otlpreceiver => %s/receiver/otlpreceiver", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/otelcol => %s/otelcol", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/pdata => %s/pdata", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/pdata/testdata => %s/pdata/testdata", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/semconv => %s/semconv", workspaceDir), + fmt.Sprintf("go.opentelemetry.io/collector/service => %s/service", workspaceDir), + } +} diff --git a/cmd/builder/internal/builder/templates.go b/cmd/builder/internal/builder/templates.go index fba3a9fc5ee..a916508d049 100644 --- a/cmd/builder/internal/builder/templates.go +++ b/cmd/builder/internal/builder/templates.go @@ -13,10 +13,6 @@ var ( componentsBytes []byte componentsTemplate = parseTemplate("components.go", componentsBytes) - //go:embed templates/components_test.go.tmpl - componentsTestBytes []byte - componentsTestTemplate = parseTemplate("components_test.go", componentsTestBytes) - //go:embed templates/main.go.tmpl mainBytes []byte mainTemplate = parseTemplate("main.go", mainBytes) diff --git a/cmd/builder/internal/builder/templates/components_test.go.tmpl b/cmd/builder/internal/builder/templates/components_test.go.tmpl deleted file mode 100644 index aaf9ee8b965..00000000000 --- a/cmd/builder/internal/builder/templates/components_test.go.tmpl +++ /dev/null @@ -1,39 +0,0 @@ -// Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT. - -package main - -import ( - "testing" - "github.com/stretchr/testify/assert" - "go.opentelemetry.io/collector/component/componenttest" -) - -func TestValidateConfigs(t *testing.T) { - factories, err := components() - assert.NoError(t, err) - - for k, factory := range factories.Receivers { - assert.Equal(t, k, factory.Type()) - assert.NoError(t, componenttest.CheckConfigStruct(factory.CreateDefaultConfig())) - } - - for k, factory := range factories.Processors { - assert.Equal(t, k, factory.Type()) - assert.NoError(t, componenttest.CheckConfigStruct(factory.CreateDefaultConfig())) - } - - for k, factory := range factories.Exporters { - assert.Equal(t, k, factory.Type()) - assert.NoError(t, componenttest.CheckConfigStruct(factory.CreateDefaultConfig())) - } - - for k, factory := range factories.Connectors { - assert.Equal(t, k, factory.Type()) - assert.NoError(t, componenttest.CheckConfigStruct(factory.CreateDefaultConfig())) - } - - for k, factory := range factories.Extensions { - assert.Equal(t, k, factory.Type()) - assert.NoError(t, componenttest.CheckConfigStruct(factory.CreateDefaultConfig())) - } -} diff --git a/cmd/builder/internal/builder/templates/go.mod.tmpl b/cmd/builder/internal/builder/templates/go.mod.tmpl index f70306ae95b..ad6fd3f78f6 100644 --- a/cmd/builder/internal/builder/templates/go.mod.tmpl +++ b/cmd/builder/internal/builder/templates/go.mod.tmpl @@ -5,6 +5,12 @@ module {{.Distribution.Module}} go 1.21 require ( + {{if .Distribution.SupportsConfmapFactories -}} + go.opentelemetry.io/collector/confmap/converter/expandconverter v{{.Distribution.OtelColVersion}} + {{- range .Providers}} + {{if .GoMod}}{{.GoMod}}{{end}} + {{- end}} + {{- end}} {{- range .Connectors}} {{if .GoMod}}{{.GoMod}}{{end}} {{- end}} diff --git a/cmd/builder/internal/builder/templates/main.go.tmpl b/cmd/builder/internal/builder/templates/main.go.tmpl index 64a81295bcb..f9964c5d5ec 100644 --- a/cmd/builder/internal/builder/templates/main.go.tmpl +++ b/cmd/builder/internal/builder/templates/main.go.tmpl @@ -7,6 +7,13 @@ import ( "log" "go.opentelemetry.io/collector/component" + {{- if .Distribution.SupportsConfmapFactories}} + "go.opentelemetry.io/collector/confmap" + "go.opentelemetry.io/collector/confmap/converter/expandconverter" + {{- range .Providers}} + {{.Name}} "{{.Import}}" + {{- end}} + {{- end}} "go.opentelemetry.io/collector/otelcol" ) @@ -17,7 +24,26 @@ func main() { Version: "{{ .Distribution.Version }}", } - if err := run(otelcol.CollectorSettings{BuildInfo: info, Factories: components}); err != nil { + set := otelcol.CollectorSettings{ + BuildInfo: info, + Factories: components, + {{- if .Distribution.SupportsConfmapFactories}} + ConfigProviderSettings: otelcol.ConfigProviderSettings{ + ResolverSettings: confmap.ResolverSettings{ + ProviderFactories: []confmap.ProviderFactory{ + {{- range .Providers}} + {{.Name}}.NewFactory(), + {{- end}} + }, + ConverterFactories: []confmap.ConverterFactory{ + expandconverter.NewFactory(), + }, + }, + }, + {{- end}} + } + + if err := run(set); err != nil { log.Fatal(err) } } diff --git a/cmd/builder/internal/command.go b/cmd/builder/internal/command.go index 34d1b0b13b9..b6cc41a9ba5 100644 --- a/cmd/builder/internal/command.go +++ b/cmd/builder/internal/command.go @@ -23,6 +23,7 @@ const ( skipGenerateFlag = "skip-generate" skipCompilationFlag = "skip-compilation" skipGetModulesFlag = "skip-get-modules" + skipStrictVersioningFlag = "skip-strict-versioning" ldflagsFlag = "ldflags" distributionNameFlag = "name" distributionDescriptionFlag = "description" @@ -65,7 +66,7 @@ configuration is provided, ocb will generate a default Collector. return fmt.Errorf("go not found: %w", err) } - if err := cfg.SetRequireOtelColModule(); err != nil { + if err := cfg.SetBackwardsCompatibility(); err != nil { return fmt.Errorf("unable to compare otelcol version: %w", err) } @@ -83,6 +84,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.SkipStrictVersioning, skipStrictVersioningFlag, false, "Whether builder should skip strictly checking the calculated versions following dependency resolution") 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") @@ -168,6 +170,7 @@ func applyCfgFromFile(flags *flag.FlagSet, cfgFromFile builder.Config) { cfg.Receivers = cfgFromFile.Receivers cfg.Processors = cfgFromFile.Processors cfg.Connectors = cfgFromFile.Connectors + cfg.Providers = cfgFromFile.Providers cfg.Replaces = cfgFromFile.Replaces cfg.Excludes = cfgFromFile.Excludes @@ -180,6 +183,9 @@ func applyCfgFromFile(flags *flag.FlagSet, cfgFromFile builder.Config) { if !flags.Changed(skipGetModulesFlag) && cfgFromFile.SkipGetModules { cfg.SkipGetModules = cfgFromFile.SkipGetModules } + if !flags.Changed(skipStrictVersioningFlag) && cfgFromFile.SkipStrictVersioning { + cfg.SkipStrictVersioning = cfgFromFile.SkipStrictVersioning + } if !flags.Changed(distributionNameFlag) && cfgFromFile.Distribution.Name != "" { cfg.Distribution.Name = cfgFromFile.Distribution.Name } diff --git a/cmd/builder/internal/command_test.go b/cmd/builder/internal/command_test.go index 78ad0d740d2..27ae655893b 100644 --- a/cmd/builder/internal/command_test.go +++ b/cmd/builder/internal/command_test.go @@ -178,6 +178,26 @@ func Test_applyCfgFromFile(t *testing.T) { }, wantErr: false, }, + { + name: "Skip strict versioning true", + args: args{ + flags: flag.NewFlagSet("version=1.0.0", 1), + cfgFromFile: builder.Config{ + Logger: zap.NewNop(), + SkipCompilation: true, + SkipStrictVersioning: true, + Distribution: testDistribution, + }, + }, + want: builder.Config{ + Logger: zap.NewNop(), + SkipCompilation: true, + SkipGetModules: true, + SkipStrictVersioning: true, + Distribution: testDistribution, + }, + wantErr: false, + }, { name: "Skip generate false", args: args{ @@ -191,11 +211,12 @@ func Test_applyCfgFromFile(t *testing.T) { }, }, want: builder.Config{ - Logger: zap.NewNop(), - SkipGenerate: false, - SkipCompilation: true, - SkipGetModules: true, - Distribution: testDistribution, + Logger: zap.NewNop(), + SkipGenerate: false, + SkipCompilation: true, + SkipGetModules: true, + SkipStrictVersioning: true, + Distribution: testDistribution, }, wantErr: false, }, @@ -212,11 +233,12 @@ func Test_applyCfgFromFile(t *testing.T) { }, }, want: builder.Config{ - Logger: zap.NewNop(), - SkipGenerate: true, - SkipCompilation: true, - SkipGetModules: true, - Distribution: testDistribution, + Logger: zap.NewNop(), + SkipGenerate: true, + SkipCompilation: true, + SkipGetModules: true, + SkipStrictVersioning: true, + Distribution: testDistribution, }, wantErr: false, }, @@ -228,6 +250,7 @@ func Test_applyCfgFromFile(t *testing.T) { assert.Equal(t, tt.want.SkipGenerate, cfg.SkipGenerate) assert.Equal(t, tt.want.SkipCompilation, cfg.SkipCompilation) assert.Equal(t, tt.want.SkipGetModules, cfg.SkipGetModules) + assert.Equal(t, tt.want.SkipStrictVersioning, cfg.SkipStrictVersioning) assert.Equal(t, tt.want.Excludes, cfg.Excludes) assert.Equal(t, tt.want.Exporters, cfg.Exporters) assert.Equal(t, tt.want.Receivers, cfg.Receivers) diff --git a/cmd/builder/internal/config/default.yaml b/cmd/builder/internal/config/default.yaml index 1aee339e91b..ac86def33ff 100644 --- a/cmd/builder/internal/config/default.yaml +++ b/cmd/builder/internal/config/default.yaml @@ -2,23 +2,32 @@ dist: module: go.opentelemetry.io/collector/cmd/otelcorecol name: otelcorecol description: Local OpenTelemetry Collector binary, testing only. - version: 0.96.0-dev - otelcol_version: 0.96.0 + version: 0.100.0-dev + otelcol_version: 0.100.0 receivers: - - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.96.0 + - gomod: go.opentelemetry.io/collector/receiver/nopreceiver v0.100.0 + - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.100.0 exporters: - - 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 + - gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.100.0 + - gomod: go.opentelemetry.io/collector/exporter/loggingexporter v0.100.0 + - gomod: go.opentelemetry.io/collector/exporter/nopexporter v0.100.0 + - gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.100.0 + - gomod: go.opentelemetry.io/collector/exporter/otlphttpexporter v0.100.0 extensions: - - 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 + - gomod: go.opentelemetry.io/collector/extension/ballastextension v0.100.0 + - gomod: go.opentelemetry.io/collector/extension/memorylimiterextension v0.100.0 + - gomod: go.opentelemetry.io/collector/extension/zpagesextension v0.100.0 processors: - - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.96.0 - - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.96.0 + - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.100.0 + - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.100.0 connectors: - - gomod: go.opentelemetry.io/collector/connector/forwardconnector v0.96.0 + - gomod: go.opentelemetry.io/collector/connector/forwardconnector v0.100.0 + +providers: + - gomod: go.opentelemetry.io/collector/confmap/provider/envprovider v0.100.0 + - gomod: go.opentelemetry.io/collector/confmap/provider/fileprovider v0.100.0 + - gomod: go.opentelemetry.io/collector/confmap/provider/httpprovider v0.100.0 + - gomod: go.opentelemetry.io/collector/confmap/provider/httpsprovider v0.100.0 + - gomod: go.opentelemetry.io/collector/confmap/provider/yamlprovider v0.100.0 diff --git a/cmd/builder/test/core.builder.yaml b/cmd/builder/test/core.builder.yaml index 0f4fe8e9df4..7baedadd974 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.94.0 + otelcol_version: 0.100.0 extensions: - import: go.opentelemetry.io/collector/extension/zpagesextension - gomod: go.opentelemetry.io/collector v0.94.0 + gomod: go.opentelemetry.io/collector v0.100.0 path: ${WORKSPACE_DIR} receivers: - import: go.opentelemetry.io/collector/receiver/otlpreceiver - gomod: go.opentelemetry.io/collector v0.94.0 + gomod: go.opentelemetry.io/collector v0.100.0 path: ${WORKSPACE_DIR} exporters: - import: go.opentelemetry.io/collector/exporter/debugexporter - gomod: go.opentelemetry.io/collector v0.94.0 + gomod: go.opentelemetry.io/collector v0.100.0 path: ${WORKSPACE_DIR} replaces: @@ -48,6 +48,7 @@ replaces: - go.opentelemetry.io/collector/featuregate => ${WORKSPACE_DIR}/featuregate - go.opentelemetry.io/collector/otelcol => ${WORKSPACE_DIR}/otelcol - go.opentelemetry.io/collector/pdata => ${WORKSPACE_DIR}/pdata + - go.opentelemetry.io/collector/pdata/testdata => ${WORKSPACE_DIR}/pdata/testdata - go.opentelemetry.io/collector/processor => ${WORKSPACE_DIR}/processor - go.opentelemetry.io/collector/receiver => ${WORKSPACE_DIR}/receiver - go.opentelemetry.io/collector/receiver/otlpreceiver => ${WORKSPACE_DIR}/receiver/otlpreceiver diff --git a/cmd/mdatagen/doc.go b/cmd/mdatagen/doc.go deleted file mode 100644 index 8f1fc6a7176..00000000000 --- a/cmd/mdatagen/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -// 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/embeded_templates_test.go b/cmd/mdatagen/embeded_templates_test.go index 1f4c4684e4e..3bba543b139 100644 --- a/cmd/mdatagen/embeded_templates_test.go +++ b/cmd/mdatagen/embeded_templates_test.go @@ -28,8 +28,11 @@ func TestEnsureTemplatesLoaded(t *testing.T) { path.Join(rootDir, "resource_test.go.tmpl"): {}, path.Join(rootDir, "config.go.tmpl"): {}, path.Join(rootDir, "config_test.go.tmpl"): {}, + path.Join(rootDir, "package_test.go.tmpl"): {}, path.Join(rootDir, "readme.md.tmpl"): {}, path.Join(rootDir, "status.go.tmpl"): {}, + path.Join(rootDir, "telemetry.go.tmpl"): {}, + path.Join(rootDir, "telemetry_test.go.tmpl"): {}, path.Join(rootDir, "testdata", "config.yaml.tmpl"): {}, } count = 0 diff --git a/cmd/mdatagen/go.mod b/cmd/mdatagen/go.mod index e654d0832c7..8512c0f3a0d 100644 --- a/cmd/mdatagen/go.mod +++ b/cmd/mdatagen/go.mod @@ -4,16 +4,18 @@ 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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/confmap/provider/fileprovider v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/filter v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/collector/receiver v0.100.0 + go.opentelemetry.io/collector/semconv v0.100.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.0 + go.uber.org/goleak v1.3.0 go.uber.org/zap v1.27.0 golang.org/x/text v0.14.0 ) @@ -26,31 +28,31 @@ require ( 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/google/uuid 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.1 // 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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 + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -60,8 +62,12 @@ replace go.opentelemetry.io/collector/confmap => ../../confmap replace go.opentelemetry.io/collector/confmap/provider/fileprovider => ../../confmap/provider/fileprovider +replace go.opentelemetry.io/collector/filter => ../../filter + replace go.opentelemetry.io/collector/pdata => ../../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata + replace go.opentelemetry.io/collector/receiver => ../../receiver replace go.opentelemetry.io/collector/semconv => ../../semconv diff --git a/cmd/mdatagen/go.sum b/cmd/mdatagen/go.sum index 06616cda85d..4394e616fe3 100644 --- a/cmd/mdatagen/go.sum +++ b/cmd/mdatagen/go.sum @@ -14,13 +14,11 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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/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= @@ -29,8 +27,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -48,32 +46,32 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.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.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -89,16 +87,16 @@ 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -111,14 +109,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/cmd/mdatagen/internal/metadata/generated_status.go b/cmd/mdatagen/internal/metadata/generated_status.go deleted file mode 100644 index 7e332e5ba4a..00000000000 --- a/cmd/mdatagen/internal/metadata/generated_status.go +++ /dev/null @@ -1,29 +0,0 @@ -// 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 deleted file mode 100644 index 8283dc2dd70..00000000000 --- a/cmd/mdatagen/internal/metadata/testdata/config.yaml +++ /dev/null @@ -1,55 +0,0 @@ -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/internal/samplereceiver/README.md b/cmd/mdatagen/internal/samplereceiver/README.md new file mode 100644 index 00000000000..8444ce2e8ec --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/README.md @@ -0,0 +1,22 @@ +# Sample Receiver +This receiver is used for testing purposes to check the output of mdatagen. + +| Status | | +| ------------- |-----------| +| Stability | [development]: logs | +| | [beta]: traces | +| | [stable]: metrics | +| Unsupported Platforms | freebsd, illumos | +| Distributions | [] | +| Warnings | [Any additional information that should be brought to the consumer's attention](#warnings) | +| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Areceiver%2Fsample%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Areceiver%2Fsample) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Areceiver%2Fsample%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Areceiver%2Fsample) | +| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@dmitryax](https://www.github.com/dmitryax) | + +[development]: https://github.com/open-telemetry/opentelemetry-collector#development +[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta +[stable]: https://github.com/open-telemetry/opentelemetry-collector#stable + + +## Warnings + +This is where warnings are described. diff --git a/cmd/mdatagen/internal/samplereceiver/doc.go b/cmd/mdatagen/internal/samplereceiver/doc.go new file mode 100644 index 00000000000..7b7505667ae --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/doc.go @@ -0,0 +1,10 @@ +// 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.yaml + +// Deprecated: This package is moving to https://github.com/open-telemetry/opentelemetry-collector and will eventually be removed. +// Please see https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/30497 +// This is a sample receiver package used to showcase how mdatagen is applied. +package samplereceiver // import "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplereceiver" diff --git a/cmd/mdatagen/documentation.md b/cmd/mdatagen/internal/samplereceiver/documentation.md similarity index 81% rename from cmd/mdatagen/documentation.md rename to cmd/mdatagen/internal/samplereceiver/documentation.md index 1955e081535..60a79a7941a 100644 --- a/cmd/mdatagen/documentation.md +++ b/cmd/mdatagen/internal/samplereceiver/documentation.md @@ -1,6 +1,6 @@ [comment]: <> (Code generated by mdatagen. DO NOT EDIT.) -# file +# sample ## Default Metrics @@ -42,6 +42,24 @@ The metric will be will be removed soon. | ---- | ----------- | ---------- | ----------------------- | --------- | | s | Sum | Double | Delta | false | +### metric.input_type + +Monotonic cumulative sum int metric with string input_type enabled by default. + +| 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 | + ## Optional Metrics The following metrics are not emitted by default. Each of them can be enabled by applying the following configuration: diff --git a/cmd/mdatagen/internal/samplereceiver/factory.go b/cmd/mdatagen/internal/samplereceiver/factory.go new file mode 100644 index 00000000000..89769521f74 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/factory.go @@ -0,0 +1,42 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package samplereceiver // import "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplereceiver" + +import ( + "context" + + "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplereceiver/internal/metadata" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/receiver" +) + +// NewFactory returns a receiver.Factory for sample receiver. +func NewFactory() receiver.Factory { + return receiver.NewFactory( + metadata.Type, + func() component.Config { return &struct{}{} }, + receiver.WithTraces(createTraces, metadata.TracesStability), + receiver.WithMetrics(createMetrics, metadata.MetricsStability), + receiver.WithLogs(createLogs, metadata.LogsStability)) +} + +func createTraces(context.Context, receiver.CreateSettings, component.Config, consumer.Traces) (receiver.Traces, error) { + return nopInstance, nil +} + +func createMetrics(context.Context, receiver.CreateSettings, component.Config, consumer.Metrics) (receiver.Metrics, error) { + return nopInstance, nil +} + +func createLogs(context.Context, receiver.CreateSettings, component.Config, consumer.Logs) (receiver.Logs, error) { + return nopInstance, nil +} + +var nopInstance = &nopReceiver{} + +type nopReceiver struct { + component.StartFunc + component.ShutdownFunc +} diff --git a/cmd/mdatagen/internal/samplereceiver/generated_component_test.go b/cmd/mdatagen/internal/samplereceiver/generated_component_test.go new file mode 100644 index 00000000000..af315d20a85 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/generated_component_test.go @@ -0,0 +1,85 @@ +// Code generated by mdatagen. DO NOT EDIT. +//go:build !freebsd && !illumos + +package samplereceiver + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/receiver" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "sample", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +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) + }{ + + { + name: "logs", + createFn: func(ctx context.Context, set receiver.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsReceiver(ctx, set, cfg, consumertest.NewNop()) + }, + }, + + { + name: "metrics", + createFn: func(ctx context.Context, set receiver.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsReceiver(ctx, set, cfg, consumertest.NewNop()) + }, + }, + + { + name: "traces", + createFn: func(ctx context.Context, set receiver.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesReceiver(ctx, set, cfg, consumertest.NewNop()) + }, + }, + } + + 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) { + 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())) + }) + } +} diff --git a/exporter/exportertest/package_test.go b/cmd/mdatagen/internal/samplereceiver/generated_package_test.go similarity index 51% rename from exporter/exportertest/package_test.go rename to cmd/mdatagen/internal/samplereceiver/generated_package_test.go index 8fa8a72b85f..ba2afcd94ca 100644 --- a/exporter/exportertest/package_test.go +++ b/cmd/mdatagen/internal/samplereceiver/generated_package_test.go @@ -1,7 +1,6 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 +// Code generated by mdatagen. DO NOT EDIT. -package exportertest +package samplereceiver import ( "testing" diff --git a/cmd/mdatagen/internal/metadata/generated_config.go b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_config.go similarity index 78% rename from cmd/mdatagen/internal/metadata/generated_config.go rename to cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_config.go index 92937f48dbf..05ddc47ac40 100644 --- a/cmd/mdatagen/internal/metadata/generated_config.go +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_config.go @@ -2,7 +2,10 @@ package metadata -import "go.opentelemetry.io/collector/confmap" +import ( + "go.opentelemetry.io/collector/confmap" + "go.opentelemetry.io/collector/filter" +) // MetricConfig provides common config for a particular metric. type MetricConfig struct { @@ -23,10 +26,11 @@ func (ms *MetricConfig) Unmarshal(parser *confmap.Conf) error { return nil } -// MetricsConfig provides config for file metrics. +// MetricsConfig provides config for sample metrics. type MetricsConfig struct { DefaultMetric MetricConfig `mapstructure:"default.metric"` DefaultMetricToBeRemoved MetricConfig `mapstructure:"default.metric.to_be_removed"` + MetricInputType MetricConfig `mapstructure:"metric.input_type"` OptionalMetric MetricConfig `mapstructure:"optional.metric"` OptionalMetricEmptyUnit MetricConfig `mapstructure:"optional.metric.empty_unit"` } @@ -39,6 +43,9 @@ func DefaultMetricsConfig() MetricsConfig { DefaultMetricToBeRemoved: MetricConfig{ Enabled: true, }, + MetricInputType: MetricConfig{ + Enabled: true, + }, OptionalMetric: MetricConfig{ Enabled: false, }, @@ -51,6 +58,13 @@ func DefaultMetricsConfig() MetricsConfig { // ResourceAttributeConfig provides common config for a particular resource attribute. type ResourceAttributeConfig struct { Enabled bool `mapstructure:"enabled"` + // Experimental: MetricsInclude defines a list of filters for attribute values. + // If the list is not empty, only metrics with matching resource attribute values will be emitted. + MetricsInclude []filter.Config `mapstructure:"metrics_include"` + // Experimental: MetricsExclude defines a list of filters for attribute values. + // If the list is not empty, metrics with matching resource attribute values will not be emitted. + // MetricsInclude has higher priority than MetricsExclude. + MetricsExclude []filter.Config `mapstructure:"metrics_exclude"` enabledSetByUser bool } @@ -67,7 +81,7 @@ func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error { return nil } -// ResourceAttributesConfig provides config for file resource attributes. +// ResourceAttributesConfig provides config for sample resource attributes. type ResourceAttributesConfig struct { MapResourceAttr ResourceAttributeConfig `mapstructure:"map.resource.attr"` OptionalResourceAttr ResourceAttributeConfig `mapstructure:"optional.resource.attr"` @@ -108,7 +122,7 @@ func DefaultResourceAttributesConfig() ResourceAttributesConfig { } } -// MetricsBuilderConfig is a configuration for file metrics builder. +// MetricsBuilderConfig is a configuration for sample metrics builder. type MetricsBuilderConfig struct { Metrics MetricsConfig `mapstructure:"metrics"` ResourceAttributes ResourceAttributesConfig `mapstructure:"resource_attributes"` diff --git a/cmd/mdatagen/internal/metadata/generated_config_test.go b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_config_test.go similarity index 97% rename from cmd/mdatagen/internal/metadata/generated_config_test.go rename to cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_config_test.go index bfb90940386..0f581b137f7 100644 --- a/cmd/mdatagen/internal/metadata/generated_config_test.go +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_config_test.go @@ -29,6 +29,7 @@ func TestMetricsBuilderConfig(t *testing.T) { Metrics: MetricsConfig{ DefaultMetric: MetricConfig{Enabled: true}, DefaultMetricToBeRemoved: MetricConfig{Enabled: true}, + MetricInputType: MetricConfig{Enabled: true}, OptionalMetric: MetricConfig{Enabled: true}, OptionalMetricEmptyUnit: MetricConfig{Enabled: true}, }, @@ -50,6 +51,7 @@ func TestMetricsBuilderConfig(t *testing.T) { Metrics: MetricsConfig{ DefaultMetric: MetricConfig{Enabled: false}, DefaultMetricToBeRemoved: MetricConfig{Enabled: false}, + MetricInputType: MetricConfig{Enabled: false}, OptionalMetric: MetricConfig{Enabled: false}, OptionalMetricEmptyUnit: MetricConfig{Enabled: false}, }, diff --git a/cmd/mdatagen/internal/metadata/generated_metrics.go b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_metrics.go similarity index 69% rename from cmd/mdatagen/internal/metadata/generated_metrics.go rename to cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_metrics.go index a6d8a7e4169..344599e2c40 100644 --- a/cmd/mdatagen/internal/metadata/generated_metrics.go +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_metrics.go @@ -3,9 +3,12 @@ package metadata import ( + "fmt" + "strconv" "time" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/filter" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/receiver" @@ -150,6 +153,63 @@ func newMetricDefaultMetricToBeRemoved(cfg MetricConfig) metricDefaultMetricToBe return m } +type metricMetricInputType 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 metric.input_type metric with initial data. +func (m *metricMetricInputType) init() { + m.data.SetName("metric.input_type") + m.data.SetDescription("Monotonic cumulative sum int metric with string input_type 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 *metricMetricInputType) 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 *metricMetricInputType) 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 *metricMetricInputType) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricMetricInputType(cfg MetricConfig) metricMetricInputType { + m := metricMetricInputType{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. @@ -262,8 +322,11 @@ type MetricsBuilder struct { metricsCapacity int // maximum observed number of metrics per resource. metricsBuffer pmetric.Metrics // accumulates metrics data before emitting. buildInfo component.BuildInfo // contains version information. + resourceAttributeIncludeFilter map[string]filter.Filter + resourceAttributeExcludeFilter map[string]filter.Filter metricDefaultMetric metricDefaultMetric metricDefaultMetricToBeRemoved metricDefaultMetricToBeRemoved + metricMetricInputType metricMetricInputType metricOptionalMetric metricOptionalMetric metricOptionalMetricEmptyUnit metricOptionalMetricEmptyUnit } @@ -294,7 +357,7 @@ func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.CreateSetting 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 { + if mbc.ResourceAttributes.StringResourceAttrRemoveWarning.enabledSetByUser || mbc.ResourceAttributes.StringResourceAttrRemoveWarning.MetricsInclude != nil || mbc.ResourceAttributes.StringResourceAttrRemoveWarning.MetricsExclude != nil { 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 { @@ -307,9 +370,61 @@ func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.CreateSetting buildInfo: settings.BuildInfo, metricDefaultMetric: newMetricDefaultMetric(mbc.Metrics.DefaultMetric), metricDefaultMetricToBeRemoved: newMetricDefaultMetricToBeRemoved(mbc.Metrics.DefaultMetricToBeRemoved), + metricMetricInputType: newMetricMetricInputType(mbc.Metrics.MetricInputType), metricOptionalMetric: newMetricOptionalMetric(mbc.Metrics.OptionalMetric), metricOptionalMetricEmptyUnit: newMetricOptionalMetricEmptyUnit(mbc.Metrics.OptionalMetricEmptyUnit), + resourceAttributeIncludeFilter: make(map[string]filter.Filter), + resourceAttributeExcludeFilter: make(map[string]filter.Filter), + } + if mbc.ResourceAttributes.MapResourceAttr.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["map.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.MapResourceAttr.MetricsInclude) + } + if mbc.ResourceAttributes.MapResourceAttr.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["map.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.MapResourceAttr.MetricsExclude) + } + if mbc.ResourceAttributes.OptionalResourceAttr.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["optional.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.OptionalResourceAttr.MetricsInclude) + } + if mbc.ResourceAttributes.OptionalResourceAttr.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["optional.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.OptionalResourceAttr.MetricsExclude) + } + if mbc.ResourceAttributes.SliceResourceAttr.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["slice.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.SliceResourceAttr.MetricsInclude) + } + if mbc.ResourceAttributes.SliceResourceAttr.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["slice.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.SliceResourceAttr.MetricsExclude) + } + if mbc.ResourceAttributes.StringEnumResourceAttr.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["string.enum.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.StringEnumResourceAttr.MetricsInclude) } + if mbc.ResourceAttributes.StringEnumResourceAttr.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["string.enum.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.StringEnumResourceAttr.MetricsExclude) + } + if mbc.ResourceAttributes.StringResourceAttr.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["string.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttr.MetricsInclude) + } + if mbc.ResourceAttributes.StringResourceAttr.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["string.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttr.MetricsExclude) + } + if mbc.ResourceAttributes.StringResourceAttrDisableWarning.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["string.resource.attr_disable_warning"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttrDisableWarning.MetricsInclude) + } + if mbc.ResourceAttributes.StringResourceAttrDisableWarning.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["string.resource.attr_disable_warning"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttrDisableWarning.MetricsExclude) + } + if mbc.ResourceAttributes.StringResourceAttrRemoveWarning.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["string.resource.attr_remove_warning"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttrRemoveWarning.MetricsInclude) + } + if mbc.ResourceAttributes.StringResourceAttrRemoveWarning.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["string.resource.attr_remove_warning"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttrRemoveWarning.MetricsExclude) + } + if mbc.ResourceAttributes.StringResourceAttrToBeRemoved.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["string.resource.attr_to_be_removed"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttrToBeRemoved.MetricsInclude) + } + if mbc.ResourceAttributes.StringResourceAttrToBeRemoved.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["string.resource.attr_to_be_removed"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttrToBeRemoved.MetricsExclude) + } + for _, op := range options { op(mb) } @@ -368,17 +483,29 @@ 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().SetName("go.opentelemetry.io/collector/internal/receiver/samplereceiver") ils.Scope().SetVersion(mb.buildInfo.Version) ils.Metrics().EnsureCapacity(mb.metricsCapacity) mb.metricDefaultMetric.emit(ils.Metrics()) mb.metricDefaultMetricToBeRemoved.emit(ils.Metrics()) + mb.metricMetricInputType.emit(ils.Metrics()) mb.metricOptionalMetric.emit(ils.Metrics()) mb.metricOptionalMetricEmptyUnit.emit(ils.Metrics()) for _, op := range rmo { op(rm) } + for attr, filter := range mb.resourceAttributeIncludeFilter { + if val, ok := rm.Resource().Attributes().Get(attr); ok && !filter.Matches(val.AsString()) { + return + } + } + for attr, filter := range mb.resourceAttributeExcludeFilter { + if val, ok := rm.Resource().Attributes().Get(attr); ok && filter.Matches(val.AsString()) { + return + } + } + if ils.Metrics().Len() > 0 { mb.updateCapacity(rm) rm.MoveTo(mb.metricsBuffer.ResourceMetrics().AppendEmpty()) @@ -405,6 +532,16 @@ func (mb *MetricsBuilder) RecordDefaultMetricToBeRemovedDataPoint(ts pcommon.Tim mb.metricDefaultMetricToBeRemoved.recordDataPoint(mb.startTime, ts, val) } +// RecordMetricInputTypeDataPoint adds a data point to metric.input_type metric. +func (mb *MetricsBuilder) RecordMetricInputTypeDataPoint(ts pcommon.Timestamp, inputVal string, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue AttributeEnumAttr, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any) error { + val, err := strconv.ParseInt(inputVal, 10, 64) + if err != nil { + return fmt.Errorf("failed to parse int64 for MetricInputType, value was %s: %w", inputVal, err) + } + mb.metricMetricInputType.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, overriddenIntAttrAttributeValue, enumAttrAttributeValue.String(), sliceAttrAttributeValue, mapAttrAttributeValue) + return nil +} + // 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) diff --git a/cmd/mdatagen/internal/metadata/generated_metrics_test.go b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_metrics_test.go similarity index 74% rename from cmd/mdatagen/internal/metadata/generated_metrics_test.go rename to cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_metrics_test.go index 4860ac1ba2b..b6214e5d894 100644 --- a/cmd/mdatagen/internal/metadata/generated_metrics_test.go +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_metrics_test.go @@ -14,30 +14,43 @@ import ( "go.opentelemetry.io/collector/receiver/receivertest" ) -type testConfigCollection int +type testDataSet int const ( - testSetDefault testConfigCollection = iota - testSetAll - testSetNone + testDataSetDefault testDataSet = iota + testDataSetAll + testDataSetNone ) func TestMetricsBuilder(t *testing.T) { tests := []struct { - name string - configSet testConfigCollection + name string + metricsSet testDataSet + resAttrsSet testDataSet + expectEmpty bool }{ { - name: "default", - configSet: testSetDefault, + name: "default", }, { - name: "all_set", - configSet: testSetAll, + name: "all_set", + metricsSet: testDataSetAll, + resAttrsSet: testDataSetAll, }, { - name: "none_set", - configSet: testSetNone, + name: "none_set", + metricsSet: testDataSetNone, + resAttrsSet: testDataSetNone, + expectEmpty: true, + }, + { + name: "filter_set_include", + resAttrsSet: testDataSetAll, + }, + { + name: "filter_set_exclude", + resAttrsSet: testDataSetAll, + expectEmpty: true, }, } for _, test := range tests { @@ -50,31 +63,31 @@ func TestMetricsBuilder(t *testing.T) { mb := NewMetricsBuilder(loadMetricsBuilderConfig(t, test.name), settings, WithStartTime(start)) expectedWarnings := 0 - if test.configSet == testSetDefault { + if test.metricsSet == testDataSetDefault { 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 { + if test.metricsSet == testDataSetDefault || test.metricsSet == testDataSetAll { 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 { + if test.metricsSet == testDataSetAll || test.metricsSet == testDataSetNone { 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 { + if test.metricsSet == testDataSetAll || test.metricsSet == testDataSetNone { 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 { + if test.resAttrsSet == testDataSetDefault { 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 { + if test.resAttrsSet == testDataSetAll || test.resAttrsSet == testDataSetNone { 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 { + if test.resAttrsSet == testDataSetDefault || test.resAttrsSet == testDataSetAll { 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++ } @@ -92,6 +105,10 @@ func TestMetricsBuilder(t *testing.T) { allMetricsCount++ mb.RecordDefaultMetricToBeRemovedDataPoint(ts, 1) + defaultMetricsCount++ + allMetricsCount++ + mb.RecordMetricInputTypeDataPoint(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"}) + allMetricsCount++ mb.RecordOptionalMetricDataPoint(ts, 1, "string_attr-val", true) @@ -110,7 +127,7 @@ func TestMetricsBuilder(t *testing.T) { res := rb.Emit() metrics := mb.Emit(WithResource(res)) - if test.configSet == testSetNone { + if test.expectEmpty { assert.Equal(t, 0, metrics.ResourceMetrics().Len()) return } @@ -120,10 +137,10 @@ func TestMetricsBuilder(t *testing.T) { assert.Equal(t, res, rm.Resource()) assert.Equal(t, 1, rm.ScopeMetrics().Len()) ms := rm.ScopeMetrics().At(0).Metrics() - if test.configSet == testSetDefault { + if test.metricsSet == testDataSetDefault { assert.Equal(t, defaultMetricsCount, ms.Len()) } - if test.configSet == testSetAll { + if test.metricsSet == testDataSetAll { assert.Equal(t, allMetricsCount, ms.Len()) } validatedMetrics := make(map[string]bool) @@ -172,6 +189,35 @@ func TestMetricsBuilder(t *testing.T) { assert.Equal(t, ts, dp.Timestamp()) assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) assert.Equal(t, float64(1), dp.DoubleValue()) + case "metric.input_type": + assert.False(t, validatedMetrics["metric.input_type"], "Found a duplicate in the metrics slice: metric.input_type") + validatedMetrics["metric.input_type"] = 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 with string input_type 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 "optional.metric": assert.False(t, validatedMetrics["optional.metric"], "Found a duplicate in the metrics slice: optional.metric") validatedMetrics["optional.metric"] = true diff --git a/cmd/mdatagen/internal/metadata/generated_resource.go b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_resource.go similarity index 100% rename from cmd/mdatagen/internal/metadata/generated_resource.go rename to cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_resource.go diff --git a/cmd/mdatagen/internal/metadata/generated_resource_test.go b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_resource_test.go similarity index 100% rename from cmd/mdatagen/internal/metadata/generated_resource_test.go rename to cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_resource_test.go diff --git a/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_status.go b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_status.go new file mode 100644 index 00000000000..e3e8df2ad14 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_status.go @@ -0,0 +1,17 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("sample") +) + +const ( + LogsStability = component.StabilityLevelDevelopment + TracesStability = component.StabilityLevelBeta + MetricsStability = component.StabilityLevelStable +) diff --git a/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry.go b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..2e9683259cd --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry.go @@ -0,0 +1,18 @@ +// 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" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/internal/receiver/samplereceiver") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/internal/receiver/samplereceiver") +} diff --git a/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry_test.go b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..cfdc5ab89e3 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/internal/receiver/samplereceiver", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/internal/receiver/samplereceiver", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/cmd/mdatagen/internal/samplereceiver/internal/metadata/testdata/config.yaml b/cmd/mdatagen/internal/samplereceiver/internal/metadata/testdata/config.yaml new file mode 100644 index 00000000000..c4b7edd6568 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadata/testdata/config.yaml @@ -0,0 +1,127 @@ +default: +all_set: + metrics: + default.metric: + enabled: true + default.metric.to_be_removed: + enabled: true + metric.input_type: + 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 + metric.input_type: + 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 +filter_set_include: + resource_attributes: + map.resource.attr: + enabled: true + metrics_include: + - regexp: ".*" + optional.resource.attr: + enabled: true + metrics_include: + - regexp: ".*" + slice.resource.attr: + enabled: true + metrics_include: + - regexp: ".*" + string.enum.resource.attr: + enabled: true + metrics_include: + - regexp: ".*" + string.resource.attr: + enabled: true + metrics_include: + - regexp: ".*" + string.resource.attr_disable_warning: + enabled: true + metrics_include: + - regexp: ".*" + string.resource.attr_remove_warning: + enabled: true + metrics_include: + - regexp: ".*" + string.resource.attr_to_be_removed: + enabled: true + metrics_include: + - regexp: ".*" +filter_set_exclude: + resource_attributes: + map.resource.attr: + enabled: true + metrics_exclude: + - regexp: ".*" + optional.resource.attr: + enabled: true + metrics_exclude: + - strict: "optional.resource.attr-val" + slice.resource.attr: + enabled: true + metrics_exclude: + - regexp: ".*" + string.enum.resource.attr: + enabled: true + metrics_exclude: + - strict: "one" + string.resource.attr: + enabled: true + metrics_exclude: + - strict: "string.resource.attr-val" + string.resource.attr_disable_warning: + enabled: true + metrics_exclude: + - strict: "string.resource.attr_disable_warning-val" + string.resource.attr_remove_warning: + enabled: true + metrics_exclude: + - strict: "string.resource.attr_remove_warning-val" + string.resource.attr_to_be_removed: + enabled: true + metrics_exclude: + - strict: "string.resource.attr_to_be_removed-val" diff --git a/cmd/mdatagen/metadata-sample.yaml b/cmd/mdatagen/internal/samplereceiver/metadata.yaml similarity index 85% rename from cmd/mdatagen/metadata-sample.yaml rename to cmd/mdatagen/internal/samplereceiver/metadata.yaml index b9a5f8f6c90..06d544b18af 100644 --- a/cmd/mdatagen/metadata-sample.yaml +++ b/cmd/mdatagen/internal/samplereceiver/metadata.yaml @@ -1,6 +1,7 @@ -# Sample metric metadata file with all available configurations. +# Sample metadata file with all available configurations for a receiver. -type: file +type: sample +scope_name: go.opentelemetry.io/collector/internal/receiver/samplereceiver sem_conv_version: 1.9.0 @@ -10,7 +11,10 @@ status: development: [logs] beta: [traces] stable: [metrics] - distributions: [contrib] + distributions: [] + unsupported_platforms: [freebsd, illumos] + codeowners: + active: [dmitryax] warnings: - Any additional information that should be brought to the consumer's attention @@ -134,3 +138,14 @@ metrics: aggregation_temporality: delta warnings: if_enabled: This metric is deprecated and will be removed soon. + + metric.input_type: + enabled: true + description: Monotonic cumulative sum int metric with string input_type enabled by default. + unit: s + sum: + value_type: int + input_type: string + monotonic: true + aggregation_temporality: cumulative + attributes: [ string_attr, overridden_int_attr, enum_attr, slice_attr, map_attr ] diff --git a/cmd/mdatagen/internal/samplereceiver/metrics_test.go b/cmd/mdatagen/internal/samplereceiver/metrics_test.go new file mode 100644 index 00000000000..ec5f67cf0db --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/metrics_test.go @@ -0,0 +1,20 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package samplereceiver + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplereceiver/internal/metadata" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +// TestGeneratedMetrics verifies that the internal/metadata API is generated correctly. +func TestGeneratedMetrics(t *testing.T) { + mb := metadata.NewMetricsBuilder(metadata.DefaultMetricsBuilderConfig(), receivertest.NewNopCreateSettings()) + m := mb.Emit() + require.Equal(t, 0, m.ResourceMetrics().Len()) +} diff --git a/cmd/mdatagen/lint_test.go b/cmd/mdatagen/lint_test.go index 5c470f302d7..f05d6615ea3 100644 --- a/cmd/mdatagen/lint_test.go +++ b/cmd/mdatagen/lint_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" ) -func Test_formatIdentifier(t *testing.T) { +func TestFormatIdentifier(t *testing.T) { var tests = []struct { input string want string diff --git a/cmd/mdatagen/loader.go b/cmd/mdatagen/loader.go index 8b4b996a5e2..20b20d0dc19 100644 --- a/cmd/mdatagen/loader.go +++ b/cmd/mdatagen/loader.go @@ -7,12 +7,14 @@ import ( "context" "errors" "fmt" - "os" + "os/exec" "path/filepath" "strings" "go.opentelemetry.io/collector/confmap" + "go.opentelemetry.io/collector/confmap/confmaptest" "go.opentelemetry.io/collector/confmap/provider/fileprovider" + "go.opentelemetry.io/collector/filter" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -124,11 +126,7 @@ 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 + return parser.Unmarshal(m) } func (m metric) Data() MetricData { if m.Sum != nil { @@ -156,6 +154,10 @@ type attribute struct { NameOverride string `mapstructure:"name_override"` // Enabled defines whether the attribute is enabled by default. Enabled bool `mapstructure:"enabled"` + // Include can be used to filter attributes. + Include []filter.Config `mapstructure:"include"` + // Include can be used to filter attributes. + Exclude []filter.Config `mapstructure:"exclude"` // Enum can optionally describe the set of values to which the attribute can belong. Enum []string `mapstructure:"enum"` // Type is an attribute type. @@ -199,10 +201,24 @@ func (a attribute) TestValue() string { return "" } +type ignore struct { + Top []string `mapstructure:"top"` + Any []string `mapstructure:"any"` +} + +type goLeak struct { + Skip bool `mapstructure:"skip"` + Ignore ignore `mapstructure:"ignore"` + Setup string `mapstructure:"setup"` + Teardown string `mapstructure:"teardown"` +} + type tests struct { - Config any `mapstructure:"config"` - SkipLifecycle bool `mapstructure:"skip_lifecycle"` - ExpectConsumerError bool `mapstructure:"expect_consumer_error"` + Config any `mapstructure:"config"` + SkipLifecycle bool `mapstructure:"skip_lifecycle"` + SkipShutdown bool `mapstructure:"skip_shutdown"` + GoLeak goLeak `mapstructure:"goleak"` + ExpectConsumerError bool `mapstructure:"expect_consumer_error"` } type metadata struct { @@ -221,11 +237,11 @@ type metadata struct { // 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:"-"` + ScopeName string `mapstructure:"scope_name"` // ShortFolderName is the shortened folder name of the component, removing class if present ShortFolderName string `mapstructure:"-"` - Tests *tests `mapstructure:"tests"` + Tests tests `mapstructure:"tests"` } func setAttributesFullName(attrs map[attributeName]attribute) { @@ -242,7 +258,7 @@ type templateContext struct { } func loadMetadata(filePath string) (metadata, error) { - cp, err := fileprovider.New().Retrieve(context.Background(), "file:"+filePath, nil) + cp, err := fileprovider.NewFactory().Create(confmaptest.NewNopProviderSettings()).Retrieve(context.Background(), "file:"+filePath, nil) if err != nil { return metadata{}, err } @@ -252,12 +268,18 @@ func loadMetadata(filePath string) (metadata, error) { return metadata{}, err } - md := metadata{ScopeName: scopeName(filePath), ShortFolderName: shortFolderName(filePath)} - if err := conf.Unmarshal(&md); err != nil { + md := metadata{ShortFolderName: shortFolderName(filePath)} + if err = conf.Unmarshal(&md); err != nil { return md, err } + if md.ScopeName == "" { + md.ScopeName, err = packageName() + if err != nil { + return md, err + } + } - if err := md.Validate(); err != nil { + if err = md.Validate(); err != nil { return md, err } @@ -286,15 +308,11 @@ func shortFolderName(filePath string) string { 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 - } - } +func packageName() (string, error) { + cmd := exec.Command("go", "list", "-f", "{{.ImportPath}}") + output, err := cmd.Output() + if err != nil { + return "", err } - return sn + return strings.TrimSpace(string(output)), nil } diff --git a/cmd/mdatagen/loader_test.go b/cmd/mdatagen/loader_test.go index aafacc8f252..cf3d59e07ce 100644 --- a/cmd/mdatagen/loader_test.go +++ b/cmd/mdatagen/loader_test.go @@ -8,30 +8,35 @@ import ( "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/pmetric" ) -func Test_loadMetadata(t *testing.T) { +func TestLoadMetadata(t *testing.T) { tests := []struct { name string want metadata wantErr string }{ { - name: "metadata-sample.yaml", + name: "internal/samplereceiver/metadata.yaml", want: metadata{ - Type: "file", + Type: "sample", SemConvVersion: "1.9.0", Status: &Status{ Class: "receiver", - Stability: map[string][]string{ - "development": {"logs"}, - "beta": {"traces"}, - "stable": {"metrics"}, + Stability: map[component.StabilityLevel][]string{ + component.StabilityLevelDevelopment: {"logs"}, + component.StabilityLevelBeta: {"traces"}, + component.StabilityLevelStable: {"metrics"}, }, - Distributions: []string{"contrib"}, - Warnings: []string{"Any additional information that should be brought to the consumer's attention"}, + Distributions: []string{}, + Codeowners: &Codeowners{ + Active: []string{"dmitryax"}, + }, + Warnings: []string{"Any additional information that should be brought to the consumer's attention"}, + UnsupportedPlatforms: []string{"freebsd", "illumos"}, }, ResourceAttributes: map[attributeName]attribute{ "string.resource.attr": { @@ -213,9 +218,21 @@ func Test_loadMetadata(t *testing.T) { Mono: Mono{Monotonic: false}, }, }, + "metric.input_type": { + Enabled: true, + Description: "Monotonic cumulative sum int metric with string input_type enabled by default.", + Unit: strPtr("s"), + Sum: &sum{ + MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeInt}, + MetricInputType: MetricInputType{InputType: "string"}, + AggregationTemporality: AggregationTemporality{Aggregation: pmetric.AggregationTemporalityCumulative}, + Mono: Mono{Monotonic: true}, + }, + Attributes: []attributeName{"string_attr", "overridden_int_attr", "enum_attr", "slice_attr", "map_attr"}, + }, }, - ScopeName: "go.opentelemetry.io/collector", - ShortFolderName: ".", + ScopeName: "go.opentelemetry.io/collector/internal/receiver/samplereceiver", + ShortFolderName: "sample", }, }, { @@ -223,7 +240,7 @@ func Test_loadMetadata(t *testing.T) { want: metadata{ Type: "subcomponent", Parent: "parentComponent", - ScopeName: "go.opentelemetry.io/collector", + ScopeName: "go.opentelemetry.io/collector/cmd/mdatagen", ShortFolderName: "testdata", }, }, diff --git a/cmd/mdatagen/main.go b/cmd/mdatagen/main.go index 4d04bd0696f..8d7d1731faa 100644 --- a/cmd/mdatagen/main.go +++ b/cmd/mdatagen/main.go @@ -43,6 +43,7 @@ func run(ymlPath string) error { } ymlDir := filepath.Dir(ymlPath) + packageName := filepath.Base(ymlDir) md, err := loadMetadata(ymlPath) if err != nil { @@ -61,6 +62,22 @@ func run(ymlPath string) error { filepath.Join(codeDir, "generated_status.go"), md, "metadata"); err != nil { return err } + if err = generateFile(filepath.Join(tmplDir, "telemetry.go.tmpl"), + filepath.Join(codeDir, "generated_telemetry.go"), md, "metadata"); err != nil { + return err + } + if err = generateFile(filepath.Join(tmplDir, "telemetry_test.go.tmpl"), + filepath.Join(codeDir, "generated_telemetry_test.go"), md, "metadata"); err != nil { + return err + } + if err = generateFile(filepath.Join(tmplDir, "component_test.go.tmpl"), + filepath.Join(ymlDir, "generated_component_test.go"), md, packageName); err != nil { + return err + } + if err = generateFile(filepath.Join(tmplDir, "package_test.go.tmpl"), + filepath.Join(ymlDir, "generated_package_test.go"), md, packageName); err != nil { + return err + } } if _, err = os.Stat(filepath.Join(ymlDir, "README.md")); err == nil { @@ -73,13 +90,6 @@ func run(ymlPath string) error { } } - 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 } @@ -164,7 +174,8 @@ func templatize(tmplFile string, md metadata) *template.Template { } return result }, - "casesTitle": cases.Title(language.English).String, + "casesTitle": cases.Title(language.English).String, + "toLowerCase": strings.ToLower, "toCamelCase": func(s string) string { caser := cases.Title(language.English).String parts := strings.Split(s, "_") @@ -193,9 +204,6 @@ func templatize(tmplFile string, md metadata) *template.Template { "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 { diff --git a/cmd/mdatagen/main_test.go b/cmd/mdatagen/main_test.go index df3387fd167..bfd197a42fd 100644 --- a/cmd/mdatagen/main_test.go +++ b/cmd/mdatagen/main_test.go @@ -6,23 +6,27 @@ package main import ( "bytes" "fmt" + "go/parser" + "go/token" "os" "path/filepath" "testing" "github.com/stretchr/testify/require" - md "go.opentelemetry.io/collector/cmd/mdatagen/internal/metadata" - "go.opentelemetry.io/collector/receiver/receivertest" + "go.opentelemetry.io/collector/component" ) -func Test_runContents(t *testing.T) { +func TestRunContents(t *testing.T) { tests := []struct { yml string wantMetricsGenerated bool wantConfigGenerated bool wantStatusGenerated bool - wantTestsGenerated bool + wantGoleakIgnore bool + wantGoleakSkip bool + wantGoleakSetup bool + wantGoleakTeardown bool wantErr bool }{ { @@ -46,29 +50,44 @@ func Test_runContents(t *testing.T) { }, { 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, }, + { + yml: "with_goleak_ignores.yaml", + wantStatusGenerated: true, + wantGoleakIgnore: true, + }, + { + yml: "with_goleak_skip.yaml", + wantStatusGenerated: true, + wantGoleakSkip: true, + }, + { + yml: "with_goleak_setup.yaml", + wantStatusGenerated: true, + wantGoleakSetup: true, + }, + { + yml: "with_goleak_teardown.yaml", + wantStatusGenerated: true, + wantGoleakTeardown: true, + }, } for _, tt := range tests { t.Run(tt.yml, func(t *testing.T) { @@ -109,31 +128,63 @@ foo require.NoFileExists(t, filepath.Join(tmpdir, "internal/metadata/generated_config_test.go")) } + var contents []byte 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 + 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 + 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") + 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") + _, err = parser.ParseFile(token.NewFileSet(), "", contents, parser.DeclarationErrors) + require.NoError(t, err) + + require.FileExists(t, filepath.Join(tmpdir, "generated_package_test.go")) + contents, err = os.ReadFile(filepath.Join(tmpdir, "generated_package_test.go")) // nolint: gosec + require.NoError(t, err) + require.Contains(t, string(contents), "func TestMain") + _, err = parser.ParseFile(token.NewFileSet(), "", contents, parser.DeclarationErrors) + require.NoError(t, err) + + if tt.wantGoleakSkip { + require.Contains(t, string(contents), "skipping goleak test") + } else { + require.NotContains(t, string(contents), "skipping goleak test") + } + + if tt.wantGoleakIgnore { + require.Contains(t, string(contents), "IgnoreTopFunction") + require.Contains(t, string(contents), "IgnoreAnyFunction") + } else { + require.NotContains(t, string(contents), "IgnoreTopFunction") + require.NotContains(t, string(contents), "IgnoreAnyFunction") + } + + if tt.wantGoleakSetup { + require.Contains(t, string(contents), "setupFunc") + } else { + require.NotContains(t, string(contents), "setupFunc") + } + + if tt.wantGoleakTeardown { + require.Contains(t, string(contents), "teardownFunc") } else { - require.NoFileExists(t, filepath.Join(tmpdir, "generated_component_test.go")) + require.NotContains(t, string(contents), "teardownFunc") } }) } } -func Test_run(t *testing.T) { +func TestRun(t *testing.T) { type args struct { ymlPath string } @@ -162,14 +213,14 @@ func Test_run(t *testing.T) { } } -func Test_inlineReplace(t *testing.T) { +func TestInlineReplace(t *testing.T) { tests := []struct { name string markdown string outputFile string componentClass string warnings []string - stability map[string][]string + stability map[component.StabilityLevel][]string distros []string codeowners *Codeowners }{ @@ -298,8 +349,11 @@ Some warning there. Some info about a component `, outputFile: "readme_with_multiple_signals.md", - stability: map[string][]string{"beta": {"metrics"}, "alpha": {"logs"}}, - distros: []string{"contrib"}, + stability: map[component.StabilityLevel][]string{ + component.StabilityLevelBeta: {"metrics"}, + component.StabilityLevelAlpha: {"logs"}, + }, + distros: []string{"contrib"}, }, { name: "readme with cmd class", @@ -310,15 +364,18 @@ Some info about a component Some info about a component `, - outputFile: "readme_with_cmd_class.md", - stability: map[string][]string{"beta": {"metrics"}, "alpha": {"logs"}}, + outputFile: "readme_with_cmd_class.md", + stability: map[component.StabilityLevel][]string{ + component.StabilityLevelBeta: {"metrics"}, + component.StabilityLevelAlpha: {"logs"}, + }, componentClass: "cmd", distros: []string{}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - stability := map[string][]string{"beta": {"metrics"}} + stability := map[component.StabilityLevel][]string{component.StabilityLevelBeta: {"metrics"}} if len(tt.stability) > 0 { stability = tt.stability } @@ -367,7 +424,9 @@ func TestGenerateStatusMetadata(t *testing.T) { md: metadata{ Type: "foo", Status: &Status{ - Stability: map[string][]string{"beta": {"metrics"}}, + Stability: map[component.StabilityLevel][]string{ + component.StabilityLevelBeta: {"metrics"}, + }, Distributions: []string{"contrib"}, Class: "receiver", }, @@ -378,25 +437,96 @@ package metadata import ( "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/trace" ) var ( - Type = component.MustNewType("foo") - scopeName = "" + Type = component.MustNewType("foo") ) const ( MetricsStability = component.StabilityLevelBeta ) +`, + }, + { + name: "foo component with alpha status", + md: metadata{ + Type: "foo", + Status: &Status{ + Stability: map[component.StabilityLevel][]string{ + component.StabilityLevelAlpha: {"metrics"}, + }, + Distributions: []string{"contrib"}, + Class: "receiver", + }, + }, + expected: `// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("foo") +) + +const ( + MetricsStability = component.StabilityLevelAlpha +) +`, + }, + } + + 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)) + }) + } +} + +func TestGenerateTelemetryMetadata(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[component.StabilityLevel][]string{ + component.StabilityLevelBeta: {"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" +) func Meter(settings component.TelemetrySettings) metric.Meter { - return settings.MeterProvider.Meter(scopeName) + return settings.MeterProvider.Meter("") } func Tracer(settings component.TelemetrySettings) trace.Tracer { - return settings.TracerProvider.Tracer(scopeName) + return settings.TracerProvider.Tracer("") } `, }, @@ -405,7 +535,9 @@ func Tracer(settings component.TelemetrySettings) trace.Tracer { md: metadata{ Type: "foo", Status: &Status{ - Stability: map[string][]string{"alpha": {"metrics"}}, + Stability: map[component.StabilityLevel][]string{ + component.StabilityLevelAlpha: {"metrics"}, + }, Distributions: []string{"contrib"}, Class: "receiver", }, @@ -420,21 +552,12 @@ import ( "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) + return settings.MeterProvider.Meter("") } func Tracer(settings component.TelemetrySettings) trace.Tracer { - return settings.TracerProvider.Tracer(scopeName) + return settings.TracerProvider.Tracer("") } `, }, @@ -443,19 +566,12 @@ func Tracer(settings component.TelemetrySettings) trace.Tracer { 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") + err := generateFile("templates/telemetry.go.tmpl", + filepath.Join(tmpdir, "generated_telemetry.go"), tt.md, "metadata") require.NoError(t, err) - actual, err := os.ReadFile(filepath.Join(tmpdir, "generated_status.go")) // nolint: gosec + actual, err := os.ReadFile(filepath.Join(tmpdir, "generated_telemetry.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-schema.yaml b/cmd/mdatagen/metadata-schema.yaml index 879307fdd3d..1363346971e 100644 --- a/cmd/mdatagen/metadata-schema.yaml +++ b/cmd/mdatagen/metadata-schema.yaml @@ -4,6 +4,9 @@ type: # Required for subcomponents: The type of the parent component. parent: string +# Optional: Scope name for the telemetry generated by the component. If not set, name of the go package will be used. +scope_name: 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) @@ -109,5 +112,16 @@ metrics: # Lifecycle tests generated for this component. tests: config: # {} by default, specific testing configuration for lifecycle tests. + # Skip lifecycle tests for this component. Not recommended for components that are not in development. skip_lifecycle: false # false by default + # Skip shutdown tests for this component. Not recommended for components that are not in development. + skip_shutdown: false # false by default + # Whether it's expected that the Consume[Logs|Metrics|Traces] method will return an error with the given configuration. expect_consumer_error: true # false by default + goleak: # {} by default generates a package_test to enable check for leaks + skip: false # set to true if goleak tests should be skipped + setup: string # Optional: supports configuring a setup function that runs before goleak checks + teardown: string # Optional: supports configuring a teardown function that runs before goleak checks + ignore: + top: [string] # Optional: array of strings representing functions that should be ignore via IgnoreTopFunction + any: [string] # Optional: array of strings representing functions that should be ignore via IgnoreAnyFunction diff --git a/cmd/mdatagen/metricdata.go b/cmd/mdatagen/metricdata.go index f4515136aae..5bf77985cc9 100644 --- a/cmd/mdatagen/metricdata.go +++ b/cmd/mdatagen/metricdata.go @@ -125,7 +125,7 @@ func (d *gauge) Unmarshal(parser *confmap.Conf) error { if err := d.MetricValueType.Unmarshal(parser); err != nil { return err } - return parser.Unmarshal(d) + return parser.Unmarshal(d, confmap.WithIgnoreUnused()) } func (d gauge) Type() string { @@ -155,7 +155,7 @@ func (d *sum) Unmarshal(parser *confmap.Conf) error { if err := d.MetricValueType.Unmarshal(parser); err != nil { return err } - return parser.Unmarshal(d) + return parser.Unmarshal(d, confmap.WithIgnoreUnused()) } // TODO: Currently, this func will not be called because of https://github.com/open-telemetry/opentelemetry-collector/issues/6671. Uncomment function and diff --git a/exporter/otlpexporter/package_test.go b/cmd/mdatagen/package_test.go similarity index 89% rename from exporter/otlpexporter/package_test.go rename to cmd/mdatagen/package_test.go index c5fb1007f5b..5cd502ca564 100644 --- a/exporter/otlpexporter/package_test.go +++ b/cmd/mdatagen/package_test.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package otlpexporter +package main import ( "testing" diff --git a/cmd/mdatagen/statusdata.go b/cmd/mdatagen/statusdata.go index d65a5c20f58..c157b82a73c 100644 --- a/cmd/mdatagen/statusdata.go +++ b/cmd/mdatagen/statusdata.go @@ -4,23 +4,21 @@ package main import ( + "errors" "sort" + "strings" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap" ) // 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 distribution is open source and maintained by the OpenTelemetry project. // - 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", + "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", } type Codeowners struct { @@ -32,13 +30,15 @@ type Codeowners struct { SeekingNew bool `mapstructure:"seeking_new"` } +type StabilityMap map[component.StabilityLevel][]string + 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"` + Stability StabilityMap `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 { @@ -60,3 +60,31 @@ func (s *Status) SortedDistributions() []string { }) return sorted } + +func (ms *StabilityMap) Unmarshal(parser *confmap.Conf) error { + *ms = make(StabilityMap) + raw := make(map[string][]string) + err := parser.Unmarshal(&raw) + if err != nil { + return err + } + for k, v := range raw { + switch strings.ToLower(k) { + case strings.ToLower(component.StabilityLevelUnmaintained.String()): + (*ms)[component.StabilityLevelUnmaintained] = v + case strings.ToLower(component.StabilityLevelDeprecated.String()): + (*ms)[component.StabilityLevelDeprecated] = v + case strings.ToLower(component.StabilityLevelDevelopment.String()): + (*ms)[component.StabilityLevelDevelopment] = v + case strings.ToLower(component.StabilityLevelAlpha.String()): + (*ms)[component.StabilityLevelAlpha] = v + case strings.ToLower(component.StabilityLevelBeta.String()): + (*ms)[component.StabilityLevelBeta] = v + case strings.ToLower(component.StabilityLevelStable.String()): + (*ms)[component.StabilityLevelStable] = v + default: + return errors.New("invalid stability level: " + k) + } + } + return nil +} diff --git a/cmd/mdatagen/templates/component_test.go.tmpl b/cmd/mdatagen/templates/component_test.go.tmpl index 3c82b1ed2d2..ca948214d80 100644 --- a/cmd/mdatagen/templates/component_test.go.tmpl +++ b/cmd/mdatagen/templates/component_test.go.tmpl @@ -1,51 +1,69 @@ // Code generated by mdatagen. DO NOT EDIT. -{{ if len .Status.UnsupportedPlatforms -}} +{{- if len .Status.UnsupportedPlatforms }} //go:build {{ range $i, $v := .Status.UnsupportedPlatforms }}{{ if $i }} && {{ end }}!{{ . }}{{ end }} {{- end }} package {{ .Package }} import ( + {{- if not (and .Tests.SkipLifecycle .Tests.SkipShutdown) }} "context" + {{- end }} "testing" + {{- if and (not (and .Tests.SkipLifecycle .Tests.SkipShutdown)) (or isExporter isProcessor) }} + "time" + {{- end }} "github.com/stretchr/testify/require" + {{- if not (and .Tests.SkipLifecycle .Tests.SkipShutdown) }} "go.opentelemetry.io/collector/component" + {{- end }} "go.opentelemetry.io/collector/component/componenttest" -{{ if isExporter }} + "go.opentelemetry.io/collector/confmap/confmaptest" + {{- if not (and .Tests.SkipLifecycle .Tests.SkipShutdown) }} + {{- if isExporter }} "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exportertest" -{{ end }} -{{ if isProcessor }} + {{- end }} + {{- if isProcessor }} "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/processor" "go.opentelemetry.io/collector/processor/processortest" -{{ end }} -{{ if isReceiver }} + {{- end }} + {{- if isReceiver }} "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/receiver" "go.opentelemetry.io/collector/receiver/receivertest" -{{ end }} -{{ if isExtension }} + {{- end }} + {{- if isExtension }} "go.opentelemetry.io/collector/extension/extensiontest" -{{ end }} -{{ if isConnector }} - "go.opentelemetry.io/collector/consumer/consumertest" + {{- end }} + {{- if isConnector }} "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 }} + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumertest" + {{- end }} + {{- if or isExporter isProcessor }} + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" + {{- end }} + {{- end }} ) -func TestCheckConfigStruct(t *testing.T) { - componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig()) +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "{{ .Type }}", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) } -{{ if isExporter }} +{{ if not (and .Tests.SkipLifecycle .Tests.SkipShutdown) -}} +{{ if isExporter -}} func TestComponentLifecycle(t *testing.T) { factory := NewFactory() @@ -87,39 +105,44 @@ func TestComponentLifecycle(t *testing.T) { require.NoError(t, component.UnmarshalConfig(sub, cfg)) for _, test := range tests { + {{- if not .Tests.SkipShutdown }} 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) }) + {{- end }} + {{- if not .Tests.SkipLifecycle }} 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) + switch test.name { + case "logs": + e, ok := c.(exporter.Logs) + require.True(t, ok) + logs := generateLifecycleTestLogs() if !e.Capabilities().MutatesData { logs.MarkReadOnly() } err = e.ConsumeLogs(context.Background(), logs) - case exporter.Metrics: - metrics := testdata.GenerateMetricsTwoMetrics() + case "metrics": + e, ok := c.(exporter.Metrics) + require.True(t, ok) + metrics := generateLifecycleTestMetrics() if !e.Capabilities().MutatesData { metrics.MarkReadOnly() } err = e.ConsumeMetrics(context.Background(), metrics) - case exporter.Traces: - traces := testdata.GenerateTracesTwoSpansSameResource() + case "traces": + e, ok := c.(exporter.Traces) + require.True(t, ok) + traces := generateLifecycleTestTraces() if !e.Capabilities().MutatesData { traces.MarkReadOnly() } @@ -132,6 +155,7 @@ func TestComponentLifecycle(t *testing.T) { err = c.Shutdown(context.Background()) require.NoError(t, err) }) + {{- end }} } } {{ end }} @@ -178,39 +202,44 @@ func TestComponentLifecycle(t *testing.T) { require.NoError(t, component.UnmarshalConfig(sub, cfg)) for _, test := range tests { + {{- if not .Tests.SkipShutdown }} 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) }) + {{- end }} + {{- if not .Tests.SkipLifecycle }} 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) + switch test.name { + case "logs": + e, ok := c.(processor.Logs) + require.True(t, ok) + logs := generateLifecycleTestLogs() if !e.Capabilities().MutatesData { logs.MarkReadOnly() } err = e.ConsumeLogs(context.Background(), logs) - case processor.Metrics: - metrics := testdata.GenerateMetricsTwoMetrics() + case "metrics": + e, ok := c.(processor.Metrics) + require.True(t, ok) + metrics := generateLifecycleTestMetrics() if !e.Capabilities().MutatesData { metrics.MarkReadOnly() } err = e.ConsumeMetrics(context.Background(), metrics) - case processor.Traces: - traces := testdata.GenerateTracesTwoSpansSameResource() + case "traces": + e, ok := c.(processor.Traces) + require.True(t, ok) + traces := generateLifecycleTestTraces() if !e.Capabilities().MutatesData { traces.MarkReadOnly() } @@ -221,6 +250,7 @@ func TestComponentLifecycle(t *testing.T) { err = c.Shutdown(context.Background()) require.NoError(t, err) }) + {{- end }} } } {{ end }} @@ -267,18 +297,17 @@ func TestComponentLifecycle(t *testing.T) { require.NoError(t, component.UnmarshalConfig(sub, cfg)) for _, test := range tests { + {{- if not .Tests.SkipShutdown }} 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) }) + {{- end }} + {{- if not .Tests.SkipLifecycle }} 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() @@ -290,6 +319,7 @@ func TestComponentLifecycle(t *testing.T) { require.NoError(t, secondRcvr.Start(context.Background(), host)) require.NoError(t, secondRcvr.Shutdown(context.Background())) }) + {{- end }} } } {{ end }} @@ -305,18 +335,17 @@ func TestComponentLifecycle(t *testing.T) { require.NoError(t, err) require.NoError(t, component.UnmarshalConfig(sub, cfg)) + {{- if not .Tests.SkipShutdown }} 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) }) + {{- end }} + {{- if not .Tests.SkipLifecycle }} 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())) @@ -327,6 +356,7 @@ func TestComponentLifecycle(t *testing.T) { require.NoError(t, secondExt.Start(context.Background(), componenttest.NewNopHost())) require.NoError(t, secondExt.Shutdown(context.Background())) }) + {{- end }} } {{ end }} @@ -342,7 +372,8 @@ func TestComponentLifecycle(t *testing.T) { { 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()) + router := connector.NewLogsRouter(map[component.ID]consumer.Logs{component.NewID(component.DataTypeLogs): consumertest.NewNop()}) + return factory.CreateLogsToLogs(ctx, set, cfg, router) }, }, {{ end }} @@ -350,7 +381,8 @@ func TestComponentLifecycle(t *testing.T) { { 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()) + router := connector.NewMetricsRouter(map[component.ID]consumer.Metrics{component.NewID(component.DataTypeMetrics): consumertest.NewNop()}) + return factory.CreateLogsToMetrics(ctx, set, cfg, router) }, }, {{ end }} @@ -358,7 +390,8 @@ func TestComponentLifecycle(t *testing.T) { { 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()) + router := connector.NewTracesRouter(map[component.ID]consumer.Traces{component.NewID(component.DataTypeTraces): consumertest.NewNop()}) + return factory.CreateLogsToTraces(ctx, set, cfg, router) }, }, {{ end }} @@ -366,7 +399,8 @@ func TestComponentLifecycle(t *testing.T) { { 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()) + router := connector.NewLogsRouter(map[component.ID]consumer.Logs{component.NewID(component.DataTypeLogs): consumertest.NewNop()}) + return factory.CreateMetricsToLogs(ctx, set, cfg, router) }, }, {{ end }} @@ -374,7 +408,8 @@ func TestComponentLifecycle(t *testing.T) { { 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()) + router := connector.NewMetricsRouter(map[component.ID]consumer.Metrics{component.NewID(component.DataTypeMetrics): consumertest.NewNop()}) + return factory.CreateMetricsToMetrics(ctx, set, cfg, router) }, }, {{ end }} @@ -382,7 +417,8 @@ func TestComponentLifecycle(t *testing.T) { { 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()) + router := connector.NewTracesRouter(map[component.ID]consumer.Traces{component.NewID(component.DataTypeTraces): consumertest.NewNop()}) + return factory.CreateMetricsToTraces(ctx, set, cfg, router) }, }, {{ end }} @@ -390,7 +426,8 @@ func TestComponentLifecycle(t *testing.T) { { 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()) + router := connector.NewLogsRouter(map[component.ID]consumer.Logs{component.NewID(component.DataTypeLogs): consumertest.NewNop()}) + return factory.CreateTracesToLogs(ctx, set, cfg, router) }, }, {{ end }} @@ -398,7 +435,8 @@ func TestComponentLifecycle(t *testing.T) { { 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()) + router := connector.NewMetricsRouter(map[component.ID]consumer.Metrics{component.NewID(component.DataTypeMetrics): consumertest.NewNop()}) + return factory.CreateTracesToMetrics(ctx, set, cfg, router) }, }, {{ end }} @@ -406,7 +444,8 @@ func TestComponentLifecycle(t *testing.T) { { 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()) + router := connector.NewTracesRouter(map[component.ID]consumer.Traces{component.NewID(component.DataTypeTraces): consumertest.NewNop()}) + return factory.CreateTracesToTraces(ctx, set, cfg, router) }, }, {{ end }} @@ -420,21 +459,20 @@ func TestComponentLifecycle(t *testing.T) { require.NoError(t, component.UnmarshalConfig(sub, cfg)) for _, test := range tests { + {{- if not .Tests.SkipShutdown }} 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) }) + {{- end }} + {{- if not .Tests.SkipLifecycle }} 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) + host := componenttest.NewNopHost() require.NoError(t, err) require.NoError(t, firstConnector.Start(context.Background(), host)) require.NoError(t, firstConnector.Shutdown(context.Background())) @@ -443,6 +481,45 @@ func TestComponentLifecycle(t *testing.T) { require.NoError(t, secondConnector.Start(context.Background(), host)) require.NoError(t, secondConnector.Shutdown(context.Background())) }) + {{- end }} } } -{{ end }} \ No newline at end of file +{{ end }} + +{{ if or isExporter isProcessor -}} +func generateLifecycleTestLogs() plog.Logs { + logs := plog.NewLogs() + rl := logs.ResourceLogs().AppendEmpty() + rl.Resource().Attributes().PutStr("resource", "R1") + l := rl.ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() + l.Body().SetStr("test log message") + l.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return logs +} + +func generateLifecycleTestMetrics() pmetric.Metrics { + metrics := pmetric.NewMetrics() + rm := metrics.ResourceMetrics().AppendEmpty() + rm.Resource().Attributes().PutStr("resource", "R1") + m := rm.ScopeMetrics().AppendEmpty().Metrics().AppendEmpty() + m.SetName("test_metric") + dp := m.SetEmptyGauge().DataPoints().AppendEmpty() + dp.Attributes().PutStr("test_attr", "value_1") + dp.SetIntValue(123) + dp.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return metrics +} + +func generateLifecycleTestTraces() ptrace.Traces { + traces := ptrace.NewTraces() + rs := traces.ResourceSpans().AppendEmpty() + rs.Resource().Attributes().PutStr("resource", "R1") + span := rs.ScopeSpans().AppendEmpty().Spans().AppendEmpty() + span.Attributes().PutStr("test_attr", "value_1") + span.SetName("test_span") + span.SetStartTimestamp(pcommon.NewTimestampFromTime(time.Now().Add(-1 * time.Second))) + span.SetEndTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return traces +} +{{- end }} +{{- end }} diff --git a/cmd/mdatagen/templates/config.go.tmpl b/cmd/mdatagen/templates/config.go.tmpl index 712602222e7..877d435754b 100644 --- a/cmd/mdatagen/templates/config.go.tmpl +++ b/cmd/mdatagen/templates/config.go.tmpl @@ -2,10 +2,12 @@ package {{ .Package }} -{{ if or .Metrics .ResourceAttributes -}} -import "go.opentelemetry.io/collector/confmap" -{{- end }} - +import ( + "go.opentelemetry.io/collector/confmap" + {{ if and .Metrics .ResourceAttributes -}} + "go.opentelemetry.io/collector/filter" + {{- end }} +) {{ if .Metrics -}} // MetricConfig provides common config for a particular metric. @@ -49,6 +51,15 @@ func DefaultMetricsConfig() MetricsConfig { // ResourceAttributeConfig provides common config for a particular resource attribute. type ResourceAttributeConfig struct { Enabled bool `mapstructure:"enabled"` + {{- if .Metrics }} + // Experimental: MetricsInclude defines a list of filters for attribute values. + // If the list is not empty, only metrics with matching resource attribute values will be emitted. + MetricsInclude []filter.Config `mapstructure:"metrics_include"` + // Experimental: MetricsExclude defines a list of filters for attribute values. + // If the list is not empty, metrics with matching resource attribute values will not be emitted. + // MetricsInclude has higher priority than MetricsExclude. + MetricsExclude []filter.Config `mapstructure:"metrics_exclude"` + {{- end }} enabledSetByUser bool } diff --git a/cmd/mdatagen/templates/metrics.go.tmpl b/cmd/mdatagen/templates/metrics.go.tmpl index c76623c40fc..14428451c1e 100644 --- a/cmd/mdatagen/templates/metrics.go.tmpl +++ b/cmd/mdatagen/templates/metrics.go.tmpl @@ -16,6 +16,9 @@ import ( {{- if .SemConvVersion }} conventions "go.opentelemetry.io/collector/semconv/v{{ .SemConvVersion }}" {{- end }} + {{ if .ResourceAttributes -}} + "go.opentelemetry.io/collector/filter" + {{- end }} ) {{ range $name, $info := .Attributes }} @@ -132,6 +135,10 @@ type MetricsBuilder struct { metricsCapacity int // maximum observed number of metrics per resource. metricsBuffer pmetric.Metrics // accumulates metrics data before emitting. buildInfo component.BuildInfo // contains version information. + {{- if .ResourceAttributes }} + resourceAttributeIncludeFilter map[string]filter.Filter + resourceAttributeExcludeFilter map[string]filter.Filter + {{- end }} {{- range $name, $metric := .Metrics }} metric{{ $name.Render }} metric{{ $name.Render }} {{- end }} @@ -177,7 +184,7 @@ func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.CreateSetting } {{- end }} {{- if $attr.Warnings.IfConfigured }} - if mbc.ResourceAttributes.{{ $name.Render }}.enabledSetByUser { + if mbc.ResourceAttributes.{{ $name.Render }}.enabledSetByUser || mbc.ResourceAttributes.{{ $name.Render }}.MetricsInclude != nil || mbc.ResourceAttributes.{{ $name.Render }}.MetricsExclude != nil { settings.Logger.Warn("[WARNING] `{{ $name }}` should not be configured: {{ $attr.Warnings.IfConfigured }}") } {{- end }} @@ -190,7 +197,20 @@ func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.CreateSetting {{- range $name, $metric := .Metrics }} metric{{ $name.Render }}: newMetric{{ $name.Render }}(mbc.Metrics.{{ $name.Render }}), {{- end }} + {{ if .ResourceAttributes -}} + resourceAttributeIncludeFilter: make(map[string]filter.Filter), + resourceAttributeExcludeFilter: make(map[string]filter.Filter), + {{- end }} } + {{- range $name, $attr := .ResourceAttributes }} + if mbc.ResourceAttributes.{{ $name.Render }}.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["{{ $name }}"] = filter.CreateFilter(mbc.ResourceAttributes.{{ $name.Render }}.MetricsInclude) + } + if mbc.ResourceAttributes.{{ $name.Render }}.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["{{ $name }}"] = filter.CreateFilter(mbc.ResourceAttributes.{{ $name.Render }}.MetricsExclude) + } + {{- end }} + for _, op := range options { op(mb) } @@ -263,6 +283,19 @@ func (mb *MetricsBuilder) EmitForResource(rmo ...ResourceMetricsOption) { for _, op := range rmo { op(rm) } + {{ if .ResourceAttributes -}} + for attr, filter := range mb.resourceAttributeIncludeFilter { + if val, ok := rm.Resource().Attributes().Get(attr); ok && !filter.Matches(val.AsString()) { + return + } + } + for attr, filter := range mb.resourceAttributeExcludeFilter { + if val, ok := rm.Resource().Attributes().Get(attr); ok && filter.Matches(val.AsString()) { + return + } + } + {{- end }} + if ils.Metrics().Len() > 0 { mb.updateCapacity(rm) rm.MoveTo(mb.metricsBuffer.ResourceMetrics().AppendEmpty()) diff --git a/cmd/mdatagen/templates/metrics_test.go.tmpl b/cmd/mdatagen/templates/metrics_test.go.tmpl index bf7b09d05a9..13342842eab 100644 --- a/cmd/mdatagen/templates/metrics_test.go.tmpl +++ b/cmd/mdatagen/templates/metrics_test.go.tmpl @@ -14,31 +14,46 @@ import ( ) -type testConfigCollection int +type testDataSet int const ( - testSetDefault testConfigCollection = iota - testSetAll - testSetNone + testDataSetDefault testDataSet = iota + testDataSetAll + testDataSetNone ) func TestMetricsBuilder(t *testing.T) { tests := []struct { - name string - configSet testConfigCollection + name string + metricsSet testDataSet + resAttrsSet testDataSet + expectEmpty bool }{ { - name: "default", - configSet: testSetDefault, + name: "default", }, { - name: "all_set", - configSet: testSetAll, + name: "all_set", + metricsSet: testDataSetAll, + resAttrsSet: testDataSetAll, }, { - name: "none_set", - configSet: testSetNone, + name: "none_set", + metricsSet: testDataSetNone, + resAttrsSet: testDataSetNone, + expectEmpty: true, }, + {{- if .ResourceAttributes }} + { + name: "filter_set_include", + resAttrsSet: testDataSetAll, + }, + { + name: "filter_set_exclude", + resAttrsSet: testDataSetAll, + expectEmpty: true, + }, + {{- end }} } for _, test := range tests { t.Run(test.name, func(t *testing.T) { @@ -52,19 +67,19 @@ func TestMetricsBuilder(t *testing.T) { expectedWarnings := 0 {{- range $name, $metric := .Metrics }} {{- if and $metric.Enabled $metric.Warnings.IfEnabled }} - if test.configSet == testSetDefault || test.configSet == testSetAll { + if test.metricsSet == testDataSetDefault || test.metricsSet == testDataSetAll { 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 { + if test.metricsSet == testDataSetDefault { 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 { + if test.metricsSet == testDataSetAll || test.metricsSet == testDataSetNone { assert.Equal(t, "[WARNING] `{{ $name }}` should not be configured: {{ $metric.Warnings.IfConfigured }}", observedLogs.All()[expectedWarnings].Message) expectedWarnings++ } @@ -72,19 +87,19 @@ func TestMetricsBuilder(t *testing.T) { {{- end }} {{- range $name, $attr := .ResourceAttributes }} {{- if and $attr.Enabled $attr.Warnings.IfEnabled }} - if test.configSet == testSetDefault || test.configSet == testSetAll { + if test.resAttrsSet == testDataSetDefault || test.resAttrsSet == testDataSetAll { 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 { + if test.resAttrsSet == testDataSetDefault { 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 { + if test.resAttrsSet == testDataSetAll || test.resAttrsSet == testDataSetNone { assert.Equal(t, "[WARNING] `{{ $name }}` should not be configured: {{ $attr.Warnings.IfConfigured }}", observedLogs.All()[expectedWarnings].Message) expectedWarnings++ } @@ -121,7 +136,7 @@ func TestMetricsBuilder(t *testing.T) { {{- end }} metrics := mb.Emit(WithResource(res)) - if test.configSet == testSetNone { + if test.expectEmpty { assert.Equal(t, 0, metrics.ResourceMetrics().Len()) return } @@ -131,10 +146,10 @@ func TestMetricsBuilder(t *testing.T) { assert.Equal(t, res, rm.Resource()) assert.Equal(t, 1, rm.ScopeMetrics().Len()) ms := rm.ScopeMetrics().At(0).Metrics() - if test.configSet == testSetDefault { + if test.metricsSet == testDataSetDefault { assert.Equal(t, defaultMetricsCount, ms.Len()) } - if test.configSet == testSetAll { + if test.metricsSet == testDataSetAll { assert.Equal(t, allMetricsCount, ms.Len()) } validatedMetrics := make(map[string]bool) diff --git a/cmd/mdatagen/templates/package_test.go.tmpl b/cmd/mdatagen/templates/package_test.go.tmpl new file mode 100644 index 00000000000..d0c8f823748 --- /dev/null +++ b/cmd/mdatagen/templates/package_test.go.tmpl @@ -0,0 +1,25 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package {{ .Package }} + +import ( + "testing" + + {{- if not .Tests.GoLeak.Skip }} + "go.uber.org/goleak" + {{- end }} +) + +func TestMain(m *testing.M) { + {{- if .Tests.GoLeak.Setup }} + {{.Tests.GoLeak.Setup}} + {{- end }} + {{- if .Tests.GoLeak.Skip }} + // skipping goleak test as per metadata.yml configuration + {{- else }} + goleak.VerifyTestMain(m {{- range $val := .Tests.GoLeak.Ignore.Top}}, goleak.IgnoreTopFunction("{{$val}}"){{end}}{{- range $val := .Tests.GoLeak.Ignore.Any}}, goleak.IgnoreAnyFunction("{{$val}}"){{end}} ) + {{- end }} + {{- if .Tests.GoLeak.Teardown }} + {{.Tests.GoLeak.Teardown}} + {{- end }} +} diff --git a/cmd/mdatagen/templates/readme.md.tmpl b/cmd/mdatagen/templates/readme.md.tmpl index ad41f11dd42..3ead446b982 100644 --- a/cmd/mdatagen/templates/readme.md.tmpl +++ b/cmd/mdatagen/templates/readme.md.tmpl @@ -7,10 +7,13 @@ {{- 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 }} | +| {{ if not $idx }}Stability{{ else }} {{ end }} | [{{ toLowerCase $stability.String }}]{{ if ne $class "extension" }}: {{ stringsJoin $value ", " }} {{ end }} | {{- $idx = inc $idx }} {{- end }} {{- end}} +{{- if .Status.UnsupportedPlatforms }} +| Unsupported Platforms | {{ stringsJoin .Status.UnsupportedPlatforms ", " }} | +{{- end }} {{- if and (ne $class "cmd") (ne $class "pkg") }} | Distributions | [{{ stringsJoin .Status.SortedDistributions "], [" }}] | {{- end }} @@ -29,7 +32,7 @@ {{- end }} {{- end }} {{range $stability, $val := .Status.Stability}} -[{{ $stability }}]: https://github.com/open-telemetry/opentelemetry-collector#{{ $stability }} +[{{ toLowerCase $stability.String }}]: https://github.com/open-telemetry/opentelemetry-collector#{{ toLowerCase $stability.String }} {{- end }} {{- range .Status.SortedDistributions }} [{{.}}]: {{ distroURL . }} @@ -43,7 +46,7 @@ {{- range $stability, $pipelines := .Status.Stability }} {{- range $pipeline := $pipelines }} {{- $parts := stringsSplit $pipeline "_to_" }} -| {{index $parts 0}} | {{index $parts 1}} | [{{$stability}}] | +| {{index $parts 0}} | {{index $parts 1}} | [{{ toLowerCase $stability.String }}] | {{- end }} {{- end }} diff --git a/cmd/mdatagen/templates/status.go.tmpl b/cmd/mdatagen/templates/status.go.tmpl index d35cf76ff01..b90047f7dd0 100644 --- a/cmd/mdatagen/templates/status.go.tmpl +++ b/cmd/mdatagen/templates/status.go.tmpl @@ -3,28 +3,17 @@ package {{ .Package }} import ( - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/trace" + "go.opentelemetry.io/collector/component" ) var ( Type = component.MustNewType("{{ .Type }}") - scopeName = "{{ .ScopeName }}" ) const ( {{- range $stability, $signals := .Status.Stability }} {{- range $signal := $signals }} - {{ toCamelCase $signal }}Stability = component.StabilityLevel{{ casesTitle $stability }} + {{ toCamelCase $signal }}Stability = component.StabilityLevel{{ casesTitle $stability.String }} {{- 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/telemetry.go.tmpl b/cmd/mdatagen/templates/telemetry.go.tmpl new file mode 100644 index 00000000000..f0b430f3653 --- /dev/null +++ b/cmd/mdatagen/templates/telemetry.go.tmpl @@ -0,0 +1,17 @@ +// 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" +) + +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/telemetry_test.go.tmpl b/cmd/mdatagen/templates/telemetry_test.go.tmpl new file mode 100644 index 00000000000..073a53d2aec --- /dev/null +++ b/cmd/mdatagen/templates/telemetry_test.go.tmpl @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package {{ .Package }} + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "{{ .ScopeName }}", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "{{ .ScopeName }}", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/cmd/mdatagen/templates/testdata/config.yaml.tmpl b/cmd/mdatagen/templates/testdata/config.yaml.tmpl index 8b32773ec45..394646cc297 100644 --- a/cmd/mdatagen/templates/testdata/config.yaml.tmpl +++ b/cmd/mdatagen/templates/testdata/config.yaml.tmpl @@ -29,3 +29,25 @@ none_set: enabled: false {{- end }} {{- end }} +{{- if and .Metrics .ResourceAttributes }} +filter_set_include: + resource_attributes: + {{- range $name, $attr := .ResourceAttributes }} + {{ $name }}: + enabled: true + metrics_include: + - regexp: ".*" + {{- end }} +filter_set_exclude: + resource_attributes: + {{- range $name, $attr := .ResourceAttributes }} + {{ $name }}: + enabled: true + metrics_exclude: + {{- if eq $attr.Type.String "Str" }} + - strict: {{ $attr.TestValue }} + {{- else }} + - regexp: ".*" + {{- end }} + {{- end }} +{{- end }} diff --git a/cmd/mdatagen/testdata/metrics_and_type.yaml b/cmd/mdatagen/testdata/metrics_and_type.yaml index 81d66bde9c1..2306a08b35e 100644 --- a/cmd/mdatagen/testdata/metrics_and_type.yaml +++ b/cmd/mdatagen/testdata/metrics_and_type.yaml @@ -17,3 +17,7 @@ metrics: unit: s gauge: value_type: double + +tests: + skip_lifecycle: true + skip_shutdown: true diff --git a/cmd/mdatagen/testdata/resource_attributes_only.yaml b/cmd/mdatagen/testdata/resource_attributes_only.yaml index 05e031bcf45..a6fe611fe86 100644 --- a/cmd/mdatagen/testdata/resource_attributes_only.yaml +++ b/cmd/mdatagen/testdata/resource_attributes_only.yaml @@ -15,3 +15,7 @@ resource_attributes: description: Resource attribute 1. type: string enabled: true + +tests: + skip_lifecycle: true + skip_shutdown: true diff --git a/cmd/mdatagen/testdata/status_only.yaml b/cmd/mdatagen/testdata/status_only.yaml index 2365b43f1d9..d66977249dd 100644 --- a/cmd/mdatagen/testdata/status_only.yaml +++ b/cmd/mdatagen/testdata/status_only.yaml @@ -4,3 +4,7 @@ status: stability: beta: [traces, metrics, logs] distributions: [contrib] + +tests: + skip_lifecycle: true + skip_shutdown: true diff --git a/cmd/mdatagen/testdata/with_goleak_ignores.yaml b/cmd/mdatagen/testdata/with_goleak_ignores.yaml new file mode 100644 index 00000000000..18ee688ea38 --- /dev/null +++ b/cmd/mdatagen/testdata/with_goleak_ignores.yaml @@ -0,0 +1,14 @@ +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: + goleak: + ignore: + top: + - "testfunc1" + any: + - "testfunc2" \ No newline at end of file diff --git a/cmd/mdatagen/testdata/with_goleak_setup.yaml b/cmd/mdatagen/testdata/with_goleak_setup.yaml new file mode 100644 index 00000000000..de67c767af1 --- /dev/null +++ b/cmd/mdatagen/testdata/with_goleak_setup.yaml @@ -0,0 +1,10 @@ +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: + goleak: + setup: "setupFunc()" \ No newline at end of file diff --git a/cmd/mdatagen/testdata/with_goleak_skip.yaml b/cmd/mdatagen/testdata/with_goleak_skip.yaml new file mode 100644 index 00000000000..583d8af185d --- /dev/null +++ b/cmd/mdatagen/testdata/with_goleak_skip.yaml @@ -0,0 +1,10 @@ +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: + goleak: + skip: true \ No newline at end of file diff --git a/cmd/mdatagen/testdata/with_goleak_teardown.yaml b/cmd/mdatagen/testdata/with_goleak_teardown.yaml new file mode 100644 index 00000000000..51a1dc4cf2a --- /dev/null +++ b/cmd/mdatagen/testdata/with_goleak_teardown.yaml @@ -0,0 +1,10 @@ +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: + goleak: + teardown: "teardownFunc()" \ No newline at end of file diff --git a/cmd/mdatagen/testdata/with_tests_connector.yaml b/cmd/mdatagen/testdata/with_tests_connector.yaml index ad05872698e..2c1f542cca2 100644 --- a/cmd/mdatagen/testdata/with_tests_connector.yaml +++ b/cmd/mdatagen/testdata/with_tests_connector.yaml @@ -4,6 +4,3 @@ 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 index e110f3d10e3..44c9ccc5f9b 100644 --- a/cmd/mdatagen/testdata/with_tests_exporter.yaml +++ b/cmd/mdatagen/testdata/with_tests_exporter.yaml @@ -4,6 +4,3 @@ 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 index 08eb4d5cf29..1f201264155 100644 --- a/cmd/mdatagen/testdata/with_tests_extension.yaml +++ b/cmd/mdatagen/testdata/with_tests_extension.yaml @@ -4,6 +4,3 @@ 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 index fa6a2238f2c..d0df3f84f0e 100644 --- a/cmd/mdatagen/testdata/with_tests_processor.yaml +++ b/cmd/mdatagen/testdata/with_tests_processor.yaml @@ -4,6 +4,3 @@ 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 index e55c6190728..f3e35dc659c 100644 --- a/cmd/mdatagen/testdata/with_tests_receiver.yaml +++ b/cmd/mdatagen/testdata/with_tests_receiver.yaml @@ -4,6 +4,3 @@ status: class: receiver stability: beta: [traces, logs, metrics] - -tests: - config: diff --git a/cmd/mdatagen/validate.go b/cmd/mdatagen/validate.go index bc56375baf9..63108f29470 100644 --- a/cmd/mdatagen/validate.go +++ b/cmd/mdatagen/validate.go @@ -8,24 +8,22 @@ import ( "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) + errs = errors.Join(errs, err) } if err := md.validateStatus(); err != nil { - errs = multierr.Append(errs, err) + errs = errors.Join(errs, err) } if err := md.validateResourceAttributes(); err != nil { - errs = multierr.Append(errs, err) + errs = errors.Join(errs, err) } if err := md.validateMetrics(); err != nil { - errs = multierr.Append(errs, err) + errs = errors.Join(errs, err) } return errs } @@ -33,14 +31,20 @@ func (md *metadata) Validate() error { // 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 '_'. +// We allow '/' for subcomponents. // This must be kept in sync with the regex in component/config.go. -var typeRegexp = regexp.MustCompile(`^[a-zA-Z][0-9a-zA-Z_]*$`) +var typeRegexp = regexp.MustCompile(`^[a-zA-Z][0-9a-zA-Z_]{0,62}$`) func (md *metadata) validateType() error { if md.Type == "" { return errors.New("missing type") } + if md.Parent != "" { + // subcomponents are allowed to have a '/' in their type. + return nil + } + if !typeRegexp.MatchString(md.Type) { return fmt.Errorf("invalid character(s) in type %q", md.Type) } @@ -58,11 +62,11 @@ func (md *metadata) validateStatus() error { return errors.New("missing status") } if err := md.Status.validateClass(); err != nil { - errs = multierr.Append(errs, err) + errs = errors.Join(errs, err) } if md.Parent == "" { if err := md.Status.validateStability(); err != nil { - errs = multierr.Append(errs, err) + errs = errors.Join(errs, err) } } return errs @@ -84,11 +88,8 @@ func (s *Status) validateStability() error { 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)) + if len(component) == 0 { + errs = errors.Join(errs, fmt.Errorf("missing component for stability: %v", stability)) } for _, c := range component { if c != "metrics" && @@ -104,7 +105,7 @@ func (s *Status) validateStability() error { c != "logs_to_metrics" && c != "logs_to_logs" && c != "extension" { - errs = multierr.Append(errs, fmt.Errorf("invalid component: %v", c)) + errs = errors.Join(errs, fmt.Errorf("invalid component: %v", c)) } } } @@ -115,11 +116,11 @@ 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)) + errs = errors.Join(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)) + errs = errors.Join(errs, fmt.Errorf("empty type for resource attribute: %v", name)) } } return errs @@ -130,17 +131,17 @@ func (md *metadata) validateMetrics() 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, "+ + errs = errors.Join(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, "+ + errs = errors.Join(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)) + errs = errors.Join(errs, fmt.Errorf(`metric "%v": %w`, mn, err)) continue } unknownAttrs := make([]attributeName, 0, len(m.Attributes)) @@ -152,26 +153,26 @@ func (md *metadata) validateMetrics() error { } } if len(unknownAttrs) > 0 { - errs = multierr.Append(errs, fmt.Errorf(`metric "%v" refers to undefined attributes: %v`, mn, unknownAttrs)) + errs = errors.Join(errs, fmt.Errorf(`metric "%v" refers to undefined attributes: %v`, mn, unknownAttrs)) } } - errs = multierr.Append(errs, md.validateAttributes(usedAttrs)) + errs = errors.Join(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`)) + errs = errors.Join(errs, errors.New(`missing metric description`)) } if m.Unit == nil { - errs = multierr.Append(errs, errors.New(`missing metric unit`)) + errs = errors.Join(errs, errors.New(`missing metric unit`)) } if m.Sum != nil { - errs = multierr.Append(errs, m.Sum.Validate()) + errs = errors.Join(errs, m.Sum.Validate()) } if m.Gauge != nil { - errs = multierr.Append(errs, m.Gauge.Validate()) + errs = errors.Join(errs, m.Gauge.Validate()) } return errs } @@ -188,18 +189,18 @@ func (md *metadata) validateAttributes(usedAttrs map[attributeName]bool) 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)) + errs = errors.Join(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)) + errs = errors.Join(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)) + errs = errors.Join(errs, fmt.Errorf("unused attributes: %v", unusedAttrs)) } return errs } diff --git a/cmd/mdatagen/validate_test.go b/cmd/mdatagen/validate_test.go index 4c2ddea5741..b64ca66e77c 100644 --- a/cmd/mdatagen/validate_test.go +++ b/cmd/mdatagen/validate_test.go @@ -40,11 +40,11 @@ func TestValidate(t *testing.T) { }, { name: "testdata/invalid_stability.yaml", - wantErr: "invalid stability: incorrectstability", + wantErr: "1 error(s) decoding:\n\n* error decoding 'status.stability': invalid stability level: incorrectstability", }, { name: "testdata/no_stability_component.yaml", - wantErr: "missing component for stability: beta", + wantErr: "missing component for stability: Beta", }, { name: "testdata/invalid_stability_component.yaml", diff --git a/cmd/otelcorecol/builder-config.yaml b/cmd/otelcorecol/builder-config.yaml index d528d09964d..8d8f88ad980 100644 --- a/cmd/otelcorecol/builder-config.yaml +++ b/cmd/otelcorecol/builder-config.yaml @@ -2,25 +2,34 @@ dist: module: go.opentelemetry.io/collector/cmd/otelcorecol name: otelcorecol description: Local OpenTelemetry Collector binary, testing only. - version: 0.96.0-dev - otelcol_version: 0.96.0 + version: 0.100.0-dev + otelcol_version: 0.100.0 receivers: - - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.96.0 + - gomod: go.opentelemetry.io/collector/receiver/nopreceiver v0.100.0 + - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.100.0 exporters: - - 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 + - gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.100.0 + - gomod: go.opentelemetry.io/collector/exporter/loggingexporter v0.100.0 + - gomod: go.opentelemetry.io/collector/exporter/nopexporter v0.100.0 + - gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.100.0 + - gomod: go.opentelemetry.io/collector/exporter/otlphttpexporter v0.100.0 extensions: - - 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 + - gomod: go.opentelemetry.io/collector/extension/ballastextension v0.100.0 + - gomod: go.opentelemetry.io/collector/extension/memorylimiterextension v0.100.0 + - gomod: go.opentelemetry.io/collector/extension/zpagesextension v0.100.0 processors: - - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.96.0 - - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.96.0 + - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.100.0 + - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.100.0 connectors: - - gomod: go.opentelemetry.io/collector/connector/forwardconnector v0.96.0 + - gomod: go.opentelemetry.io/collector/connector/forwardconnector v0.100.0 + +providers: + - gomod: go.opentelemetry.io/collector/confmap/provider/envprovider v0.100.0 + - gomod: go.opentelemetry.io/collector/confmap/provider/fileprovider v0.100.0 + - gomod: go.opentelemetry.io/collector/confmap/provider/httpprovider v0.100.0 + - gomod: go.opentelemetry.io/collector/confmap/provider/httpsprovider v0.100.0 + - gomod: go.opentelemetry.io/collector/confmap/provider/yamlprovider v0.100.0 replaces: - go.opentelemetry.io/collector => ../../ @@ -49,6 +58,7 @@ replaces: - go.opentelemetry.io/collector/exporter => ../../exporter - go.opentelemetry.io/collector/exporter/debugexporter => ../../exporter/debugexporter - go.opentelemetry.io/collector/exporter/loggingexporter => ../../exporter/loggingexporter + - go.opentelemetry.io/collector/exporter/nopexporter => ../../exporter/nopexporter - go.opentelemetry.io/collector/exporter/otlpexporter => ../../exporter/otlpexporter - go.opentelemetry.io/collector/exporter/otlphttpexporter => ../../exporter/otlphttpexporter - go.opentelemetry.io/collector/extension => ../../extension @@ -58,8 +68,10 @@ replaces: - go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension - go.opentelemetry.io/collector/featuregate => ../../featuregate - go.opentelemetry.io/collector/pdata => ../../pdata + - go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata - go.opentelemetry.io/collector/processor => ../../processor - go.opentelemetry.io/collector/receiver => ../../receiver + - go.opentelemetry.io/collector/receiver/nopreceiver => ../../receiver/nopreceiver - go.opentelemetry.io/collector/receiver/otlpreceiver => ../../receiver/otlpreceiver - go.opentelemetry.io/collector/processor/batchprocessor => ../../processor/batchprocessor - go.opentelemetry.io/collector/processor/memorylimiterprocessor => ../../processor/memorylimiterprocessor diff --git a/cmd/otelcorecol/components.go b/cmd/otelcorecol/components.go index 786743099b9..9f8a7d45b06 100644 --- a/cmd/otelcorecol/components.go +++ b/cmd/otelcorecol/components.go @@ -8,6 +8,7 @@ import ( "go.opentelemetry.io/collector/exporter" debugexporter "go.opentelemetry.io/collector/exporter/debugexporter" loggingexporter "go.opentelemetry.io/collector/exporter/loggingexporter" + nopexporter "go.opentelemetry.io/collector/exporter/nopexporter" otlpexporter "go.opentelemetry.io/collector/exporter/otlpexporter" otlphttpexporter "go.opentelemetry.io/collector/exporter/otlphttpexporter" "go.opentelemetry.io/collector/extension" @@ -19,6 +20,7 @@ import ( batchprocessor "go.opentelemetry.io/collector/processor/batchprocessor" memorylimiterprocessor "go.opentelemetry.io/collector/processor/memorylimiterprocessor" "go.opentelemetry.io/collector/receiver" + nopreceiver "go.opentelemetry.io/collector/receiver/nopreceiver" otlpreceiver "go.opentelemetry.io/collector/receiver/otlpreceiver" ) @@ -36,6 +38,7 @@ func components() (otelcol.Factories, error) { } factories.Receivers, err = receiver.MakeFactoryMap( + nopreceiver.NewFactory(), otlpreceiver.NewFactory(), ) if err != nil { @@ -45,6 +48,7 @@ func components() (otelcol.Factories, error) { factories.Exporters, err = exporter.MakeFactoryMap( debugexporter.NewFactory(), loggingexporter.NewFactory(), + nopexporter.NewFactory(), otlpexporter.NewFactory(), otlphttpexporter.NewFactory(), ) diff --git a/cmd/otelcorecol/components_test.go b/cmd/otelcorecol/components_test.go deleted file mode 100644 index 0e08cdb02d1..00000000000 --- a/cmd/otelcorecol/components_test.go +++ /dev/null @@ -1,41 +0,0 @@ -// Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT. - -package main - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "go.opentelemetry.io/collector/component/componenttest" -) - -func TestValidateConfigs(t *testing.T) { - factories, err := components() - assert.NoError(t, err) - - for k, factory := range factories.Receivers { - assert.Equal(t, k, factory.Type()) - assert.NoError(t, componenttest.CheckConfigStruct(factory.CreateDefaultConfig())) - } - - for k, factory := range factories.Processors { - assert.Equal(t, k, factory.Type()) - assert.NoError(t, componenttest.CheckConfigStruct(factory.CreateDefaultConfig())) - } - - for k, factory := range factories.Exporters { - assert.Equal(t, k, factory.Type()) - assert.NoError(t, componenttest.CheckConfigStruct(factory.CreateDefaultConfig())) - } - - for k, factory := range factories.Connectors { - assert.Equal(t, k, factory.Type()) - assert.NoError(t, componenttest.CheckConfigStruct(factory.CreateDefaultConfig())) - } - - for k, factory := range factories.Extensions { - assert.Equal(t, k, factory.Type()) - assert.NoError(t, componenttest.CheckConfigStruct(factory.CreateDefaultConfig())) - } -} diff --git a/cmd/otelcorecol/go.mod b/cmd/otelcorecol/go.mod index a9a702bd1b5..9fda292e0f7 100644 --- a/cmd/otelcorecol/go.mod +++ b/cmd/otelcorecol/go.mod @@ -5,35 +5,41 @@ module go.opentelemetry.io/collector/cmd/otelcorecol go 1.21 require ( - github.com/stretchr/testify v1.8.4 - 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.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/confmap/converter/expandconverter v0.100.0 + go.opentelemetry.io/collector/confmap/provider/envprovider v0.100.0 + go.opentelemetry.io/collector/confmap/provider/fileprovider v0.100.0 + go.opentelemetry.io/collector/confmap/provider/httpprovider v0.100.0 + go.opentelemetry.io/collector/confmap/provider/httpsprovider v0.100.0 + go.opentelemetry.io/collector/confmap/provider/yamlprovider v0.100.0 + go.opentelemetry.io/collector/connector v0.100.0 + go.opentelemetry.io/collector/connector/forwardconnector v0.100.0 + go.opentelemetry.io/collector/exporter v0.100.0 + go.opentelemetry.io/collector/exporter/debugexporter v0.100.0 + go.opentelemetry.io/collector/exporter/loggingexporter v0.100.0 + go.opentelemetry.io/collector/exporter/nopexporter v0.100.0 + go.opentelemetry.io/collector/exporter/otlpexporter v0.100.0 + go.opentelemetry.io/collector/exporter/otlphttpexporter v0.100.0 + go.opentelemetry.io/collector/extension v0.100.0 + go.opentelemetry.io/collector/extension/ballastextension v0.100.0 + go.opentelemetry.io/collector/extension/memorylimiterextension v0.100.0 + go.opentelemetry.io/collector/extension/zpagesextension v0.100.0 + go.opentelemetry.io/collector/otelcol v0.100.0 + go.opentelemetry.io/collector/processor v0.100.0 + go.opentelemetry.io/collector/processor/batchprocessor v0.100.0 + go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.100.0 + go.opentelemetry.io/collector/receiver v0.100.0 + go.opentelemetry.io/collector/receiver/nopreceiver v0.100.0 + go.opentelemetry.io/collector/receiver/otlpreceiver v0.100.0 go.uber.org/goleak v1.3.0 - golang.org/x/sys v0.17.0 + golang.org/x/sys v0.19.0 ) require ( - 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/cenkalti/backoff/v4 v4.3.0 // 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 @@ -42,92 +48,83 @@ require ( 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.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // 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.7 // indirect + github.com/klauspost/compress v1.17.8 // 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/knadh/koanf/v2 v2.1.1 // 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/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/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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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/shirou/gopsutil/v3 v3.24.3 // indirect github.com/shoenig/go-m1cpu v0.1.6 // 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 + github.com/yusufpapurcu/wmi v1.2.4 // indirect go.opencensus.io v0.24.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.opentelemetry.io/collector v0.100.0 // indirect + go.opentelemetry.io/collector/config/configauth v0.100.0 // indirect + go.opentelemetry.io/collector/config/configcompression v1.7.0 // indirect + go.opentelemetry.io/collector/config/configgrpc v0.100.0 // indirect + go.opentelemetry.io/collector/config/confighttp v0.100.0 // indirect + go.opentelemetry.io/collector/config/confignet v0.100.0 // indirect + go.opentelemetry.io/collector/config/configopaque v1.7.0 // indirect + go.opentelemetry.io/collector/config/configretry v0.100.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/config/configtls v0.100.0 // indirect + go.opentelemetry.io/collector/config/internal v0.100.0 // indirect + go.opentelemetry.io/collector/consumer v0.100.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.100.0 // indirect + go.opentelemetry.io/collector/featuregate v1.7.0 // indirect + go.opentelemetry.io/collector/pdata v1.7.0 // indirect + go.opentelemetry.io/collector/semconv v0.100.0 // indirect + go.opentelemetry.io/collector/service v0.100.0 // indirect + go.opentelemetry.io/contrib/config v0.6.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.26.0 // indirect + go.opentelemetry.io/contrib/zpages v0.51.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/bridge/opencensus v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 // indirect + go.opentelemetry.io/otel/metric v1.26.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.opentelemetry.io/otel/trace v1.26.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.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/oauth2 v0.17.0 // indirect + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect + golang.org/x/net v0.24.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-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 + gonum.org/v1/gonum v0.15.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -183,6 +180,8 @@ replace go.opentelemetry.io/collector/exporter/debugexporter => ../../exporter/d replace go.opentelemetry.io/collector/exporter/loggingexporter => ../../exporter/loggingexporter +replace go.opentelemetry.io/collector/exporter/nopexporter => ../../exporter/nopexporter + replace go.opentelemetry.io/collector/exporter/otlpexporter => ../../exporter/otlpexporter replace go.opentelemetry.io/collector/exporter/otlphttpexporter => ../../exporter/otlphttpexporter @@ -201,10 +200,14 @@ replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata + replace go.opentelemetry.io/collector/processor => ../../processor replace go.opentelemetry.io/collector/receiver => ../../receiver +replace go.opentelemetry.io/collector/receiver/nopreceiver => ../../receiver/nopreceiver + replace go.opentelemetry.io/collector/receiver/otlpreceiver => ../../receiver/otlpreceiver replace go.opentelemetry.io/collector/processor/batchprocessor => ../../processor/batchprocessor diff --git a/cmd/otelcorecol/go.sum b/cmd/otelcorecol/go.sum index b8a1209e827..13c5f8a3f42 100644 --- a/cmd/otelcorecol/go.sum +++ b/cmd/otelcorecol/go.sum @@ -1,21 +1,14 @@ 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/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/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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/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/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/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= @@ -24,8 +17,6 @@ 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/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= @@ -55,9 +46,6 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W 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= @@ -66,7 +54,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -75,8 +62,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= 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= @@ -85,14 +72,14 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr 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/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/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/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -117,10 +104,10 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:Om 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.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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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= @@ -128,8 +115,8 @@ github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUz 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/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= -github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= +github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE= +github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg= 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= @@ -141,62 +128,64 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An 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/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 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= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/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/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.opentelemetry.io/contrib/config v0.6.0 h1:M1SRD1Z15XHPGk61tMLI1up77XT5FdrqQSRrlH0fYuk= +go.opentelemetry.io/contrib/config v0.6.0/go.mod h1:t+/kzmRWLN7J+4F/dD4fFvlYCmCO63WYwy/B00IC++c= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 h1:A3SayB3rNyt+1S6qpI9mHPkeHTZbD7XILEqWnYZb2l0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0/go.mod h1:27iA5uvhuRNmalO+iEUdVn5ZMj2qy10Mm+XRIpRmyuU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 h1:Xs2Ncz0gNihqu9iosIZ5SkBbWo5T8JhhLJFMQL1qmLI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0/go.mod h1:vy+2G/6NvVMpwGX/NyLqcC41fxepnuKHk16E6IZUcJc= +go.opentelemetry.io/contrib/propagators/b3 v1.26.0 h1:wgFbVA+bK2k+fGVfDOCOG4cfDAoppyr5sI2dVlh8MWM= +go.opentelemetry.io/contrib/propagators/b3 v1.26.0/go.mod h1:DDktFXxA+fyItAAM0Sbl5OBH7KOsCTjvbBdPKtoIf/k= +go.opentelemetry.io/contrib/zpages v0.51.0 h1:psVr4JTWd0qtISPj9EA6AODGJ09bvsOxWiuKqiGdSCA= +go.opentelemetry.io/contrib/zpages v0.51.0/go.mod h1:PKtp+NEp1gTTLmFHpynYgYCSkKtisPntOb9S1mQjFKg= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/bridge/opencensus v1.26.0 h1:DZzxj9QjznMVoehskOJnFP2gsTCWtDTFBDvFhPAY7nc= +go.opentelemetry.io/otel/bridge/opencensus v1.26.0/go.mod h1:rJiX0KrF5m8Tm1XE8jLczpAv5zUaDcvhKecFG0ZoFG4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 h1:+hm+I+KigBy3M24/h1p/NHkUx/evbLH0PNcjpMyCHc4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0/go.mod h1:NjC8142mLvvNT6biDpaMjyz78kyEHIwAJlSX0N9P5KI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 h1:HGZWGmCVRCVyAs2GQaiHQPbDHo+ObFWeUEOd+zDnp64= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0/go.mod h1:SaH+v38LSCHddyk7RGlU9uZyQoRrKao6IBnJw6Kbn+c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 h1:1u/AyyOqAWzy+SkPxDpahCNZParHV8Vid1RnI2clyDE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0/go.mod h1:z46paqbJ9l7c9fIPCXTqTGwhQZ5XoTIsfeFYWboizjs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 h1:Waw9Wfpo/IXzOI8bCB7DIk+0JZcqqsyn1JFnAc+iam8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0/go.mod h1:wnJIG4fOqyynOnnQF/eQb4/16VlX2EJAHhHgqIqWfAo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 h1:1wp/gyxsuYtuE/JFxsQRtcCDtMrO2qMvlfXALU5wkzI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0/go.mod h1:gbTHmghkGgqxMomVQQMur1Nba4M0MQ8AYThXDUjsJ38= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 h1:5fnmgteaar1VcAA69huatudPduNFz7guRtCmfZCooZI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0/go.mod h1:lsPccfZiz1cb1AhBPmicWM2E4F1VynFXEvD8SEBS4TM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 h1:0W5o9SzoR15ocYHEQfvfipzcNog1lBxOLfnex91Hk6s= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0/go.mod h1:zVZ8nz+VSggWmnh6tTsJqXQ7rU4xLwRtna1M4x5jq58= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= 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= @@ -207,8 +196,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk 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-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= 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= @@ -223,11 +212,9 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -241,9 +228,9 @@ 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.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/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -260,28 +247,26 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= -gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= +gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= +gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= 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.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-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -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/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 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.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= -google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 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= @@ -291,10 +276,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 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/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= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/cmd/otelcorecol/main.go b/cmd/otelcorecol/main.go index 2ab2d3c7249..beaeb912ee4 100644 --- a/cmd/otelcorecol/main.go +++ b/cmd/otelcorecol/main.go @@ -7,6 +7,13 @@ import ( "log" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/confmap" + "go.opentelemetry.io/collector/confmap/converter/expandconverter" + envprovider "go.opentelemetry.io/collector/confmap/provider/envprovider" + fileprovider "go.opentelemetry.io/collector/confmap/provider/fileprovider" + httpprovider "go.opentelemetry.io/collector/confmap/provider/httpprovider" + httpsprovider "go.opentelemetry.io/collector/confmap/provider/httpsprovider" + yamlprovider "go.opentelemetry.io/collector/confmap/provider/yamlprovider" "go.opentelemetry.io/collector/otelcol" ) @@ -14,10 +21,29 @@ func main() { info := component.BuildInfo{ Command: "otelcorecol", Description: "Local OpenTelemetry Collector binary, testing only.", - Version: "0.96.0-dev", + Version: "0.100.0-dev", } - if err := run(otelcol.CollectorSettings{BuildInfo: info, Factories: components}); err != nil { + set := otelcol.CollectorSettings{ + BuildInfo: info, + Factories: components, + ConfigProviderSettings: otelcol.ConfigProviderSettings{ + ResolverSettings: confmap.ResolverSettings{ + ProviderFactories: []confmap.ProviderFactory{ + envprovider.NewFactory(), + fileprovider.NewFactory(), + httpprovider.NewFactory(), + httpsprovider.NewFactory(), + yamlprovider.NewFactory(), + }, + ConverterFactories: []confmap.ConverterFactory{ + expandconverter.NewFactory(), + }, + }, + }, + } + + if err := run(set); err != nil { log.Fatal(err) } } diff --git a/cmd/otelcorecol/package_test.go b/cmd/otelcorecol/package_test.go index c5c48c671cc..5cd502ca564 100644 --- a/cmd/otelcorecol/package_test.go +++ b/cmd/otelcorecol/package_test.go @@ -9,9 +9,6 @@ import ( "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")) + goleak.VerifyTestMain(m) } diff --git a/component/component.go b/component/component.go index 32d69f7eda0..c7f6408680a 100644 --- a/component/component.go +++ b/component/component.go @@ -9,12 +9,6 @@ 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 // Component if the particular telemetry data type is not supported by the receiver, exporter or processor. ErrDataTypeIsNotSupported = errors.New("telemetry type is not supported") diff --git a/component/componenttest/nop_host_test.go b/component/componenttest/nop_host_test.go index 4aada24b1be..111c8f33574 100644 --- a/component/componenttest/nop_host_test.go +++ b/component/componenttest/nop_host_test.go @@ -17,7 +17,6 @@ func TestNewNopHost(t *testing.T) { require.NotNil(t, nh) require.IsType(t, &nopHost{}, nh) - assert.Nil(t, nh.GetExporters()) // nolint: staticcheck assert.Nil(t, nh.GetExtensions()) assert.Nil(t, nh.GetFactory(component.KindReceiver, component.MustNewType("test"))) } diff --git a/component/componenttest/otelprometheuschecker.go b/component/componenttest/otelprometheuschecker.go index 878bfd0a37a..5beef52373a 100644 --- a/component/componenttest/otelprometheuschecker.go +++ b/component/componenttest/otelprometheuschecker.go @@ -196,7 +196,7 @@ func attributesForProcessorMetrics(processor component.ID) []attribute.KeyValue return []attribute.KeyValue{attribute.String(processorTag, processor.String())} } -// attributesForReceiverMetrics returns the attributes that are needed for the receiver metrics. +// attributesForExporterMetrics returns the attributes that are needed for the receiver metrics. func attributesForExporterMetrics(exporter component.ID) []attribute.KeyValue { return []attribute.KeyValue{attribute.String(exporterTag, exporter.String())} } diff --git a/component/config.go b/component/config.go index f54b3a176c2..49cc7f5219f 100644 --- a/component/config.go +++ b/component/config.go @@ -110,18 +110,25 @@ func callValidateIfPossible(v reflect.Value) error { } // Type is the component type as it is used in the config. -type Type string +type Type struct { + name string +} // String returns the string representation of the type. func (t Type) String() string { - return string(t) + return t.name +} + +// MarshalText marshals returns the Type name. +func (t Type) MarshalText() ([]byte, error) { + return []byte(t.name), nil } // 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_]*$`) +var typeRegexp = regexp.MustCompile(`^[a-zA-Z][0-9a-zA-Z_]{0,62}$`) // NewType creates a type. It returns an error if the type is invalid. // A type must @@ -130,12 +137,12 @@ var typeRegexp = regexp.MustCompile(`^[a-zA-Z][0-9a-zA-Z_]*$`) // - 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") + 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{}, fmt.Errorf("invalid character(s) in type %q", ty) } - return Type(ty), nil + return Type{name: ty}, nil } // MustNewType creates a type. It panics if the type is invalid. @@ -155,14 +162,18 @@ func MustNewType(strType string) Type { // collecting metrics, traces and logs, this can expand in the future. type DataType = Type +func mustNewDataType(strType string) DataType { + return MustNewType(strType) +} + // Currently supported data types. Add new data types here when new types are supported in the future. -const ( +var ( // DataTypeTraces is the data type tag for traces. - DataTypeTraces DataType = "traces" + DataTypeTraces = mustNewDataType("traces") // DataTypeMetrics is the data type tag for metrics. - DataTypeMetrics DataType = "metrics" + DataTypeMetrics = mustNewDataType("metrics") // DataTypeLogs is the data type tag for logs. - DataTypeLogs DataType = "logs" + DataTypeLogs = mustNewDataType("logs") ) diff --git a/component/config_test.go b/component/config_test.go index fcddc343d20..caed4dc20ab 100644 --- a/component/config_test.go +++ b/component/config_test.go @@ -7,13 +7,16 @@ import ( "errors" "fmt" "reflect" + "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/confmap" ) -var _ fmt.Stringer = (Type)("") +var _ fmt.Stringer = Type{} type configChildStruct struct { Child errConfig @@ -395,6 +398,7 @@ func TestNewType(t *testing.T) { {name: "zipkin_encoding"}, {name: "zookeeper"}, {name: "zpages"}, + {name: strings.Repeat("a", 63)}, {name: "", shouldErr: true}, {name: "contains spaces", shouldErr: true}, @@ -403,6 +407,7 @@ func TestNewType(t *testing.T) { {name: "contains/slash", shouldErr: true}, {name: "contains:colon", shouldErr: true}, {name: "contains#hash", shouldErr: true}, + {name: strings.Repeat("a", 64), shouldErr: true}, } for _, tt := range tests { @@ -417,3 +422,28 @@ func TestNewType(t *testing.T) { }) } } + +type configWithEmbeddedStruct struct { + String string `mapstructure:"string"` + Num int `mapstructure:"num"` + embeddedUnmarshallingConfig +} + +type embeddedUnmarshallingConfig struct { +} + +func (euc *embeddedUnmarshallingConfig) Unmarshal(_ *confmap.Conf) error { + return nil // do nothing. +} +func TestStructWithEmbeddedUnmarshaling(t *testing.T) { + t.Skip("Skipping, to be fixed with https://github.com/open-telemetry/opentelemetry-collector/issues/7102") + cfgMap := confmap.NewFromStringMap(map[string]any{ + "string": "foo", + "num": 123, + }) + tc := &configWithEmbeddedStruct{} + err := UnmarshalConfig(cfgMap, tc) + require.NoError(t, err) + assert.Equal(t, "foo", tc.String) + assert.Equal(t, 123, tc.Num) +} diff --git a/component/doc.go b/component/doc.go index cef6b568edf..c7ac848a1ef 100644 --- a/component/doc.go +++ b/component/doc.go @@ -4,5 +4,5 @@ // Package component outlines the components used in the collector // and provides a foundation for the component’s creation and // termination process. A component can be either a receiver, exporter, -// processor, or an extension. +// processor, an extension, or a connector. package component // import "go.opentelemetry.io/collector/component" diff --git a/component/go.mod b/component/go.mod index 05298e470ba..41731120641 100644 --- a/component/go.mod +++ b/component/go.mod @@ -4,18 +4,18 @@ 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.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 + github.com/prometheus/client_model v0.6.1 + github.com/prometheus/common v0.53.0 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/otel v1.26.0 + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/sdk v1.26.0 + go.opentelemetry.io/otel/sdk/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 @@ -29,20 +29,19 @@ require ( 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.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/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/net v0.23.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/component/go.sum b/component/go.sum index 2f664245ecd..5467b123e44 100644 --- a/component/go.sum +++ b/component/go.sum @@ -13,10 +13,6 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -25,8 +21,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -39,30 +35,30 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.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.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -78,16 +74,16 @@ 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.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -100,14 +96,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/component/host.go b/component/host.go index 4b6933baaef..50472a6d88c 100644 --- a/component/host.go +++ b/component/host.go @@ -27,24 +27,4 @@ type Host interface { // GetExtensions can be called by the component anytime after Component.Start() begins and // until Component.Shutdown() ends. GetExtensions() map[ID]Component - - // GetExporters returns the map of exporters. Only enabled and created exporters will be returned. - // Typically is used to find exporters by type or by full config name. Both cases - // can be done by iterating the returned map. There are typically very few exporters, - // so there are no performance implications due to iteration. - // This returns a map by DataType of maps by exporter configs to the exporter instance. - // Note that an exporter with the same name may be attached to multiple pipelines and - // thus we may have an instance of the exporter for multiple data types. - // This is an experimental function that may change or even be removed completely. - // - // GetExporters can be called by the component anytime after Component.Start() begins and - // until Component.Shutdown() ends. - // - // Deprecated: [0.79.0] This function will be removed in the future. - // Several components in the contrib repository use this function so it cannot be removed - // before those cases are removed. In most cases, use of this function can be replaced by a - // connector. See https://github.com/open-telemetry/opentelemetry-collector/issues/7370 and - // https://github.com/open-telemetry/opentelemetry-collector/pull/7390#issuecomment-1483710184 - // for additional information. - GetExporters() map[DataType]map[ID]Component } diff --git a/component/telemetry.go b/component/telemetry.go index 572b4bdd916..17ca3dcab67 100644 --- a/component/telemetry.go +++ b/component/telemetry.go @@ -15,7 +15,7 @@ import ( // 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 with the exception of ReportStatus. 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 diff --git a/config/configauth/configauth.go b/config/configauth/configauth.go index 8e7d8edb41a..aa7002c270b 100644 --- a/config/configauth/configauth.go +++ b/config/configauth/configauth.go @@ -26,6 +26,11 @@ type Authentication struct { AuthenticatorID component.ID `mapstructure:"authenticator"` } +// NewDefaultAuthentication returns a default authentication configuration. +func NewDefaultAuthentication() *Authentication { + return &Authentication{} +} + // GetServerAuthenticator attempts to select the appropriate auth.Server from the list of extensions, // based on the requested extension name. If an authenticator is not found, an error is returned. func (a Authentication) GetServerAuthenticator(extensions map[component.ID]component.Component) (auth.Server, error) { diff --git a/config/configauth/configauth_test.go b/config/configauth/configauth_test.go index 43c84ceb497..e16289a1490 100644 --- a/config/configauth/configauth_test.go +++ b/config/configauth/configauth_test.go @@ -15,6 +15,12 @@ import ( var mockID = component.MustNewID("mock") +func TestNewDefaultAuthentication(t *testing.T) { + auth := NewDefaultAuthentication() + assert.NotNil(t, auth) + assert.Empty(t, auth) +} + func TestGetServer(t *testing.T) { testCases := []struct { desc string diff --git a/config/configauth/go.mod b/config/configauth/go.mod index a58c97c3449..072dce27655 100644 --- a/config/configauth/go.mod +++ b/config/configauth/go.mod @@ -3,10 +3,10 @@ module go.opentelemetry.io/collector/config/configauth go 1.21 require ( - github.com/stretchr/testify v1.8.4 - 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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/extension v0.100.0 + go.opentelemetry.io/collector/extension/auth v0.100.0 go.uber.org/goleak v1.3.0 ) @@ -14,27 +14,26 @@ 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.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 - 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.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/confmap v0.100.0 // indirect + go.opentelemetry.io/collector/pdata v1.7.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/metric v1.26.0 // indirect + go.opentelemetry.io/otel/trace v1.26.0 // indirect go.uber.org/multierr v1.11.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/net v0.23.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/config/configauth/go.sum b/config/configauth/go.sum index f0d91ce3b4d..624dd0f4bec 100644 --- a/config/configauth/go.sum +++ b/config/configauth/go.sum @@ -12,10 +12,6 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -24,8 +20,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -38,30 +34,30 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.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.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -77,16 +73,16 @@ 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.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -99,14 +95,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/config/configcompression/compressiontype.go b/config/configcompression/compressiontype.go index f2bf3850964..004e9558665 100644 --- a/config/configcompression/compressiontype.go +++ b/config/configcompression/compressiontype.go @@ -25,17 +25,17 @@ func (ct *Type) IsCompressed() bool { } func (ct *Type) UnmarshalText(in []byte) error { - switch typ := Type(in); typ { - case TypeGzip, - TypeZlib, - TypeDeflate, - TypeSnappy, - TypeZstd, - typeNone, - typeEmpty: + typ := Type(in) + if typ == TypeGzip || + typ == TypeZlib || + typ == TypeDeflate || + typ == TypeSnappy || + typ == TypeZstd || + typ == typeNone || + typ == typeEmpty { *ct = typ return nil - default: - return fmt.Errorf("unsupported compression type %q", typ) } + return fmt.Errorf("unsupported compression type %q", typ) + } diff --git a/config/configcompression/go.mod b/config/configcompression/go.mod index 1ac40196d85..a79f2d91f3d 100644 --- a/config/configcompression/go.mod +++ b/config/configcompression/go.mod @@ -3,7 +3,7 @@ module go.opentelemetry.io/collector/config/configcompression go 1.21 require ( - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 go.uber.org/goleak v1.3.0 ) diff --git a/config/configcompression/go.sum b/config/configcompression/go.sum index b4eccab6a53..bdd6d70ba4d 100644 --- a/config/configcompression/go.sum +++ b/config/configcompression/go.sum @@ -14,8 +14,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN 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= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/config/configgrpc/configgrpc.go b/config/configgrpc/configgrpc.go index 18526262317..98d428857ce 100644 --- a/config/configgrpc/configgrpc.go +++ b/config/configgrpc/configgrpc.go @@ -30,6 +30,7 @@ import ( "go.opentelemetry.io/collector/config/configcompression" "go.opentelemetry.io/collector/config/confignet" "go.opentelemetry.io/collector/config/configopaque" + "go.opentelemetry.io/collector/config/configtelemetry" "go.opentelemetry.io/collector/config/configtls" "go.opentelemetry.io/collector/config/internal" "go.opentelemetry.io/collector/extension/auth" @@ -46,6 +47,14 @@ type KeepaliveClientConfig struct { PermitWithoutStream bool `mapstructure:"permit_without_stream"` } +// NewDefaultKeepaliveClientConfig returns a new instance of KeepaliveClientConfig with default values. +func NewDefaultKeepaliveClientConfig() *KeepaliveClientConfig { + return &KeepaliveClientConfig{ + Time: time.Second * 10, + Timeout: time.Second * 10, + } +} + // 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, @@ -90,12 +99,29 @@ type ClientConfig struct { Auth *configauth.Authentication `mapstructure:"auth"` } +// NewDefaultClientConfig returns a new instance of ClientConfig with default values. +func NewDefaultClientConfig() *ClientConfig { + return &ClientConfig{ + TLSSetting: configtls.NewDefaultClientConfig(), + Keepalive: NewDefaultKeepaliveClientConfig(), + Auth: configauth.NewDefaultAuthentication(), + } +} + // KeepaliveServerConfig is the configuration for keepalive. type KeepaliveServerConfig struct { ServerParameters *KeepaliveServerParameters `mapstructure:"server_parameters"` EnforcementPolicy *KeepaliveEnforcementPolicy `mapstructure:"enforcement_policy"` } +// NewDefaultKeepaliveServerConfig returns a new instance of KeepaliveServerConfig with default values. +func NewDefaultKeepaliveServerConfig() *KeepaliveServerConfig { + return &KeepaliveServerConfig{ + ServerParameters: NewDefaultKeepaliveServerParameters(), + EnforcementPolicy: NewDefaultKeepaliveEnforcementPolicy(), + } +} + // KeepaliveServerParameters allow configuration of the keepalive.ServerParameters. // The same default values as keepalive.ServerParameters are applicable and get applied by the server. // See https://godoc.org/google.golang.org/grpc/keepalive#ServerParameters for details. @@ -107,6 +133,11 @@ type KeepaliveServerParameters struct { Timeout time.Duration `mapstructure:"timeout"` } +// NewDefaultKeepaliveServerParameters creates and returns a new instance of KeepaliveServerParameters with default settings. +func NewDefaultKeepaliveServerParameters() *KeepaliveServerParameters { + return &KeepaliveServerParameters{} +} + // KeepaliveEnforcementPolicy allow configuration of the keepalive.EnforcementPolicy. // The same default values as keepalive.EnforcementPolicy are applicable and get applied by the server. // See https://godoc.org/google.golang.org/grpc/keepalive#EnforcementPolicy for details. @@ -115,6 +146,11 @@ type KeepaliveEnforcementPolicy struct { PermitWithoutStream bool `mapstructure:"permit_without_stream"` } +// NewDefaultKeepaliveEnforcementPolicy creates and returns a new instance of KeepaliveEnforcementPolicy with default settings. +func NewDefaultKeepaliveEnforcementPolicy() *KeepaliveEnforcementPolicy { + return &KeepaliveEnforcementPolicy{} +} + // 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. @@ -150,8 +186,16 @@ type ServerConfig struct { IncludeMetadata bool `mapstructure:"include_metadata"` } -// SanitizedEndpoint strips the prefix of either http:// or https:// from configgrpc.ClientConfig.Endpoint. -func (gcs *ClientConfig) SanitizedEndpoint() string { +// NewDefaultServerConfig returns a new instance of ServerConfig with default values. +func NewDefaultServerConfig() *ServerConfig { + return &ServerConfig{ + Keepalive: NewDefaultKeepaliveServerConfig(), + Auth: configauth.NewDefaultAuthentication(), + } +} + +// 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://") @@ -174,13 +218,13 @@ func (gcs *ClientConfig) 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 *ClientConfig) ToClientConn(ctx context.Context, host component.Host, settings component.TelemetrySettings, extraOpts ...grpc.DialOption) (*grpc.ClientConn, error) { +func (gcs *ClientConfig) ToClientConn(_ 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 } opts = append(opts, extraOpts...) - return grpc.DialContext(ctx, gcs.SanitizedEndpoint(), opts...) + return grpc.NewClient(gcs.sanitizedEndpoint(), opts...) } func (gcs *ClientConfig) toDialOptions(host component.Host, settings component.TelemetrySettings) ([]grpc.DialOption, error) { @@ -193,7 +237,7 @@ func (gcs *ClientConfig) toDialOptions(host component.Host, settings component.T opts = append(opts, grpc.WithDefaultCallOptions(grpc.UseCompressor(cp))) } - tlsCfg, err := gcs.TLSSetting.LoadTLSConfig() + tlsCfg, err := gcs.TLSSetting.LoadTLSConfig(context.Background()) if err != nil { return nil, err } @@ -253,9 +297,11 @@ func (gcs *ClientConfig) toDialOptions(host component.Host, settings component.T otelOpts := []otelgrpc.Option{ otelgrpc.WithTracerProvider(settings.TracerProvider), - otelgrpc.WithMeterProvider(settings.MeterProvider), otelgrpc.WithPropagators(otel.GetTextMapPropagator()), } + if settings.MetricsLevel >= configtelemetry.LevelDetailed { + otelOpts = append(otelOpts, otelgrpc.WithMeterProvider(settings.MeterProvider)) + } // Enable OpenTelemetry observability plugin. opts = append(opts, grpc.WithStatsHandler(otelgrpc.NewClientHandler(otelOpts...))) @@ -268,13 +314,7 @@ func validateBalancerName(balancerName string) bool { } // 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...) -} - -// 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) { +func (gss *ServerConfig) ToServer(_ 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 @@ -285,14 +325,14 @@ func (gss *ServerConfig) ToServerContext(_ context.Context, host component.Host, func (gss *ServerConfig) toServerOption(host component.Host, settings component.TelemetrySettings) ([]grpc.ServerOption, error) { switch gss.NetAddr.Transport { - case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6": + case confignet.TransportTypeTCP, confignet.TransportTypeTCP4, confignet.TransportTypeTCP6, confignet.TransportTypeUDP, confignet.TransportTypeUDP4, confignet.TransportTypeUDP6: internal.WarnOnUnspecifiedHost(settings.Logger, gss.NetAddr.Endpoint) } var opts []grpc.ServerOption if gss.TLSSetting != nil { - tlsCfg, err := gss.TLSSetting.LoadTLSConfig() + tlsCfg, err := gss.TLSSetting.LoadTLSConfig(context.Background()) if err != nil { return nil, err } @@ -362,9 +402,11 @@ func (gss *ServerConfig) toServerOption(host component.Host, settings component. otelOpts := []otelgrpc.Option{ otelgrpc.WithTracerProvider(settings.TracerProvider), - otelgrpc.WithMeterProvider(settings.MeterProvider), otelgrpc.WithPropagators(otel.GetTextMapPropagator()), } + if settings.MetricsLevel >= configtelemetry.LevelDetailed { + otelOpts = append(otelOpts, otelgrpc.WithMeterProvider(settings.MeterProvider)) + } // Enable OpenTelemetry observability plugin. diff --git a/config/configgrpc/configgrpc_benchmark_test.go b/config/configgrpc/configgrpc_benchmark_test.go index d1fc95f772b..1ad755f2b4f 100644 --- a/config/configgrpc/configgrpc_benchmark_test.go +++ b/config/configgrpc/configgrpc_benchmark_test.go @@ -16,10 +16,10 @@ import ( "google.golang.org/grpc/encoding/gzip" "google.golang.org/grpc/status" - "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/collector/pdata/testdata" ) func BenchmarkCompressors(b *testing.B) { diff --git a/config/configgrpc/configgrpc_test.go b/config/configgrpc/configgrpc_test.go index 7d646af2b3e..6f0a98aa382 100644 --- a/config/configgrpc/configgrpc_test.go +++ b/config/configgrpc/configgrpc_test.go @@ -35,6 +35,60 @@ import ( "go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp" ) +func TestNewDefaultKeepaliveClientConfig(t *testing.T) { + expectedKeepaliveClientConfig := &KeepaliveClientConfig{ + Time: time.Second * 10, + Timeout: time.Second * 10, + } + keepaliveClientConfig := NewDefaultKeepaliveClientConfig() + assert.Equal(t, expectedKeepaliveClientConfig, keepaliveClientConfig) +} + +func TestNewDefaultClientConfig(t *testing.T) { + expected := &ClientConfig{ + TLSSetting: configtls.NewDefaultClientConfig(), + Keepalive: NewDefaultKeepaliveClientConfig(), + Auth: configauth.NewDefaultAuthentication(), + } + + result := NewDefaultClientConfig() + + assert.Equal(t, expected, result) +} +func TestNewDefaultKeepaliveServerParameters(t *testing.T) { + expectedParams := &KeepaliveServerParameters{} + params := NewDefaultKeepaliveServerParameters() + + assert.Equal(t, expectedParams, params) +} +func TestNewDefaultKeepaliveEnforcementPolicy(t *testing.T) { + expectedPolicy := &KeepaliveEnforcementPolicy{} + + policy := NewDefaultKeepaliveEnforcementPolicy() + + assert.Equal(t, expectedPolicy, policy) +} + +func TestNewDefaultKeepaliveServerConfig(t *testing.T) { + expected := &KeepaliveServerConfig{ + ServerParameters: NewDefaultKeepaliveServerParameters(), + EnforcementPolicy: NewDefaultKeepaliveEnforcementPolicy(), + } + result := NewDefaultKeepaliveServerConfig() + assert.Equal(t, expected, result) +} + +func TestNewDefaultServerConfig(t *testing.T) { + expected := &ServerConfig{ + Keepalive: NewDefaultKeepaliveServerConfig(), + Auth: configauth.NewDefaultAuthentication(), + } + + result := NewDefaultServerConfig() + + assert.Equal(t, expected, result) +} + // testBalancerBuilder facilitates testing validateBalancerName(). type testBalancerBuilder struct{} @@ -194,10 +248,10 @@ func TestAllGrpcServerSettingsExceptAuth(t *testing.T) { gss := &ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "localhost:1234", - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, TLSSetting: &configtls.ServerConfig{ - TLSSetting: configtls.Config{}, + Config: configtls.Config{}, ClientCAFile: "", }, MaxRecvMsgSizeMiB: 1, @@ -237,26 +291,7 @@ func TestGrpcServerAuthSettings(t *testing.T) { 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()) + srv, err := gss.ToServer(context.Background(), host, componenttest.NewNopTelemetrySettings()) assert.NoError(t, err) assert.NotNil(t, srv) } @@ -278,7 +313,7 @@ func TestGRPCClientSettingsError(t *testing.T) { Endpoint: "", Compression: "", TLSSetting: configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: "/doesnt/exist", }, Insecure: false, @@ -294,7 +329,7 @@ func TestGRPCClientSettingsError(t *testing.T) { Endpoint: "", Compression: "", TLSSetting: configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CertFile: "/doesnt/exist", }, Insecure: false, @@ -411,7 +446,7 @@ func TestGRPCServerWarning(t *testing.T) { settings: ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "0.0.0.0:1234", - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, }, len: 1, @@ -420,7 +455,7 @@ func TestGRPCServerWarning(t *testing.T) { settings: ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "127.0.0.1:1234", - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, }, len: 0, @@ -429,7 +464,7 @@ func TestGRPCServerWarning(t *testing.T) { settings: ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "0.0.0.0:1234", - Transport: "unix", + Transport: confignet.TransportTypeUnix, }, }, len: 0, @@ -462,10 +497,10 @@ func TestGRPCServerSettingsError(t *testing.T) { settings: ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "127.0.0.1:1234", - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, TLSSetting: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: "/doesnt/exist", }, }, @@ -476,10 +511,10 @@ func TestGRPCServerSettingsError(t *testing.T) { settings: ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "127.0.0.1:1234", - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, TLSSetting: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CertFile: "/doesnt/exist", }, }, @@ -490,7 +525,7 @@ func TestGRPCServerSettingsError(t *testing.T) { settings: ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "127.0.0.1:1234", - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, TLSSetting: &configtls.ServerConfig{ ClientCAFile: "/doesnt/exist", @@ -500,7 +535,7 @@ func TestGRPCServerSettingsError(t *testing.T) { } for _, test := range tests { t.Run(test.err, func(t *testing.T) { - _, err := test.settings.ToServerContext(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) + _, err := test.settings.ToServer(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) assert.Regexp(t, test.err, err) }) } @@ -510,7 +545,7 @@ func TestGRPCServerSettings_ToListener_Error(t *testing.T) { settings := ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "127.0.0.1:1234567", - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, } _, err := settings.NetAddr.Listen(context.Background()) @@ -538,14 +573,14 @@ func TestHttpReception(t *testing.T) { { name: "TLS", tlsServerCreds: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), }, }, tlsClientCreds: &configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -554,12 +589,12 @@ func TestHttpReception(t *testing.T) { { name: "NoServerCertificates", tlsServerCreds: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, }, tlsClientCreds: &configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -569,7 +604,7 @@ func TestHttpReception(t *testing.T) { { name: "mTLS", tlsServerCreds: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), @@ -577,7 +612,7 @@ func TestHttpReception(t *testing.T) { ClientCAFile: filepath.Join("testdata", "ca.crt"), }, tlsClientCreds: &configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "client.crt"), KeyFile: filepath.Join("testdata", "client.key"), @@ -588,7 +623,7 @@ func TestHttpReception(t *testing.T) { { name: "NoClientCertificate", tlsServerCreds: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), @@ -596,7 +631,7 @@ func TestHttpReception(t *testing.T) { ClientCAFile: filepath.Join("testdata", "ca.crt"), }, tlsClientCreds: &configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -606,7 +641,7 @@ func TestHttpReception(t *testing.T) { { name: "WrongClientCA", tlsServerCreds: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), @@ -614,7 +649,7 @@ func TestHttpReception(t *testing.T) { ClientCAFile: filepath.Join("testdata", "server.crt"), }, tlsClientCreds: &configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "client.crt"), KeyFile: filepath.Join("testdata", "client.key"), @@ -631,13 +666,13 @@ func TestHttpReception(t *testing.T) { gss := &ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "localhost:0", - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, TLSSetting: test.tlsServerCreds, } ln, err := gss.NetAddr.Listen(context.Background()) assert.NoError(t, err) - s, err := gss.ToServerContext(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) + s, err := gss.ToServer(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) assert.NoError(t, err) ptraceotlp.RegisterGRPCServer(s, &grpcTraceServer{}) @@ -679,12 +714,12 @@ func TestReceiveOnUnixDomainSocket(t *testing.T) { gss := &ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: socketName, - Transport: "unix", + Transport: confignet.TransportTypeUnix, }, } ln, err := gss.NetAddr.Listen(context.Background()) assert.NoError(t, err) - srv, err := gss.ToServerContext(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) + srv, err := gss.ToServer(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) assert.NoError(t, err) ptraceotlp.RegisterGRPCServer(srv, &grpcTraceServer{}) @@ -875,10 +910,10 @@ func TestClientInfoInterceptors(t *testing.T) { gss := &ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "localhost:0", - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, } - srv, err := gss.ToServerContext(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) + srv, err := gss.ToServer(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) require.NoError(t, err) ptraceotlp.RegisterGRPCServer(srv, mock) diff --git a/config/configgrpc/go.mod b/config/configgrpc/go.mod index 224c724c8e6..ef10d17a561 100644 --- a/config/configgrpc/go.mod +++ b/config/configgrpc/go.mod @@ -4,26 +4,27 @@ go 1.21 require ( github.com/mostynb/go-grpc-compression v1.2.2 - 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/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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/config/configauth v0.100.0 + go.opentelemetry.io/collector/config/configcompression v1.7.0 + go.opentelemetry.io/collector/config/confignet v0.100.0 + go.opentelemetry.io/collector/config/configopaque v1.7.0 + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 + go.opentelemetry.io/collector/config/configtls v0.100.0 + go.opentelemetry.io/collector/config/internal v0.100.0 + go.opentelemetry.io/collector/extension/auth v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/collector/pdata/testdata v0.100.0 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 + go.opentelemetry.io/otel v1.26.0 go.uber.org/goleak v1.3.0 go.uber.org/zap v1.27.0 - google.golang.org/grpc v1.62.0 + google.golang.org/grpc v1.63.2 ) require ( - cloud.google.com/go/compute/metadata v0.2.4-0.20230617002413-005d2dfb6b68 // 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 @@ -32,38 +33,36 @@ require ( 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/hashicorp/go-version v1.6.0 // indirect github.com/json-iterator/go v1.1.12 // 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.1 // 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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.opentelemetry.io/collector/confmap v0.100.0 // indirect + go.opentelemetry.io/collector/extension v0.100.0 // indirect + go.opentelemetry.io/collector/featuregate v1.7.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/metric v1.26.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.opentelemetry.io/otel/trace v1.26.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/net v0.24.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -93,6 +92,8 @@ replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata + replace go.opentelemetry.io/collector/component => ../../component replace go.opentelemetry.io/collector/consumer => ../../consumer diff --git a/config/configgrpc/go.sum b/config/configgrpc/go.sum index 6774b9cc3c9..30b59f5dc25 100644 --- a/config/configgrpc/go.sum +++ b/config/configgrpc/go.sum @@ -1,18 +1,10 @@ -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/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/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= @@ -24,12 +16,8 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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= @@ -45,8 +33,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -66,34 +54,34 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/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.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 h1:A3SayB3rNyt+1S6qpI9mHPkeHTZbD7XILEqWnYZb2l0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0/go.mod h1:27iA5uvhuRNmalO+iEUdVn5ZMj2qy10Mm+XRIpRmyuU= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -109,18 +97,16 @@ 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.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/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -133,16 +119,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/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.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/config/configgrpc/package_test.go b/config/configgrpc/package_test.go index 519657748da..503b6469adf 100644 --- a/config/configgrpc/package_test.go +++ b/config/configgrpc/package_test.go @@ -9,9 +9,6 @@ import ( "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")) + goleak.VerifyTestMain(m) } diff --git a/config/confighttp/README.md b/config/confighttp/README.md index beb28028bdb..a0227c2402b 100644 --- a/config/confighttp/README.md +++ b/config/confighttp/README.md @@ -39,7 +39,7 @@ Example: ```yaml exporter: - otlp: + otlphttp: endpoint: otelcol2:55690 auth: authenticator: some-authenticator-extension diff --git a/config/confighttp/compression_test.go b/config/confighttp/compression_test.go index 63d9ba02ab9..794adda2ec8 100644 --- a/config/confighttp/compression_test.go +++ b/config/confighttp/compression_test.go @@ -7,6 +7,7 @@ import ( "bytes" "compress/gzip" "compress/zlib" + "context" "fmt" "io" "net/http" @@ -99,7 +100,7 @@ func TestHTTPClientCompression(t *testing.T) { Endpoint: srv.URL, Compression: tt.encoding, } - client, err := clientSettings.ToClient(componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) + client, err := clientSettings.ToClient(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) require.NoError(t, err) res, err := client.Do(req) if tt.shouldError { diff --git a/config/confighttp/compressor.go b/config/confighttp/compressor.go index 3e085bead0d..660fa83ce51 100644 --- a/config/confighttp/compressor.go +++ b/config/confighttp/compressor.go @@ -28,9 +28,10 @@ var ( _ writeCloserReset = (*snappy.Writer)(nil) snappyPool = &compressor{pool: sync.Pool{New: func() any { return snappy.NewBufferedWriter(nil) }}} _ writeCloserReset = (*zstd.Encoder)(nil) - zStdPool = &compressor{pool: sync.Pool{New: func() any { zw, _ := zstd.NewWriter(nil); return zw }}} - _ writeCloserReset = (*zlib.Writer)(nil) - zLibPool = &compressor{pool: sync.Pool{New: func() any { return zlib.NewWriter(nil) }}} + // Concurrency 1 disables async decoding via goroutines. This is useful to reduce memory usage and isn't a bottleneck for compression using sync.Pool. + zStdPool = &compressor{pool: sync.Pool{New: func() any { zw, _ := zstd.NewWriter(nil, zstd.WithEncoderConcurrency(1)); return zw }}} + _ writeCloserReset = (*zlib.Writer)(nil) + zLibPool = &compressor{pool: sync.Pool{New: func() any { return zlib.NewWriter(nil) }}} ) type compressor struct { diff --git a/config/confighttp/compressor_test.go b/config/confighttp/compressor_test.go new file mode 100644 index 00000000000..29efe4190d0 --- /dev/null +++ b/config/confighttp/compressor_test.go @@ -0,0 +1,96 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// This file contains helper functions regarding compression/decompression for confighttp. + +package confighttp // import "go.opentelemetry.io/collector/config/confighttp" + +import ( + "bytes" + "fmt" + "io" + "strings" + "testing" + + "github.com/klauspost/compress/zstd" + + "go.opentelemetry.io/collector/config/configcompression" +) + +func BenchmarkCompression(b *testing.B) { + benchmarks := []struct { + codec configcompression.Type + name string + function func(*testing.B, configcompression.Type, *bytes.Buffer, []byte) + }{ + { + codec: configcompression.TypeZstd, + name: "zstdWithConcurrency", + function: benchmarkCompression, + }, + { + codec: configcompression.TypeZstd, + name: "zstdNoConcurrency", + function: benchmarkCompressionNoConcurrency, + }, + } + payload := make([]byte, 10<<20) + buffer := bytes.Buffer{} + buffer.Grow(len(payload)) + + ts := &bytes.Buffer{} + defer func() { + fmt.Printf("input => %.2f MB\n", float64(len(payload))/(1024*1024)) + fmt.Println(ts) + }() + + for i := range benchmarks { + benchmark := &benchmarks[i] + b.Run(fmt.Sprint(benchmark.name), func(b *testing.B) { + benchmark.function(b, benchmark.codec, &buffer, payload) + }) + + } +} + +func benchmarkCompression(b *testing.B, _ configcompression.Type, buf *bytes.Buffer, payload []byte) { + // Concurrency Enabled + + b.Run("compress", func(b *testing.B) { + stringReader := strings.NewReader(string(payload)) + stringReadCloser := io.NopCloser(stringReader) + var enc io.Writer + b.ResetTimer() + b.ReportAllocs() + b.SetBytes(int64(len(payload))) + for i := 0; i < b.N; i++ { + enc, _ = zstd.NewWriter(nil, zstd.WithEncoderConcurrency(5)) + enc.(writeCloserReset).Reset(buf) + _, copyErr := io.Copy(enc, stringReadCloser) + if copyErr != nil { + b.Fatal(copyErr) + } + } + }) +} + +func benchmarkCompressionNoConcurrency(b *testing.B, _ configcompression.Type, buf *bytes.Buffer, payload []byte) { + // Concurrency Disabled + + b.Run("compress", func(b *testing.B) { + stringReader := strings.NewReader(string(payload)) + stringReadCloser := io.NopCloser(stringReader) + var enc io.Writer + b.ResetTimer() + b.ReportAllocs() + b.SetBytes(int64(len(payload))) + for i := 0; i < b.N; i++ { + enc, _ = zstd.NewWriter(nil, zstd.WithEncoderConcurrency(1)) + enc.(writeCloserReset).Reset(buf) + _, copyErr := io.Copy(enc, stringReadCloser) + if copyErr != nil { + b.Fatal(copyErr) + } + } + }) +} diff --git a/config/confighttp/confighttp.go b/config/confighttp/confighttp.go index 40ec4ba0b83..067f9d3a0ab 100644 --- a/config/confighttp/confighttp.go +++ b/config/confighttp/confighttp.go @@ -4,6 +4,7 @@ package confighttp // import "go.opentelemetry.io/collector/config/confighttp" import ( + "context" "crypto/tls" "errors" "fmt" @@ -22,6 +23,7 @@ import ( "go.opentelemetry.io/collector/config/configauth" "go.opentelemetry.io/collector/config/configcompression" "go.opentelemetry.io/collector/config/configopaque" + "go.opentelemetry.io/collector/config/configtelemetry" "go.opentelemetry.io/collector/config/configtls" "go.opentelemetry.io/collector/config/internal" "go.opentelemetry.io/collector/extension/auth" @@ -115,8 +117,8 @@ func NewDefaultClientConfig() ClientConfig { } // ToClient creates an HTTP client. -func (hcs *ClientConfig) ToClient(host component.Host, settings component.TelemetrySettings) (*http.Client, error) { - tlsCfg, err := hcs.TLSSetting.LoadTLSConfig() +func (hcs *ClientConfig) ToClient(ctx context.Context, host component.Host, settings component.TelemetrySettings) (*http.Client, error) { + tlsCfg, err := hcs.TLSSetting.LoadTLSConfig(ctx) if err != nil { return nil, err } @@ -205,14 +207,17 @@ func (hcs *ClientConfig) ToClient(host component.Host, settings component.Teleme } } + otelOpts := []otelhttp.Option{ + otelhttp.WithTracerProvider(settings.TracerProvider), + otelhttp.WithPropagators(otel.GetTextMapPropagator()), + } + if settings.MetricsLevel >= configtelemetry.LevelDetailed { + otelOpts = append(otelOpts, otelhttp.WithMeterProvider(settings.MeterProvider)) + } + // wrapping http transport with otelhttp transport to enable otel instrumentation if settings.TracerProvider != nil && settings.MeterProvider != nil { - clientTransport = otelhttp.NewTransport( - clientTransport, - otelhttp.WithTracerProvider(settings.TracerProvider), - otelhttp.WithMeterProvider(settings.MeterProvider), - otelhttp.WithPropagators(otel.GetTextMapPropagator()), - ) + clientTransport = otelhttp.NewTransport(clientTransport, otelOpts...) } if hcs.CustomRoundTripper != nil { @@ -228,6 +233,11 @@ func (hcs *ClientConfig) ToClient(host component.Host, settings component.Teleme }, nil } +// Deprecated: [v0.99.0] Use ToClient instead. +func (hcs *ClientConfig) ToClientContext(ctx context.Context, host component.Host, settings component.TelemetrySettings) (*http.Client, error) { + return hcs.ToClient(ctx, host, settings) +} + // Custom RoundTripper that adds headers. type headerRoundTripper struct { transport http.RoundTripper @@ -279,8 +289,13 @@ type ServerConfig struct { ResponseHeaders map[string]configopaque.String `mapstructure:"response_headers"` } +// Deprecated: [v0.99.0] Use ToListener instead. +func (hss *ServerConfig) ToListenerContext(ctx context.Context) (net.Listener, error) { + return hss.ToListener(ctx) +} + // ToListener creates a net.Listener. -func (hss *ServerConfig) ToListener() (net.Listener, error) { +func (hss *ServerConfig) ToListener(ctx context.Context) (net.Listener, error) { listener, err := net.Listen("tcp", hss.Endpoint) if err != nil { return nil, err @@ -288,13 +303,14 @@ func (hss *ServerConfig) ToListener() (net.Listener, error) { if hss.TLSSetting != nil { var tlsCfg *tls.Config - tlsCfg, err = hss.TLSSetting.LoadTLSConfig() + tlsCfg, err = hss.TLSSetting.LoadTLSConfig(ctx) if err != nil { return nil, err } tlsCfg.NextProtos = []string{http2.NextProtoTLS, "http/1.1"} listener = tls.NewListener(listener, tlsCfg) } + return listener, nil } @@ -328,8 +344,13 @@ func WithDecoder(key string, dec func(body io.ReadCloser) (io.ReadCloser, error) } } +// Deprecated: [v0.99.0] Use ToServer instead. +func (hss *ServerConfig) ToServerContext(ctx context.Context, host component.Host, settings component.TelemetrySettings, handler http.Handler, opts ...ToServerOption) (*http.Server, error) { + return hss.ToServer(ctx, host, settings, handler, opts...) +} + // ToServer creates an http.Server from settings object. -func (hss *ServerConfig) ToServer(host component.Host, settings component.TelemetrySettings, handler http.Handler, opts ...ToServerOption) (*http.Server, error) { +func (hss *ServerConfig) ToServer(_ context.Context, host component.Host, settings component.TelemetrySettings, handler http.Handler, opts ...ToServerOption) (*http.Server, error) { internal.WarnOnUnspecifiedHost(settings.Logger, hss.Endpoint) serverOpts := &toServerOptions{} @@ -380,18 +401,20 @@ func (hss *ServerConfig) ToServer(host component.Host, settings component.Teleme handler = responseHeadersHandler(handler, hss.ResponseHeaders) } - // Enable OpenTelemetry observability plugin. - // TODO: Consider to use component ID string as prefix for all the operations. - handler = otelhttp.NewHandler( - handler, - "", + otelOpts := []otelhttp.Option{ otelhttp.WithTracerProvider(settings.TracerProvider), - otelhttp.WithMeterProvider(settings.MeterProvider), otelhttp.WithPropagators(otel.GetTextMapPropagator()), otelhttp.WithSpanNameFormatter(func(_ string, r *http.Request) string { return r.URL.Path }), - ) + } + if settings.MetricsLevel >= configtelemetry.LevelDetailed { + otelOpts = append(otelOpts, otelhttp.WithMeterProvider(settings.MeterProvider)) + } + + // Enable OpenTelemetry observability plugin. + // TODO: Consider to use component ID string as prefix for all the operations. + handler = otelhttp.NewHandler(handler, "", otelOpts...) // wrap the current handler in an interceptor that will add client.Info to the request's context handler = &clientInfoHandler{ diff --git a/config/confighttp/confighttp_test.go b/config/confighttp/confighttp_test.go index fc90f8f7caf..635f9415a2f 100644 --- a/config/confighttp/confighttp_test.go +++ b/config/confighttp/confighttp_test.go @@ -169,7 +169,7 @@ func TestAllHTTPClientSettings(t *testing.T) { t.Run(test.name, func(t *testing.T) { tt := componenttest.NewNopTelemetrySettings() tt.TracerProvider = nil - client, err := test.settings.ToClient(host, tt) + client, err := test.settings.ToClient(context.Background(), host, tt) if test.shouldError { assert.Error(t, err) return @@ -222,7 +222,7 @@ func TestPartialHTTPClientSettings(t *testing.T) { t.Run(test.name, func(t *testing.T) { tt := componenttest.NewNopTelemetrySettings() tt.TracerProvider = nil - client, err := test.settings.ToClient(host, tt) + client, err := test.settings.ToClient(context.Background(), host, tt) assert.NoError(t, err) transport := client.Transport.(*http.Transport) assert.EqualValues(t, 1024, transport.ReadBufferSize) @@ -272,7 +272,7 @@ func TestProxyURL(t *testing.T) { tt := componenttest.NewNopTelemetrySettings() tt.TracerProvider = nil - client, err := s.ToClient(componenttest.NewNopHost(), tt) + client, err := s.ToClient(context.Background(), componenttest.NewNopHost(), tt) if tC.err { require.Error(t, err) @@ -311,7 +311,7 @@ func TestHTTPClientSettingsError(t *testing.T) { settings: ClientConfig{ Endpoint: "", TLSSetting: configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: "/doesnt/exist", }, Insecure: false, @@ -324,7 +324,7 @@ func TestHTTPClientSettingsError(t *testing.T) { settings: ClientConfig{ Endpoint: "", TLSSetting: configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CertFile: "/doesnt/exist", }, Insecure: false, @@ -342,7 +342,7 @@ func TestHTTPClientSettingsError(t *testing.T) { } for _, test := range tests { t.Run(test.err, func(t *testing.T) { - _, err := test.settings.ToClient(host, componenttest.NewNopTelemetrySettings()) + _, err := test.settings.ToClient(context.Background(), host, componenttest.NewNopTelemetrySettings()) assert.Regexp(t, test.err, err) }) } @@ -423,7 +423,7 @@ func TestHTTPClientSettingWithAuthConfig(t *testing.T) { name: "with_auth_configuration_has_extension_and_compression", settings: ClientConfig{ Endpoint: "localhost:1234", - Auth: &configauth.Authentication{AuthenticatorID: component.NewID("mock")}, + Auth: &configauth.Authentication{AuthenticatorID: component.MustNewID("mock")}, Compression: configcompression.TypeGzip, }, shouldErr: false, @@ -451,7 +451,7 @@ func TestHTTPClientSettingWithAuthConfig(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { // Omit TracerProvider and MeterProvider in TelemetrySettings as otelhttp.Transport cannot be introspected - client, err := test.settings.ToClient(test.host, component.TelemetrySettings{Logger: zap.NewNop(), MetricsLevel: configtelemetry.LevelNone}) + client, err := test.settings.ToClient(context.Background(), test.host, component.TelemetrySettings{Logger: zap.NewNop(), MetricsLevel: configtelemetry.LevelNone}) if test.shouldErr { assert.Error(t, err) return @@ -494,7 +494,7 @@ func TestHTTPServerSettingsError(t *testing.T) { settings: ServerConfig{ Endpoint: "localhost:0", TLSSetting: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: "/doesnt/exist", }, }, @@ -505,7 +505,7 @@ func TestHTTPServerSettingsError(t *testing.T) { settings: ServerConfig{ Endpoint: "localhost:0", TLSSetting: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CertFile: "/doesnt/exist", }, }, @@ -523,7 +523,7 @@ func TestHTTPServerSettingsError(t *testing.T) { } for _, test := range tests { t.Run(test.err, func(t *testing.T) { - _, err := test.settings.ToListener() + _, err := test.settings.ToListener(context.Background()) assert.Regexp(t, test.err, err) }) } @@ -555,6 +555,7 @@ func TestHTTPServerWarning(t *testing.T) { set.Logger = zap.New(logger) _, err := test.settings.ToServer( + context.Background(), componenttest.NewNopHost(), set, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { @@ -586,14 +587,14 @@ func TestHttpReception(t *testing.T) { { name: "TLS", tlsServerCreds: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), }, }, tlsClientCreds: &configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -602,14 +603,14 @@ func TestHttpReception(t *testing.T) { { name: "TLS (HTTP/1.1)", tlsServerCreds: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), }, }, tlsClientCreds: &configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -619,12 +620,12 @@ func TestHttpReception(t *testing.T) { { name: "NoServerCertificates", tlsServerCreds: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, }, tlsClientCreds: &configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -634,7 +635,7 @@ func TestHttpReception(t *testing.T) { { name: "mTLS", tlsServerCreds: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), @@ -642,7 +643,7 @@ func TestHttpReception(t *testing.T) { ClientCAFile: filepath.Join("testdata", "ca.crt"), }, tlsClientCreds: &configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "client.crt"), KeyFile: filepath.Join("testdata", "client.key"), @@ -653,7 +654,7 @@ func TestHttpReception(t *testing.T) { { name: "NoClientCertificate", tlsServerCreds: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), @@ -661,7 +662,7 @@ func TestHttpReception(t *testing.T) { ClientCAFile: filepath.Join("testdata", "ca.crt"), }, tlsClientCreds: &configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -671,7 +672,7 @@ func TestHttpReception(t *testing.T) { { name: "WrongClientCA", tlsServerCreds: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), @@ -679,7 +680,7 @@ func TestHttpReception(t *testing.T) { ClientCAFile: filepath.Join("testdata", "server.crt"), }, tlsClientCreds: &configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "client.crt"), KeyFile: filepath.Join("testdata", "client.key"), @@ -697,10 +698,11 @@ func TestHttpReception(t *testing.T) { Endpoint: "localhost:0", TLSSetting: tt.tlsServerCreds, } - ln, err := hss.ToListener() + ln, err := hss.ToListener(context.Background()) require.NoError(t, err) s, err := hss.ToServer( + context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { @@ -731,7 +733,7 @@ func TestHttpReception(t *testing.T) { return rt, nil } } - client, errClient := hcs.ToClient(componenttest.NewNopHost(), component.TelemetrySettings{}) + client, errClient := hcs.ToClient(context.Background(), componenttest.NewNopHost(), component.TelemetrySettings{}) require.NoError(t, errClient) resp, errResp := client.Get(hcs.Endpoint) @@ -810,10 +812,11 @@ func TestHttpCors(t *testing.T) { CORS: tt.CORSConfig, } - ln, err := hss.ToListener() + ln, err := hss.ToListener(context.Background()) require.NoError(t, err) s, err := hss.ToServer( + context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { @@ -854,6 +857,7 @@ func TestHttpCorsInvalidSettings(t *testing.T) { // This effectively does not enable CORS but should also not cause an error s, err := hss.ToServer( + context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})) @@ -883,7 +887,7 @@ func TestHttpCorsWithSettings(t *testing.T) { }, } - srv, err := hss.ToServer(host, componenttest.NewNopTelemetrySettings(), nil) + srv, err := hss.ToServer(context.Background(), host, componenttest.NewNopTelemetrySettings(), nil) require.NoError(t, err) require.NotNil(t, srv) @@ -926,10 +930,11 @@ func TestHttpServerHeaders(t *testing.T) { ResponseHeaders: tt.headers, } - ln, err := hss.ToListener() + ln, err := hss.ToListener(context.Background()) require.NoError(t, err) s, err := hss.ToServer( + context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { @@ -1013,6 +1018,7 @@ func ExampleServerConfig() { Endpoint: "localhost:443", } s, err := settings.ToServer( + context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})) @@ -1020,7 +1026,7 @@ func ExampleServerConfig() { panic(err) } - l, err := settings.ToListener() + l, err := settings.ToListener(context.Background()) if err != nil { panic(err) } @@ -1059,7 +1065,7 @@ func TestHttpClientHeaders(t *testing.T) { Timeout: 0, Headers: tt.headers, } - client, _ := setting.ToClient(componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) + client, _ := setting.ToClient(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) req, err := http.NewRequest(http.MethodGet, setting.Endpoint, nil) assert.NoError(t, err) _, err = client.Do(req) @@ -1089,13 +1095,13 @@ func TestHttpClientHostHeader(t *testing.T) { serverURL, _ := url.Parse(server.URL) setting := ClientConfig{ Endpoint: serverURL.String(), - TLSSetting: configtls.TLSClientSetting{}, + TLSSetting: configtls.ClientConfig{}, ReadBufferSize: 0, WriteBufferSize: 0, Timeout: 0, Headers: tt.headers, } - client, _ := setting.ToClient(componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) + client, _ := setting.ToClient(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings()) req, err := http.NewRequest(http.MethodGet, setting.Endpoint, nil) assert.NoError(t, err) _, err = client.Do(req) @@ -1190,7 +1196,7 @@ func TestServerAuth(t *testing.T) { handlerCalled = true }) - srv, err := hss.ToServer(host, componenttest.NewNopTelemetrySettings(), handler) + srv, err := hss.ToServer(context.Background(), host, componenttest.NewNopTelemetrySettings(), handler) require.NoError(t, err) // test @@ -1208,7 +1214,7 @@ func TestInvalidServerAuth(t *testing.T) { }, } - srv, err := hss.ToServer(componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), http.NewServeMux()) + srv, err := hss.ToServer(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), http.NewServeMux()) require.Error(t, err) require.Nil(t, srv) } @@ -1231,7 +1237,7 @@ func TestFailedServerAuth(t *testing.T) { }, } - srv, err := hss.ToServer(host, componenttest.NewNopTelemetrySettings(), http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})) + srv, err := hss.ToServer(context.Background(), host, componenttest.NewNopTelemetrySettings(), http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})) require.NoError(t, err) // test @@ -1255,6 +1261,7 @@ func TestServerWithErrorHandler(t *testing.T) { } srv, err := hss.ToServer( + context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}), @@ -1283,6 +1290,7 @@ func TestServerWithDecoder(t *testing.T) { } srv, err := hss.ToServer( + context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}), @@ -1340,14 +1348,14 @@ func BenchmarkHttpRequest(b *testing.B) { } tlsServerCreds := &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), CertFile: filepath.Join("testdata", "server.crt"), KeyFile: filepath.Join("testdata", "server.key"), }, } tlsClientCreds := &configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "ca.crt"), }, ServerName: "localhost", @@ -1359,6 +1367,7 @@ func BenchmarkHttpRequest(b *testing.B) { } s, err := hss.ToServer( + context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { @@ -1366,7 +1375,7 @@ func BenchmarkHttpRequest(b *testing.B) { require.NoError(b, errWrite) })) require.NoError(b, err) - ln, err := hss.ToListener() + ln, err := hss.ToListener(context.Background()) require.NoError(b, err) go func() { @@ -1390,12 +1399,12 @@ func BenchmarkHttpRequest(b *testing.B) { b.Run(bb.name, func(b *testing.B) { var c *http.Client if !bb.clientPerThread { - c, err = hcs.ToClient(componenttest.NewNopHost(), component.TelemetrySettings{}) + c, err = hcs.ToClient(context.Background(), componenttest.NewNopHost(), component.TelemetrySettings{}) require.NoError(b, err) } b.RunParallel(func(pb *testing.PB) { if c == nil { - c, err = hcs.ToClient(componenttest.NewNopHost(), component.TelemetrySettings{}) + c, err = hcs.ToClient(context.Background(), componenttest.NewNopHost(), component.TelemetrySettings{}) require.NoError(b, err) } for pb.Next() { diff --git a/config/confighttp/go.mod b/config/confighttp/go.mod index 48dd57e2806..819bc18d124 100644 --- a/config/confighttp/go.mod +++ b/config/confighttp/go.mod @@ -4,23 +4,24 @@ go 1.21 require ( github.com/golang/snappy v0.0.4 - github.com/klauspost/compress v1.17.7 + github.com/klauspost/compress v1.17.8 github.com/rs/cors v1.10.1 - 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/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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/config/configauth v0.100.0 + go.opentelemetry.io/collector/config/configcompression v1.7.0 + go.opentelemetry.io/collector/config/configopaque v1.7.0 + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 + go.opentelemetry.io/collector/config/configtls v0.100.0 + go.opentelemetry.io/collector/config/internal v0.100.0 + go.opentelemetry.io/collector/extension v0.100.0 + go.opentelemetry.io/collector/extension/auth v0.100.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 + go.opentelemetry.io/otel v1.26.0 go.uber.org/goleak v1.3.0 go.uber.org/zap v1.27.0 - golang.org/x/net v0.21.0 + golang.org/x/net v0.24.0 ) require ( @@ -33,33 +34,31 @@ require ( 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.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/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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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.opentelemetry.io/collector/confmap v0.100.0 // indirect + go.opentelemetry.io/collector/featuregate v1.7.0 // indirect + go.opentelemetry.io/collector/pdata v1.7.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/metric v1.26.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.opentelemetry.io/otel/trace v1.26.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -90,3 +89,5 @@ replace go.opentelemetry.io/collector/pdata => ../../pdata replace go.opentelemetry.io/collector/component => ../../component replace go.opentelemetry.io/collector/consumer => ../../consumer + +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata diff --git a/config/confighttp/go.sum b/config/confighttp/go.sum index 6d440490f4c..666e96bd68b 100644 --- a/config/confighttp/go.sum +++ b/config/confighttp/go.sum @@ -17,12 +17,8 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= @@ -31,14 +27,14 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr 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/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/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/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -55,34 +51,34 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/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.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 h1:Xs2Ncz0gNihqu9iosIZ5SkBbWo5T8JhhLJFMQL1qmLI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0/go.mod h1:vy+2G/6NvVMpwGX/NyLqcC41fxepnuKHk16E6IZUcJc= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -98,16 +94,16 @@ 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -120,14 +116,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/config/confighttp/ratelimit_test.go b/config/confighttp/ratelimit_test.go index b06f47010cd..bd888533034 100644 --- a/config/confighttp/ratelimit_test.go +++ b/config/confighttp/ratelimit_test.go @@ -13,16 +13,17 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" ) func TestServerRateLimit(t *testing.T) { // prepare - hss := HTTPServerSettings{ + hss := ServerConfig{ Endpoint: "localhost:0", RateLimit: &RateLimit{ - RateLimiterID: component.NewID("mock"), + RateLimiterID: component.NewID(component.MustNewType("mock")), }, } @@ -30,16 +31,16 @@ func TestServerRateLimit(t *testing.T) { host := &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("mock"): limiter, + component.NewID(component.MustNewType("mock")): limiter, }, } var handlerCalled bool - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { handlerCalled = true }) - srv, err := hss.ToServer(host, componenttest.NewNopTelemetrySettings(), handler) + srv, err := hss.ToServer(context.Background(), host, componenttest.NewNopTelemetrySettings(), handler) require.NoError(t, err) // test @@ -51,34 +52,34 @@ func TestServerRateLimit(t *testing.T) { } func TestInvalidServerRateLimit(t *testing.T) { - hss := HTTPServerSettings{ + hss := ServerConfig{ RateLimit: &RateLimit{ - RateLimiterID: component.NewID("non-existing"), + RateLimiterID: component.NewID(component.MustNewType("non_existing")), }, } - srv, err := hss.ToServer(componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), http.NewServeMux()) + srv, err := hss.ToServer(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings(), http.NewServeMux()) require.Error(t, err) require.Nil(t, srv) } func TestRejectedServerRateLimit(t *testing.T) { // prepare - hss := HTTPServerSettings{ + hss := ServerConfig{ Endpoint: "localhost:0", RateLimit: &RateLimit{ - RateLimiterID: component.NewID("mock"), + RateLimiterID: component.NewID(component.MustNewType("mock")), }, } host := &mockHost{ ext: map[component.ID]component.Component{ - component.NewID("mock"): &mockRateLimiter{ + component.NewID(component.MustNewType("mock")): &mockRateLimiter{ err: errors.New("rate limited"), }, }, } - srv, err := hss.ToServer(host, componenttest.NewNopTelemetrySettings(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) + srv, err := hss.ToServer(context.Background(), host, componenttest.NewNopTelemetrySettings(), http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {})) require.NoError(t, err) // test diff --git a/config/confignet/confignet.go b/config/confignet/confignet.go index 09f7ec24ff6..0f34aebb69f 100644 --- a/config/confignet/confignet.go +++ b/config/confignet/confignet.go @@ -5,10 +5,56 @@ package confignet // import "go.opentelemetry.io/collector/config/confignet" import ( "context" + "fmt" "net" "time" ) +// TransportType represents a type of network transport protocol +type TransportType string + +const ( + TransportTypeTCP TransportType = "tcp" + TransportTypeTCP4 TransportType = "tcp4" + TransportTypeTCP6 TransportType = "tcp6" + TransportTypeUDP TransportType = "udp" + TransportTypeUDP4 TransportType = "udp4" + TransportTypeUDP6 TransportType = "udp6" + TransportTypeIP TransportType = "ip" + TransportTypeIP4 TransportType = "ip4" + TransportTypeIP6 TransportType = "ip6" + TransportTypeUnix TransportType = "unix" + TransportTypeUnixgram TransportType = "unixgram" + TransportTypeUnixPacket TransportType = "unixpacket" + transportTypeEmpty TransportType = "" +) + +// UnmarshalText unmarshalls text to a TransportType. +// Valid values are "tcp", "tcp4", "tcp6", "udp", "udp4", +// "udp6", "ip", "ip4", "ip6", "unix", "unixgram" and "unixpacket" +func (tt *TransportType) UnmarshalText(in []byte) error { + typ := TransportType(in) + switch typ { + case TransportTypeTCP, + TransportTypeTCP4, + TransportTypeTCP6, + TransportTypeUDP, + TransportTypeUDP4, + TransportTypeUDP6, + TransportTypeIP, + TransportTypeIP4, + TransportTypeIP6, + TransportTypeUnix, + TransportTypeUnixgram, + TransportTypeUnixPacket, + transportTypeEmpty: + *tt = typ + return nil + default: + return fmt.Errorf("unsupported transport type %q", typ) + } +} + // DialerConfig contains options for connecting to an address. type DialerConfig struct { // Timeout is the maximum amount of time a dial will wait for @@ -16,6 +62,11 @@ type DialerConfig struct { Timeout time.Duration `mapstructure:"timeout"` } +// NewDefaultDialerConfig creates a new DialerConfig with any default values set +func NewDefaultDialerConfig() DialerConfig { + return DialerConfig{} +} + // AddrConfig represents a network endpoint address. type AddrConfig struct { // Endpoint configures the address for this network connection. @@ -25,24 +76,51 @@ type AddrConfig struct { // "[fe80::1%zone]:80". The zone specifies the scope of the literal IPv6 address as defined in RFC 4007. Endpoint string `mapstructure:"endpoint"` - // Transport to use. Known protocols are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only), "udp", "udp4" (IPv4-only), + // Transport to use. Allowed 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"` + Transport TransportType `mapstructure:"transport"` // DialerConfig contains options for connecting to an address. DialerConfig DialerConfig `mapstructure:"dialer"` } +// NewDefaultAddrConfig creates a new AddrConfig with any default values set +func NewDefaultAddrConfig() AddrConfig { + return AddrConfig{ + DialerConfig: NewDefaultDialerConfig(), + } +} + // 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) + return d.DialContext(ctx, string(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) + return lc.Listen(ctx, string(na.Transport), na.Endpoint) +} + +func (na *AddrConfig) Validate() error { + switch na.Transport { + case TransportTypeTCP, + TransportTypeTCP4, + TransportTypeTCP6, + TransportTypeUDP, + TransportTypeUDP4, + TransportTypeUDP6, + TransportTypeIP, + TransportTypeIP4, + TransportTypeIP6, + TransportTypeUnix, + TransportTypeUnixgram, + TransportTypeUnixPacket: + return nil + default: + return fmt.Errorf("invalid transport type %q", na.Transport) + } } // TCPAddrConfig represents a TCP endpoint address. @@ -58,14 +136,21 @@ type TCPAddrConfig struct { DialerConfig DialerConfig `mapstructure:"dialer"` } +// NewDefaultTCPAddrConfig creates a new TCPAddrConfig with any default values set +func NewDefaultTCPAddrConfig() TCPAddrConfig { + return TCPAddrConfig{ + DialerConfig: NewDefaultDialerConfig(), + } +} + // 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) + return d.DialContext(ctx, string(TransportTypeTCP), 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) + return lc.Listen(ctx, string(TransportTypeTCP), na.Endpoint) } diff --git a/config/confignet/confignet_test.go b/config/confignet/confignet_test.go index f3481609562..9375561dc39 100644 --- a/config/confignet/confignet_test.go +++ b/config/confignet/confignet_test.go @@ -11,12 +11,31 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) +func TestNewDefaultDialerConfig(t *testing.T) { + expectedDialerConfig := DialerConfig{} + dialerConfig := NewDefaultDialerConfig() + require.Equal(t, expectedDialerConfig, dialerConfig) +} + +func TestNewDefaultAddrConfig(t *testing.T) { + expectedAddrConfig := AddrConfig{} + addrConfig := NewDefaultAddrConfig() + require.Equal(t, expectedAddrConfig, addrConfig) +} + +func TestNewDefaultTCPAddrConfig(t *testing.T) { + expectedTCPAddrConfig := TCPAddrConfig{} + tcpAddrconfig := NewDefaultTCPAddrConfig() + require.Equal(t, expectedTCPAddrConfig, tcpAddrconfig) +} + func TestAddrConfigTimeout(t *testing.T) { nac := &AddrConfig{ Endpoint: "localhost:0", - Transport: "tcp", + Transport: TransportTypeTCP, DialerConfig: DialerConfig{ Timeout: -1 * time.Second, }, @@ -51,7 +70,7 @@ func TestTCPAddrConfigTimeout(t *testing.T) { func TestAddrConfig(t *testing.T) { nas := &AddrConfig{ Endpoint: "localhost:0", - Transport: "tcp", + Transport: TransportTypeTCP, } ln, err := nas.Listen(context.Background()) assert.NoError(t, err) @@ -71,7 +90,7 @@ func TestAddrConfig(t *testing.T) { nac := &AddrConfig{ Endpoint: ln.Addr().String(), - Transport: "tcp", + Transport: TransportTypeTCP, } var conn net.Conn conn, err = nac.Dial(context.Background()) @@ -83,6 +102,23 @@ func TestAddrConfig(t *testing.T) { assert.NoError(t, ln.Close()) } +func Test_NetAddr_Validate(t *testing.T) { + na := &AddrConfig{ + Transport: TransportTypeTCP, + } + assert.NoError(t, na.Validate()) + + na = &AddrConfig{ + Transport: transportTypeEmpty, + } + assert.Error(t, na.Validate()) + + na = &AddrConfig{ + Transport: "random string", + } + assert.Error(t, na.Validate()) +} + func TestTCPAddrConfig(t *testing.T) { nas := &TCPAddrConfig{ Endpoint: "localhost:0", @@ -115,3 +151,11 @@ func TestTCPAddrConfig(t *testing.T) { <-done assert.NoError(t, ln.Close()) } + +func Test_TransportType_UnmarshalText(t *testing.T) { + var tt TransportType + err := tt.UnmarshalText([]byte("tcp")) + require.NoError(t, err) + err = tt.UnmarshalText([]byte("invalid")) + require.Error(t, err) +} diff --git a/config/confignet/go.mod b/config/confignet/go.mod index cbd4d70267e..4d1f2b4813a 100644 --- a/config/confignet/go.mod +++ b/config/confignet/go.mod @@ -3,7 +3,7 @@ module go.opentelemetry.io/collector/config/confignet go 1.21 require ( - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 go.uber.org/goleak v1.3.0 ) diff --git a/config/confignet/go.sum b/config/confignet/go.sum index b4eccab6a53..bdd6d70ba4d 100644 --- a/config/confignet/go.sum +++ b/config/confignet/go.sum @@ -14,8 +14,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN 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= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/config/configopaque/go.mod b/config/configopaque/go.mod index c2c9a683f4f..1f8b080f2da 100644 --- a/config/configopaque/go.mod +++ b/config/configopaque/go.mod @@ -3,8 +3,8 @@ module go.opentelemetry.io/collector/config/configopaque go 1.21 require ( - github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/confmap v0.96.0 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/confmap v0.100.0 go.uber.org/goleak v1.3.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -14,13 +14,14 @@ require ( 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/knadh/koanf/v2 v2.1.1 // 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 + go.uber.org/zap v1.27.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect ) diff --git a/config/configopaque/go.sum b/config/configopaque/go.sum index ea17c4438d6..c42b46e7c12 100644 --- a/config/configopaque/go.sum +++ b/config/configopaque/go.sum @@ -7,8 +7,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -26,12 +26,14 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN 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= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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= 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/configretry/go.mod b/config/configretry/go.mod index aeeab554eb9..9458227d2ca 100644 --- a/config/configretry/go.mod +++ b/config/configretry/go.mod @@ -3,8 +3,8 @@ 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 + github.com/cenkalti/backoff/v4 v4.3.0 + github.com/stretchr/testify v1.9.0 go.uber.org/goleak v1.3.0 ) diff --git a/config/configretry/go.sum b/config/configretry/go.sum index 33516e2c95b..ac136ad8627 100644 --- a/config/configretry/go.sum +++ b/config/configretry/go.sum @@ -1,5 +1,5 @@ -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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/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= @@ -16,8 +16,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN 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= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/config/configtelemetry/go.mod b/config/configtelemetry/go.mod index 32161410cfd..49af6aa800f 100644 --- a/config/configtelemetry/go.mod +++ b/config/configtelemetry/go.mod @@ -3,7 +3,7 @@ module go.opentelemetry.io/collector/config/configtelemetry go 1.21 require ( - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 go.uber.org/goleak v1.3.0 ) diff --git a/config/configtelemetry/go.sum b/config/configtelemetry/go.sum index b4eccab6a53..bdd6d70ba4d 100644 --- a/config/configtelemetry/go.sum +++ b/config/configtelemetry/go.sum @@ -14,8 +14,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN 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= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/config/configtls/configtls.go b/config/configtls/configtls.go index bdd80cb56cb..2090f775d49 100644 --- a/config/configtls/configtls.go +++ b/config/configtls/configtls.go @@ -4,6 +4,7 @@ package configtls // import "go.opentelemetry.io/collector/config/configtls" import ( + "context" "crypto/tls" "crypto/x509" "errors" @@ -25,10 +26,6 @@ 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 Config. @@ -75,17 +72,17 @@ type Config struct { ReloadInterval time.Duration `mapstructure:"reload_interval"` } -// 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 +// NewDefaultConfig creates a new TLSSetting with any default values set. +func NewDefaultConfig() Config { + return Config{} +} // 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 ClientConfig struct { // squash ensures fields are correctly decoded in embedded struct. - TLSSetting `mapstructure:",squash"` + Config `mapstructure:",squash"` // These are config options specific to client connections. @@ -104,17 +101,19 @@ type ClientConfig struct { ServerName string `mapstructure:"server_name_override"` } -// 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 +// NewDefaultClientConfig creates a new TLSClientSetting with any default values set. +func NewDefaultClientConfig() ClientConfig { + return ClientConfig{ + Config: NewDefaultConfig(), + } +} // 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 ServerConfig struct { // squash ensures fields are correctly decoded in embedded struct. - TLSSetting `mapstructure:",squash"` + Config `mapstructure:",squash"` // These are config options specific to server connections. @@ -128,6 +127,13 @@ type ServerConfig struct { ReloadClientCAFile bool `mapstructure:"client_ca_file_reload"` } +// NewDefaultServerConfig creates a new TLSServerSetting with any default values set. +func NewDefaultServerConfig() ServerConfig { + return ServerConfig{ + Config: NewDefaultConfig(), + } +} + // certReloader is a wrapper object for certificate reloading // Its GetCertificate method will either return the current certificate or reload from disk // if the last reload happened more than ReloadInterval ago @@ -173,6 +179,28 @@ func (r *certReloader) GetCertificate() (*tls.Certificate, error) { return r.cert, nil } +func (c Config) Validate() error { + if c.hasCAFile() && c.hasCAPem() { + return fmt.Errorf("provide either a CA file or the PEM-encoded string, but not both") + } + + minTLS, err := convertVersion(c.MinVersion, defaultMinTLSVersion) + if err != nil { + return fmt.Errorf("invalid TLS min_version: %w", err) + } + + maxTLS, err := convertVersion(c.MaxVersion, defaultMaxTLSVersion) + if err != nil { + return fmt.Errorf("invalid TLS max_version: %w", err) + } + + if maxTLS < minTLS && maxTLS != defaultMaxTLSVersion { + return errors.New("invalid TLS configuration: min_version cannot be greater than max_version") + } + + return nil +} + // loadTLSConfig loads TLS certificates and returns a tls.Config. // This will set the RootCAs and Certificates of a tls.Config. func (c Config) loadTLSConfig() (*tls.Config, error) { @@ -272,6 +300,15 @@ func (c Config) loadCertFile(certPath string) (*x509.CertPool, error) { func (c Config) loadCertPem(certPem []byte) (*x509.CertPool, error) { certPool := x509.NewCertPool() + if c.IncludeSystemCACertsPool { + scp, err := systemCertPool() + if err != nil { + return nil, err + } + if scp != nil { + certPool = scp + } + } if !certPool.AppendCertsFromPEM(certPem) { return nil, fmt.Errorf("failed to parse cert") } @@ -339,13 +376,20 @@ func (c Config) loadCert(caPath string) (*x509.CertPool, error) { return certPool, nil } +// LoadTLSConfigContext loads the TLS configuration. +// +// Deprecated: [v0.99.0] Use LoadTLSConfig instead. +func (c ClientConfig) LoadTLSConfigContext(ctx context.Context) (*tls.Config, error) { + return c.LoadTLSConfig(ctx) +} + // LoadTLSConfig loads the TLS configuration. -func (c ClientConfig) LoadTLSConfig() (*tls.Config, error) { +func (c ClientConfig) LoadTLSConfig(_ context.Context) (*tls.Config, error) { if c.Insecure && !c.hasCA() { return nil, nil } - tlsCfg, err := c.TLSSetting.loadTLSConfig() + tlsCfg, err := c.loadTLSConfig() if err != nil { return nil, fmt.Errorf("failed to load TLS config: %w", err) } @@ -354,8 +398,15 @@ func (c ClientConfig) LoadTLSConfig() (*tls.Config, error) { return tlsCfg, nil } +// LoadTLSConfigContext loads the TLS configuration. +// +// Deprecated: [v0.99.0] Use LoadTLSConfig instead. +func (c ServerConfig) LoadTLSConfigContext(ctx context.Context) (*tls.Config, error) { + return c.LoadTLSConfig(ctx) +} + // LoadTLSConfig loads the TLS configuration. -func (c ServerConfig) LoadTLSConfig() (*tls.Config, error) { +func (c ServerConfig) LoadTLSConfig(_ context.Context) (*tls.Config, error) { tlsCfg, err := c.loadTLSConfig() if err != nil { return nil, fmt.Errorf("failed to load TLS config: %w", err) diff --git a/config/configtls/configtls_test.go b/config/configtls/configtls_test.go index 47a50f58a3e..91c0e871055 100644 --- a/config/configtls/configtls_test.go +++ b/config/configtls/configtls_test.go @@ -4,6 +4,7 @@ package configtls import ( + "context" "crypto/tls" "crypto/x509" "errors" @@ -20,6 +21,28 @@ import ( "go.opentelemetry.io/collector/config/configopaque" ) +func TestNewDefaultConfig(t *testing.T) { + expectedConfig := Config{} + config := NewDefaultConfig() + require.Equal(t, expectedConfig, config) +} + +func TestNewDefaultClientConfig(t *testing.T) { + expectedConfig := ClientConfig{ + Config: NewDefaultConfig(), + } + config := NewDefaultClientConfig() + require.Equal(t, expectedConfig, config) +} + +func TestNewDefaultServerConfig(t *testing.T) { + expectedConfig := ServerConfig{ + Config: NewDefaultConfig(), + } + config := NewDefaultServerConfig() + require.Equal(t, expectedConfig, config) +} + func TestOptionsToConfig(t *testing.T) { tests := []struct { name string @@ -36,7 +59,7 @@ func TestOptionsToConfig(t *testing.T) { }, { name: "should load system CA and custom CA", - options: TLSSetting{IncludeSystemCACertsPool: true, CAFile: filepath.Join("testdata", "ca-1.crt")}, + options: Config{IncludeSystemCACertsPool: true, CAFile: filepath.Join("testdata", "ca-1.crt")}, }, { name: "should fail with invalid CA file path", @@ -249,12 +272,12 @@ func readFilePanics(filePath string) configopaque.String { func TestLoadTLSClientConfigError(t *testing.T) { tlsSetting := ClientConfig{ - TLSSetting: Config{ + Config: Config{ CertFile: "doesnt/exist", KeyFile: "doesnt/exist", }, } - _, err := tlsSetting.LoadTLSConfig() + _, err := tlsSetting.LoadTLSConfig(context.Background()) assert.Error(t, err) } @@ -262,19 +285,19 @@ func TestLoadTLSClientConfig(t *testing.T) { tlsSetting := ClientConfig{ Insecure: true, } - tlsCfg, err := tlsSetting.LoadTLSConfig() + tlsCfg, err := tlsSetting.LoadTLSConfig(context.Background()) assert.NoError(t, err) assert.Nil(t, tlsCfg) tlsSetting = ClientConfig{} - tlsCfg, err = tlsSetting.LoadTLSConfig() + tlsCfg, err = tlsSetting.LoadTLSConfig(context.Background()) assert.NoError(t, err) assert.NotNil(t, tlsCfg) tlsSetting = ClientConfig{ InsecureSkipVerify: true, } - tlsCfg, err = tlsSetting.LoadTLSConfig() + tlsCfg, err = tlsSetting.LoadTLSConfig(context.Background()) assert.NoError(t, err) assert.NotNil(t, tlsCfg) assert.True(t, tlsCfg.InsecureSkipVerify) @@ -282,24 +305,24 @@ func TestLoadTLSClientConfig(t *testing.T) { func TestLoadTLSServerConfigError(t *testing.T) { tlsSetting := ServerConfig{ - TLSSetting: Config{ + Config: Config{ CertFile: "doesnt/exist", KeyFile: "doesnt/exist", }, } - _, err := tlsSetting.LoadTLSConfig() + _, err := tlsSetting.LoadTLSConfig(context.Background()) assert.Error(t, err) tlsSetting = ServerConfig{ ClientCAFile: "doesnt/exist", } - _, err = tlsSetting.LoadTLSConfig() + _, err = tlsSetting.LoadTLSConfig(context.Background()) assert.Error(t, err) } func TestLoadTLSServerConfig(t *testing.T) { tlsSetting := ServerConfig{} - tlsCfg, err := tlsSetting.LoadTLSConfig() + tlsCfg, err := tlsSetting.LoadTLSConfig(context.Background()) assert.NoError(t, err) assert.NotNil(t, tlsCfg) } @@ -315,7 +338,7 @@ func TestLoadTLSServerConfigReload(t *testing.T) { ReloadClientCAFile: true, } - tlsCfg, err := tlsSetting.LoadTLSConfig() + tlsCfg, err := tlsSetting.LoadTLSConfig(context.Background()) assert.NoError(t, err) assert.NotNil(t, tlsCfg) @@ -346,7 +369,7 @@ func TestLoadTLSServerConfigFailingReload(t *testing.T) { ReloadClientCAFile: true, } - tlsCfg, err := tlsSetting.LoadTLSConfig() + tlsCfg, err := tlsSetting.LoadTLSConfig(context.Background()) assert.NoError(t, err) assert.NotNil(t, tlsCfg) @@ -377,7 +400,7 @@ func TestLoadTLSServerConfigFailingInitialLoad(t *testing.T) { ReloadClientCAFile: true, } - tlsCfg, err := tlsSetting.LoadTLSConfig() + tlsCfg, err := tlsSetting.LoadTLSConfig(context.Background()) assert.Error(t, err) assert.Nil(t, tlsCfg) } @@ -391,7 +414,7 @@ func TestLoadTLSServerConfigWrongPath(t *testing.T) { ReloadClientCAFile: true, } - tlsCfg, err := tlsSetting.LoadTLSConfig() + tlsCfg, err := tlsSetting.LoadTLSConfig(context.Background()) assert.Error(t, err) assert.Nil(t, tlsCfg) } @@ -407,7 +430,7 @@ func TestLoadTLSServerConfigFailing(t *testing.T) { ReloadClientCAFile: true, } - tlsCfg, err := tlsSetting.LoadTLSConfig() + tlsCfg, err := tlsSetting.LoadTLSConfig(context.Background()) assert.NoError(t, err) assert.NotNil(t, tlsCfg) @@ -633,6 +656,37 @@ func TestMinMaxTLSVersions(t *testing.T) { } } +func TestConfigValidate(t *testing.T) { + tests := []struct { + name string + tlsConfig Config + errorTxt string + }{ + {name: `TLS Config ["", ""] to be valid`, tlsConfig: Config{MinVersion: "", MaxVersion: ""}}, + {name: `TLS Config ["", "1.3"] to be valid`, tlsConfig: Config{MinVersion: "", MaxVersion: "1.3"}}, + {name: `TLS Config ["1.2", ""] to be valid`, tlsConfig: Config{MinVersion: "1.2", MaxVersion: ""}}, + {name: `TLS Config ["1.3", "1.3"] to be valid`, tlsConfig: Config{MinVersion: "1.3", MaxVersion: "1.3"}}, + {name: `TLS Config ["1.0", "1.1"] to be valid`, tlsConfig: Config{MinVersion: "1.0", MaxVersion: "1.1"}}, + {name: `TLS Config ["asd", ""] to give [Error]`, tlsConfig: Config{MinVersion: "asd", MaxVersion: ""}, errorTxt: `invalid TLS min_version: unsupported TLS version: "asd"`}, + {name: `TLS Config ["", "asd"] to give [Error]`, tlsConfig: Config{MinVersion: "", MaxVersion: "asd"}, errorTxt: `invalid TLS max_version: unsupported TLS version: "asd"`}, + {name: `TLS Config ["0.4", ""] to give [Error]`, tlsConfig: Config{MinVersion: "0.4", MaxVersion: ""}, errorTxt: `invalid TLS min_version: unsupported TLS version: "0.4"`}, + {name: `TLS Config ["1.2", "1.1"] to give [Error]`, tlsConfig: Config{MinVersion: "1.2", MaxVersion: "1.1"}, errorTxt: `invalid TLS configuration: min_version cannot be greater than max_version`}, + {name: `TLS Config with both CA File and PEM`, tlsConfig: Config{CAFile: "test", CAPem: "test"}, errorTxt: `provide either a CA file or the PEM-encoded string, but not both`}, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + err := test.tlsConfig.Validate() + + if test.errorTxt == "" { + assert.Nil(t, err) + } else { + assert.EqualError(t, err, test.errorTxt) + } + }) + } +} + func TestCipherSuites(t *testing.T) { tests := []struct { name string @@ -686,13 +740,93 @@ func TestSystemCertPool(t *testing.T) { anError := errors.New("my error") tests := []struct { name string - tlsSetting TLSSetting + tlsConfig Config + wantErr error + systemCertFn func() (*x509.CertPool, error) + }{ + { + name: "not using system cert pool", + tlsConfig: Config{ + IncludeSystemCACertsPool: false, + CAFile: filepath.Join("testdata", "ca-1.crt"), + }, + wantErr: nil, + systemCertFn: x509.SystemCertPool, + }, + { + name: "using system cert pool", + tlsConfig: Config{ + IncludeSystemCACertsPool: true, + CAFile: filepath.Join("testdata", "ca-1.crt"), + }, + wantErr: nil, + systemCertFn: x509.SystemCertPool, + }, + { + name: "error loading system cert pool", + tlsConfig: Config{ + IncludeSystemCACertsPool: true, + CAFile: filepath.Join("testdata", "ca-1.crt"), + }, + wantErr: anError, + systemCertFn: func() (*x509.CertPool, error) { + return nil, anError + }, + }, + { + name: "nil system cert pool", + tlsConfig: Config{ + IncludeSystemCACertsPool: true, + CAFile: filepath.Join("testdata", "ca-1.crt"), + }, + 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 + }() + + serverConfig := ServerConfig{ + Config: test.tlsConfig, + } + c, err := serverConfig.LoadTLSConfig(context.Background()) + if test.wantErr != nil { + assert.ErrorContains(t, err, test.wantErr.Error()) + } else { + assert.NotNil(t, c.RootCAs) + } + + clientConfig := ClientConfig{ + Config: test.tlsConfig, + } + c, err = clientConfig.LoadTLSConfig(context.Background()) + if test.wantErr != nil { + assert.ErrorContains(t, err, test.wantErr.Error()) + } else { + assert.NotNil(t, c.RootCAs) + } + }) + } +} + +func TestSystemCertPool_loadCert(t *testing.T) { + anError := errors.New("my error") + tests := []struct { + name string + tlsConfig Config wantErr error systemCertFn func() (*x509.CertPool, error) }{ { name: "not using system cert pool", - tlsSetting: TLSSetting{ + tlsConfig: Config{ IncludeSystemCACertsPool: false, }, wantErr: nil, @@ -700,7 +834,7 @@ func TestSystemCertPool(t *testing.T) { }, { name: "using system cert pool", - tlsSetting: TLSSetting{ + tlsConfig: Config{ IncludeSystemCACertsPool: true, }, wantErr: nil, @@ -708,7 +842,7 @@ func TestSystemCertPool(t *testing.T) { }, { name: "error loading system cert pool", - tlsSetting: TLSSetting{ + tlsConfig: Config{ IncludeSystemCACertsPool: true, }, wantErr: anError, @@ -718,7 +852,7 @@ func TestSystemCertPool(t *testing.T) { }, { name: "nil system cert pool", - tlsSetting: TLSSetting{ + tlsConfig: Config{ IncludeSystemCACertsPool: true, }, wantErr: nil, @@ -734,7 +868,7 @@ func TestSystemCertPool(t *testing.T) { defer func() { systemCertPool = oldSystemCertPool }() - certPool, err := test.tlsSetting.loadCert(filepath.Join("testdata", "ca-1.crt")) + certPool, err := test.tlsConfig.loadCert(filepath.Join("testdata", "ca-1.crt")) if test.wantErr != nil { assert.Equal(t, test.wantErr, err) } else { diff --git a/config/configtls/go.mod b/config/configtls/go.mod index 865c82a969e..bad5e7c38f8 100644 --- a/config/configtls/go.mod +++ b/config/configtls/go.mod @@ -4,8 +4,8 @@ go 1.21 require ( github.com/fsnotify/fsnotify v1.7.0 - github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/config/configopaque v1.3.0 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/config/configopaque v1.7.0 ) require ( diff --git a/config/configtls/go.sum b/config/configtls/go.sum index 352be822f6e..a9394e0eca4 100644 --- a/config/configtls/go.sum +++ b/config/configtls/go.sum @@ -9,8 +9,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -23,12 +23,14 @@ 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/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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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/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= diff --git a/config/internal/go.mod b/config/internal/go.mod index 7d5daac8dab..cdadc8016e1 100644 --- a/config/internal/go.mod +++ b/config/internal/go.mod @@ -3,8 +3,8 @@ module go.opentelemetry.io/collector/config/internal go 1.21 require ( - github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.96.0 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 go.uber.org/goleak v1.3.0 go.uber.org/zap v1.27.0 ) @@ -13,7 +13,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/hashicorp/go-version v1.6.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/collector/featuregate v1.3.0 // indirect + go.opentelemetry.io/collector/featuregate v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -31,3 +31,5 @@ replace go.opentelemetry.io/collector/pdata => ../../pdata replace go.opentelemetry.io/collector/consumer => ../../consumer replace go.opentelemetry.io/collector/component => ../../component + +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata diff --git a/config/internal/go.sum b/config/internal/go.sum index d7bcd0e2f73..c961debf0d0 100644 --- a/config/internal/go.sum +++ b/config/internal/go.sum @@ -10,8 +10,8 @@ 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/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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= diff --git a/config/internal/warning.go b/config/internal/warning.go index 28d55bfd4dc..f9e32fc1c64 100644 --- a/config/internal/warning.go +++ b/config/internal/warning.go @@ -38,7 +38,7 @@ func shouldWarn(endpoint string) bool { // WarnOnUnspecifiedHost emits a warning if an endpoint has an unspecified host. func WarnOnUnspecifiedHost(logger *zap.Logger, endpoint string) { - if shouldWarn(endpoint) { + if !localhostgate.UseLocalHostAsDefaultHostfeatureGate.IsEnabled() && 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. Enable the feature gate to change the default and remove this warning.", zap.String( diff --git a/confmap/confmap.go b/confmap/confmap.go index 213e4a332d9..655ccc07315 100644 --- a/confmap/confmap.go +++ b/confmap/confmap.go @@ -5,8 +5,11 @@ package confmap // import "go.opentelemetry.io/collector/confmap" import ( "encoding" + "errors" "fmt" "reflect" + "slices" + "strings" "github.com/go-viper/mapstructure/v2" "github.com/knadh/koanf/maps" @@ -157,14 +160,24 @@ func decodeConfig(m *Conf, result any, errorUnused bool) error { mapstructure.StringToTimeDurationHookFunc(), mapstructure.TextUnmarshallerHookFunc(), unmarshalerHookFunc(result), + // after the main unmarshaler hook is called, + // we unmarshal the embedded structs if present to merge with the result: + unmarshalerEmbeddedStructsHookFunc(), zeroSliceHookFunc(), + negativeUintHookFunc(), ), } decoder, err := mapstructure.NewDecoder(dc) if err != nil { return err } - return decoder.Decode(m.ToStringMap()) + if err = decoder.Decode(m.ToStringMap()); err != nil { + if strings.HasPrefix(err.Error(), "error decoding ''") { + return errors.Unwrap(err) + } + return err + } + return nil } // encoderConfig returns a default encoder.EncoderConfig that includes @@ -232,35 +245,77 @@ func expandNilStructPointersHookFunc() mapstructure.DecodeHookFuncValue { // This is needed in combination with ComponentID, which may produce equal IDs for different strings, // and an error needs to be returned in that case, otherwise the last equivalent ID overwrites the previous one. func mapKeyStringToMapKeyTextUnmarshalerHookFunc() mapstructure.DecodeHookFuncType { - return func(f reflect.Type, t reflect.Type, data any) (any, error) { - if f.Kind() != reflect.Map || f.Key().Kind() != reflect.String { + return func(from reflect.Type, to reflect.Type, data any) (any, error) { + if from.Kind() != reflect.Map || from.Key().Kind() != reflect.String { return data, nil } - if t.Kind() != reflect.Map { + if to.Kind() != reflect.Map { return data, nil } - if _, ok := reflect.New(t.Key()).Interface().(encoding.TextUnmarshaler); !ok { + // Checks that the key type of to implements the TextUnmarshaler interface. + if _, ok := reflect.New(to.Key()).Interface().(encoding.TextUnmarshaler); !ok { return data, nil } - m := reflect.MakeMap(reflect.MapOf(t.Key(), reflect.TypeOf(true))) + // Create a map with key value of to's key to bool. + fieldNameSet := reflect.MakeMap(reflect.MapOf(to.Key(), reflect.TypeOf(true))) for k := range data.(map[string]any) { - tKey := reflect.New(t.Key()) + // Create a new value of the to's key type. + tKey := reflect.New(to.Key()) + + // Use tKey to unmarshal the key of the map. if err := tKey.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(k)); err != nil { return nil, err } - - if m.MapIndex(reflect.Indirect(tKey)).IsValid() { + // Checks if the key has already been decoded in a previous iteration. + if fieldNameSet.MapIndex(reflect.Indirect(tKey)).IsValid() { return nil, fmt.Errorf("duplicate name %q after unmarshaling %v", k, tKey) } - m.SetMapIndex(reflect.Indirect(tKey), reflect.ValueOf(true)) + fieldNameSet.SetMapIndex(reflect.Indirect(tKey), reflect.ValueOf(true)) } return data, nil } } +// unmarshalerEmbeddedStructsHookFunc provides a mechanism for embedded structs to define their own unmarshal logic, +// by implementing the Unmarshaler interface. +func unmarshalerEmbeddedStructsHookFunc() mapstructure.DecodeHookFuncValue { + return func(from reflect.Value, to reflect.Value) (any, error) { + if to.Type().Kind() != reflect.Struct { + return from.Interface(), nil + } + fromAsMap, ok := from.Interface().(map[string]any) + if !ok { + return from.Interface(), nil + } + for i := 0; i < to.Type().NumField(); i++ { + // embedded structs passed in via `squash` cannot be pointers. We just check if they are structs: + f := to.Type().Field(i) + if f.IsExported() && slices.Contains(strings.Split(f.Tag.Get("mapstructure"), ","), "squash") { + if unmarshaler, ok := to.Field(i).Addr().Interface().(Unmarshaler); ok { + if err := unmarshaler.Unmarshal(NewFromStringMap(fromAsMap)); err != nil { + return nil, err + } + // the struct we receive from this unmarshaling only contains fields related to the embedded struct. + // we merge this partially unmarshaled struct with the rest of the result. + // note we already unmarshaled the main struct earlier, and therefore merge with it. + conf := New() + if err := conf.Marshal(unmarshaler); err != nil { + return nil, err + } + resultMap := conf.ToStringMap() + for k, v := range resultMap { + fromAsMap[k] = v + } + } + } + } + return fromAsMap, nil + } +} + // Provides a mechanism for individual structs to define their own unmarshal logic, // by implementing the Unmarshaler interface. func unmarshalerHookFunc(result any) mapstructure.DecodeHookFuncValue { @@ -368,3 +423,36 @@ func zeroSliceHookFunc() mapstructure.DecodeHookFuncValue { return from.Interface(), nil } } + +// This hook is used to solve the issue: https://github.com/open-telemetry/opentelemetry-collector/issues/9060 +// Decoding should fail when converting a negative integer to any type of unsigned integer. This prevents +// negative values being decoded as large uint values. +// TODO: This should be removed as a part of https://github.com/open-telemetry/opentelemetry-collector/issues/9532 +func negativeUintHookFunc() mapstructure.DecodeHookFuncValue { + return func(from reflect.Value, to reflect.Value) (interface{}, error) { + if from.CanInt() && from.Int() < 0 && to.CanUint() { + return nil, fmt.Errorf("cannot convert negative value %v to an unsigned integer", from.Int()) + } + return from.Interface(), nil + } +} + +type moduleFactory[T any, S any] interface { + Create(s S) T +} + +type createConfmapFunc[T any, S any] func(s S) T + +type confmapModuleFactory[T any, S any] struct { + f createConfmapFunc[T, S] +} + +func (c confmapModuleFactory[T, S]) Create(s S) T { + return c.f(s) +} + +func newConfmapModuleFactory[T any, S any](f createConfmapFunc[T, S]) moduleFactory[T, S] { + return confmapModuleFactory[T, S]{ + f: f, + } +} diff --git a/confmap/confmap_test.go b/confmap/confmap_test.go index 6680a1bc517..a1ea94e1fe4 100644 --- a/confmap/confmap_test.go +++ b/confmap/confmap_test.go @@ -5,6 +5,7 @@ package confmap import ( "errors" + "fmt" "os" "path/filepath" "strings" @@ -213,6 +214,74 @@ func TestMapKeyStringToMapKeyTextUnmarshalerHookFunc(t *testing.T) { assert.Equal(t, map[TestID]string{"string": "this is a string"}, cfg.Map) } +type UintConfig struct { + UintTest uint32 `mapstructure:"uint_test"` +} + +func TestUintUnmarshalerSuccess(t *testing.T) { + tests := []struct { + name string + testValue int + }{ + { + name: "Test convert 0 to uint", + testValue: 0, + }, + { + name: "Test positive uint conversion", + testValue: 1000, + }, + } + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + stringMap := map[string]any{ + "uint_test": tt.testValue, + } + conf := NewFromStringMap(stringMap) + cfg := &UintConfig{} + err := conf.Unmarshal(cfg) + + assert.NoError(t, err) + assert.Equal(t, cfg.UintTest, uint32(tt.testValue)) + }) + } +} + +func TestUint64Unmarshaler(t *testing.T) { + negativeInt := -1000 + testValue := uint64(negativeInt) + + type Uint64Config struct { + UintTest uint64 `mapstructure:"uint_test"` + } + stringMap := map[string]any{ + "uint_test": testValue, + } + + conf := NewFromStringMap(stringMap) + cfg := &Uint64Config{} + err := conf.Unmarshal(cfg) + + assert.NoError(t, err) + assert.Equal(t, cfg.UintTest, testValue) +} + +func TestUintUnmarshalerFailure(t *testing.T) { + testValue := -1000 + stringMap := map[string]any{ + "uint_test": testValue, + } + conf := NewFromStringMap(stringMap) + cfg := &UintConfig{} + err := conf.Unmarshal(cfg) + + assert.Error(t, err) + assert.Contains(t, err.Error(), fmt.Sprintf("* error decoding 'uint_test': cannot convert negative value %v to an unsigned integer", testValue)) +} + func TestMapKeyStringToMapKeyTextUnmarshalerHookFuncDuplicateID(t *testing.T) { stringMap := map[string]any{ "bool": true, @@ -309,8 +378,78 @@ func newConfFromFile(t testing.TB, fileName string) map[string]any { } type testConfig struct { - Next *nextConfig `mapstructure:"next"` - Another string `mapstructure:"another"` + Next *nextConfig `mapstructure:"next"` + Another string `mapstructure:"another"` + EmbeddedConfig `mapstructure:",squash"` + EmbeddedConfig2 `mapstructure:",squash"` +} + +type testConfigWithoutUnmarshaler struct { + Next *nextConfig `mapstructure:"next"` + Another string `mapstructure:"another"` + EmbeddedConfig `mapstructure:",squash"` + EmbeddedConfig2 `mapstructure:",squash"` +} + +type testConfigWithEmbeddedError struct { + Next *nextConfig `mapstructure:"next"` + Another string `mapstructure:"another"` + EmbeddedConfigWithError `mapstructure:",squash"` +} + +type testConfigWithMarshalError struct { + Next *nextConfig `mapstructure:"next"` + Another string `mapstructure:"another"` + EmbeddedConfigWithMarshalError `mapstructure:",squash"` +} + +func (tc *testConfigWithEmbeddedError) Unmarshal(component *Conf) error { + if err := component.Unmarshal(tc, WithIgnoreUnused()); err != nil { + return err + } + return nil +} + +type EmbeddedConfig struct { + Some string `mapstructure:"some"` +} + +func (ec *EmbeddedConfig) Unmarshal(component *Conf) error { + if err := component.Unmarshal(ec, WithIgnoreUnused()); err != nil { + return err + } + ec.Some += " is also called" + return nil +} + +type EmbeddedConfig2 struct { + Some2 string `mapstructure:"some_2"` +} + +func (ec *EmbeddedConfig2) Unmarshal(component *Conf) error { + if err := component.Unmarshal(ec, WithIgnoreUnused()); err != nil { + return err + } + ec.Some2 += " also called2" + return nil +} + +type EmbeddedConfigWithError struct { +} + +func (ecwe *EmbeddedConfigWithError) Unmarshal(_ *Conf) error { + return errors.New("embedded error") +} + +type EmbeddedConfigWithMarshalError struct { +} + +func (ecwe EmbeddedConfigWithMarshalError) Marshal(_ *Conf) error { + return errors.New("marshaling error") +} + +func (ecwe EmbeddedConfigWithMarshalError) Unmarshal(_ *Conf) error { + return nil } func (tc *testConfig) Unmarshal(component *Conf) error { @@ -340,12 +479,59 @@ func TestUnmarshaler(t *testing.T) { "string": "make sure this", }, "another": "make sure this", + "some": "make sure this", + "some_2": "this better be", }) tc := &testConfig{} assert.NoError(t, cfgMap.Unmarshal(tc)) assert.Equal(t, "make sure this", tc.Another) assert.Equal(t, "make sure this is called", tc.Next.String) + assert.Equal(t, "make sure this is also called", tc.EmbeddedConfig.Some) + assert.Equal(t, "this better be also called2", tc.EmbeddedConfig2.Some2) +} + +func TestEmbeddedUnmarshaler(t *testing.T) { + cfgMap := NewFromStringMap(map[string]any{ + "next": map[string]any{ + "string": "make sure this", + }, + "another": "make sure this", + "some": "make sure this", + "some_2": "this better be", + }) + + tc := &testConfigWithoutUnmarshaler{} + assert.NoError(t, cfgMap.Unmarshal(tc)) + assert.Equal(t, "make sure this", tc.Another) + assert.Equal(t, "make sure this is called", tc.Next.String) + assert.Equal(t, "make sure this is also called", tc.EmbeddedConfig.Some) + assert.Equal(t, "this better be also called2", tc.EmbeddedConfig2.Some2) +} + +func TestEmbeddedUnmarshalerError(t *testing.T) { + cfgMap := NewFromStringMap(map[string]any{ + "next": map[string]any{ + "string": "make sure this", + }, + "another": "make sure this", + "some": "make sure this", + }) + + tc := &testConfigWithEmbeddedError{} + assert.EqualError(t, cfgMap.Unmarshal(tc), "embedded error") +} + +func TestEmbeddedMarshalerError(t *testing.T) { + cfgMap := NewFromStringMap(map[string]any{ + "next": map[string]any{ + "string": "make sure this", + }, + "another": "make sure this", + }) + + tc := &testConfigWithMarshalError{} + assert.EqualError(t, cfgMap.Unmarshal(tc), "error running encode hook: marshaling error") } func TestUnmarshalerKeepAlreadyInitialized(t *testing.T) { @@ -496,3 +682,148 @@ func TestZeroSliceHookFunc(t *testing.T) { }) } } + +type C struct { + Modifiers []string `mapstructure:"modifiers"` +} + +func (c *C) Unmarshal(conf *Conf) error { + if err := conf.Unmarshal(c); err != nil { + return err + } + c.Modifiers = append(c.Modifiers, "C.Unmarshal") + return nil +} + +type B struct { + Modifiers []string `mapstructure:"modifiers"` + C C `mapstructure:"c"` +} + +func (b *B) Unmarshal(conf *Conf) error { + if err := conf.Unmarshal(b); err != nil { + return err + } + b.Modifiers = append(b.Modifiers, "B.Unmarshal") + b.C.Modifiers = append(b.C.Modifiers, "B.Unmarshal") + return nil +} + +type A struct { + Modifiers []string `mapstructure:"modifiers"` + B B `mapstructure:"b"` +} + +func (a *A) Unmarshal(conf *Conf) error { + if err := conf.Unmarshal(a); err != nil { + return err + } + a.Modifiers = append(a.Modifiers, "A.Unmarshal") + a.B.Modifiers = append(a.B.Modifiers, "A.Unmarshal") + a.B.C.Modifiers = append(a.B.C.Modifiers, "A.Unmarshal") + return nil +} + +type Wrapper struct { + A A `mapstructure:"a"` +} + +// Test that calling the Unmarshal method on configuration structs is done from the inside out. +func TestNestedUnmarshalerImplementations(t *testing.T) { + conf := NewFromStringMap(map[string]any{"a": map[string]any{ + "modifiers": []string{"conf.Unmarshal"}, + "b": map[string]any{ + "modifiers": []string{"conf.Unmarshal"}, + "c": map[string]any{ + "modifiers": []string{"conf.Unmarshal"}, + }, + }, + }}) + + // Use a wrapper struct until we deprecate component.UnmarshalConfig + w := &Wrapper{} + assert.NoError(t, conf.Unmarshal(w)) + + a := w.A + assert.Equal(t, []string{"conf.Unmarshal", "A.Unmarshal"}, a.Modifiers) + assert.Equal(t, []string{"conf.Unmarshal", "B.Unmarshal", "A.Unmarshal"}, a.B.Modifiers) + assert.Equal(t, []string{"conf.Unmarshal", "C.Unmarshal", "B.Unmarshal", "A.Unmarshal"}, a.B.C.Modifiers) +} + +// Test that unmarshaling the same conf twice works. +func TestUnmarshalDouble(t *testing.T) { + conf := NewFromStringMap(map[string]any{ + "str": "test", + }) + + type Struct struct { + Str string `mapstructure:"str"` + } + s := &Struct{} + assert.NoError(t, conf.Unmarshal(s)) + assert.Equal(t, "test", s.Str) + + type Struct2 struct { + Str string `mapstructure:"str"` + } + s2 := &Struct2{} + assert.NoError(t, conf.Unmarshal(s2)) + assert.Equal(t, "test", s2.Str) +} + +type EmbeddedStructWithUnmarshal struct { + Foo string `mapstructure:"foo"` + success string +} + +func (e *EmbeddedStructWithUnmarshal) Unmarshal(c *Conf) error { + if err := c.Unmarshal(e, WithIgnoreUnused()); err != nil { + return err + } + e.success = "success" + return nil +} + +type configWithUnmarshalFromEmbeddedStruct struct { + EmbeddedStructWithUnmarshal +} + +type topLevel struct { + Cfg *configWithUnmarshalFromEmbeddedStruct `mapstructure:"toplevel"` +} + +// Test that Unmarshal is called on the embedded struct on the struct. +func TestUnmarshalThroughEmbeddedStruct(t *testing.T) { + c := NewFromStringMap(map[string]any{ + "toplevel": map[string]any{ + "foo": "bar", + }, + }) + cfg := &topLevel{} + err := c.Unmarshal(cfg) + require.NoError(t, err) + require.Equal(t, "success", cfg.Cfg.EmbeddedStructWithUnmarshal.success) + require.Equal(t, "bar", cfg.Cfg.EmbeddedStructWithUnmarshal.Foo) +} + +type configWithOwnUnmarshalAndEmbeddedSquashedStruct struct { + EmbeddedStructWithUnmarshal `mapstructure:",squash"` +} + +type topLevelSquashedEmbedded struct { + Cfg *configWithOwnUnmarshalAndEmbeddedSquashedStruct `mapstructure:"toplevel"` +} + +// Test that the Unmarshal method is called on the squashed, embedded struct. +func TestUnmarshalOwnThroughEmbeddedSquashedStruct(t *testing.T) { + c := NewFromStringMap(map[string]any{ + "toplevel": map[string]any{ + "foo": "bar", + }, + }) + cfg := &topLevelSquashedEmbedded{} + err := c.Unmarshal(cfg) + require.NoError(t, err) + require.Equal(t, "success", cfg.Cfg.EmbeddedStructWithUnmarshal.success) + require.Equal(t, "bar", cfg.Cfg.EmbeddedStructWithUnmarshal.Foo) +} diff --git a/confmap/confmaptest/provider_settings.go b/confmap/confmaptest/provider_settings.go new file mode 100644 index 00000000000..8d36b36efca --- /dev/null +++ b/confmap/confmaptest/provider_settings.go @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package confmaptest // import "go.opentelemetry.io/collector/confmap/confmaptest" + +import ( + "go.uber.org/zap" + + "go.opentelemetry.io/collector/confmap" +) + +func NewNopProviderSettings() confmap.ProviderSettings { + return confmap.ProviderSettings{Logger: zap.NewNop()} +} diff --git a/confmap/converter.go b/confmap/converter.go index 17316d10304..2dce87e496e 100644 --- a/confmap/converter.go +++ b/confmap/converter.go @@ -8,9 +8,20 @@ import ( ) // ConverterSettings are the settings to initialize a Converter. -// Any Converter should take this as a parameter in its constructor. type ConverterSettings struct{} +// ConverterFactory defines a factory that can be used to instantiate +// new instances of a Converter. +type ConverterFactory = moduleFactory[Converter, ConverterSettings] + +// CreateConverterFunc is a function that creates a Converter instance. +type CreateConverterFunc = createConfmapFunc[Converter, ConverterSettings] + +// NewConverterFactory can be used to create a ConverterFactory. +func NewConverterFactory(f CreateConverterFunc) ConverterFactory { + return newConfmapModuleFactory(f) +} + // 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/expand.go b/confmap/converter/expandconverter/expand.go index dc3a89812c4..f07617cd3d6 100644 --- a/confmap/converter/expandconverter/expand.go +++ b/confmap/converter/expandconverter/expand.go @@ -5,42 +5,62 @@ package expandconverter // import "go.opentelemetry.io/collector/confmap/convert import ( "context" + "fmt" "os" + "regexp" + + "go.uber.org/zap" "go.opentelemetry.io/collector/confmap" ) -type converter struct{} +type converter struct { + logger *zap.Logger + + // Record of which env vars we have logged a warning for + loggedDeprecations map[string]struct{} +} // New returns a confmap.Converter, that expands all environment variables for a given confmap.Conf. // // Notice: This API is experimental. -func New(confmap.ConverterSettings) confmap.Converter { - return converter{} +// +// Deprecated: [v0.99.0] Use NewFactory instead. +func New(_ confmap.ConverterSettings) confmap.Converter { + return converter{ + loggedDeprecations: make(map[string]struct{}), + logger: zap.NewNop(), // TODO: pass logger in ConverterSettings + } +} + +// NewFactory returns a factory for a confmap.Converter, +// which expands all environment variables for a given confmap.Conf. +func NewFactory() confmap.ConverterFactory { + return confmap.NewConverterFactory(New) } -func (converter) Convert(_ context.Context, conf *confmap.Conf) error { +func (c converter) Convert(_ context.Context, conf *confmap.Conf) error { out := make(map[string]any) for _, k := range conf.AllKeys() { - out[k] = expandStringValues(conf.Get(k)) + out[k] = c.expandStringValues(conf.Get(k)) } return conf.Merge(confmap.NewFromStringMap(out)) } -func expandStringValues(value any) any { +func (c converter) expandStringValues(value any) any { switch v := value.(type) { case string: - return expandEnv(v) + return c.expandEnv(v) case []any: nslice := make([]any, 0, len(v)) for _, vint := range v { - nslice = append(nslice, expandStringValues(vint)) + nslice = append(nslice, c.expandStringValues(vint)) } return nslice case map[string]any: nmap := map[string]any{} for mk, mv := range v { - nmap[mk] = expandStringValues(mv) + nmap[mk] = c.expandStringValues(mv) } return nmap default: @@ -48,8 +68,16 @@ func expandStringValues(value any) any { } } -func expandEnv(s string) string { +func (c converter) expandEnv(s string) string { return os.Expand(s, func(str string) string { + // Matches on $VAR style environment variables + // in order to make sure we don't log a warning for ${VAR} + var regex = regexp.MustCompile(fmt.Sprintf(`\$%s`, regexp.QuoteMeta(str))) + if _, exists := c.loggedDeprecations[str]; !exists && regex.MatchString(s) { + msg := fmt.Sprintf("Variable substitution using $VAR will be deprecated in favor of ${VAR} and ${env:VAR}, please update $%s", str) + c.logger.Warn(msg, zap.String("variable", str)) + c.loggedDeprecations[str] = struct{}{} + } // This allows escaping environment variable substitution via $$, e.g. // - $FOO will be substituted with env var FOO // - $$FOO will be replaced with $FOO diff --git a/confmap/converter/expandconverter/expand_test.go b/confmap/converter/expandconverter/expand_test.go index 731dd52e9b6..424a8be0319 100644 --- a/confmap/converter/expandconverter/expand_test.go +++ b/confmap/converter/expandconverter/expand_test.go @@ -5,11 +5,15 @@ package expandconverter import ( "context" + "fmt" "path/filepath" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "go.uber.org/zap/zaptest/observer" "go.opentelemetry.io/collector/confmap" "go.opentelemetry.io/collector/confmap/confmaptest" @@ -45,7 +49,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(confmap.ConverterSettings{}).Convert(context.Background(), conf)) + require.NoError(t, createConverter().Convert(context.Background(), conf)) assert.Equal(t, expectedCfgMap.ToStringMap(), conf.ToStringMap()) }) } @@ -64,7 +68,7 @@ func TestNewExpandConverter_EscapedMaps(t *testing.T) { "recv": "$MAP_VALUE", }}, ) - require.NoError(t, New(confmap.ConverterSettings{}).Convert(context.Background(), conf)) + require.NoError(t, createConverter().Convert(context.Background(), conf)) expectedMap := map[string]any{ "test_string_map": map[string]any{ @@ -101,7 +105,7 @@ func TestNewExpandConverter_EscapedEnvVars(t *testing.T) { // escaped $ alone "recv.7": "$", }} - require.NoError(t, New(confmap.ConverterSettings{}).Convert(context.Background(), conf)) + require.NoError(t, createConverter().Convert(context.Background(), conf)) assert.Equal(t, expectedMap, conf.ToStringMap()) } @@ -154,8 +158,101 @@ 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(confmap.ConverterSettings{}).Convert(context.Background(), conf)) + require.NoError(t, createConverter().Convert(context.Background(), conf)) assert.Equal(t, tt.expected, conf.ToStringMap()) }) } } + +func NewTestConverter() (confmap.Converter, *observer.ObservedLogs) { + core, logs := observer.New(zapcore.InfoLevel) + conv := converter{loggedDeprecations: make(map[string]struct{}), logger: zap.New(core)} + return conv, logs +} + +func TestDeprecatedWarning(t *testing.T) { + msgTemplate := `Variable substitution using $VAR will be deprecated in favor of ${VAR} and ${env:VAR}, please update $%s` + t.Setenv("HOST", "127.0.0.1") + t.Setenv("PORT", "4317") + + t.Setenv("HOST_NAME", "127.0.0.2") + t.Setenv("HOST.NAME", "127.0.0.3") + + var testCases = []struct { + name string + input map[string]any + expectedOutput map[string]any + expectedWarnings []string + }{ + { + name: "no warning", + input: map[string]any{ + "test": "${HOST}:${PORT}", + }, + expectedOutput: map[string]any{ + "test": "127.0.0.1:4317", + }, + expectedWarnings: []string{}, + }, + { + name: "one deprecated var", + input: map[string]any{ + "test": "${HOST}:$PORT", + }, + expectedOutput: map[string]any{ + "test": "127.0.0.1:4317", + }, + expectedWarnings: []string{"PORT"}, + }, + { + name: "two deprecated vars", + input: map[string]any{ + "test": "$HOST:$PORT", + }, + expectedOutput: map[string]any{ + "test": "127.0.0.1:4317", + }, + expectedWarnings: []string{"HOST", "PORT"}, + }, + { + name: "one depracated serveral times", + input: map[string]any{ + "test": "$HOST,$HOST", + "test2": "$HOST", + }, + expectedOutput: map[string]any{ + "test": "127.0.0.1,127.0.0.1", + "test2": "127.0.0.1", + }, + expectedWarnings: []string{"HOST"}, + }, + { + name: "one warning", + input: map[string]any{ + "test": "$HOST_NAME,${HOST.NAME}", + }, + expectedOutput: map[string]any{ + "test": "127.0.0.2,127.0.0.3", + }, + expectedWarnings: []string{"HOST_NAME"}, + }, + } + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + conf := confmap.NewFromStringMap(tt.input) + conv, logs := NewTestConverter() + require.NoError(t, conv.Convert(context.Background(), conf)) + + assert.Equal(t, tt.expectedOutput, conf.ToStringMap()) + assert.Equal(t, len(tt.expectedWarnings), len(logs.All())) + for i, variable := range tt.expectedWarnings { + errorMsg := fmt.Sprintf(msgTemplate, variable) + assert.Equal(t, errorMsg, logs.All()[i].Message) + } + }) + } +} + +func createConverter() confmap.Converter { + return NewFactory().Create(confmap.ConverterSettings{}) +} diff --git a/confmap/converter/expandconverter/go.mod b/confmap/converter/expandconverter/go.mod index 81efa808243..9e9492973b4 100644 --- a/confmap/converter/expandconverter/go.mod +++ b/confmap/converter/expandconverter/go.mod @@ -3,9 +3,10 @@ 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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/confmap v0.100.0 go.uber.org/goleak v1.3.0 + go.uber.org/zap v1.27.0 ) require ( @@ -13,7 +14,7 @@ require ( 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/knadh/koanf/v2 v2.1.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 diff --git a/confmap/converter/expandconverter/go.sum b/confmap/converter/expandconverter/go.sum index 69f4a4f6724..e70f902d5f5 100644 --- a/confmap/converter/expandconverter/go.sum +++ b/confmap/converter/expandconverter/go.sum @@ -6,8 +6,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -18,12 +18,14 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx 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= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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= 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= diff --git a/confmap/doc_test.go b/confmap/doc_test.go new file mode 100644 index 00000000000..d026bc2d733 --- /dev/null +++ b/confmap/doc_test.go @@ -0,0 +1,97 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package confmap_test + +import ( + "fmt" + "slices" + "time" + + "go.opentelemetry.io/collector/confmap" +) + +type DiskScrape struct { + Disk string `mapstructure:"disk"` + Scrape time.Duration `mapstructure:"scrape"` +} + +// We can annotate a struct with mapstructure field annotations. +func Example_simpleUnmarshaling() { + conf := confmap.NewFromStringMap(map[string]any{ + "disk": "c", + "scrape": "5s", + }) + scrapeInfo := &DiskScrape{} + if err := conf.Unmarshal(scrapeInfo); err != nil { + panic(err) + } + fmt.Printf("Configuration contains the following:\nDisk: %q\nScrape: %s\n", scrapeInfo.Disk, scrapeInfo.Scrape) + //Output: Configuration contains the following: + // Disk: "c" + // Scrape: 5s +} + +type CPUScrape struct { + Enabled bool `mapstructure:"enabled"` +} + +type ComputerScrape struct { + DiskScrape `mapstructure:",squash"` + CPUScrape `mapstructure:",squash"` +} + +// We can unmarshal embedded structs with mapstructure field annotations. +func Example_embeddedUnmarshaling() { + conf := confmap.NewFromStringMap(map[string]any{ + "disk": "c", + "scrape": "5s", + "enabled": true, + }) + scrapeInfo := &ComputerScrape{} + if err := conf.Unmarshal(scrapeInfo); err != nil { + panic(err) + } + fmt.Printf("Configuration contains the following:\nDisk: %q\nScrape: %s\nEnabled: %v\n", scrapeInfo.Disk, scrapeInfo.Scrape, scrapeInfo.Enabled) + //Output: Configuration contains the following: + // Disk: "c" + // Scrape: 5s + // Enabled: true +} + +type NetworkScrape struct { + Enabled bool `mapstructure:"enabled"` + Networks []string `mapstructure:"networks"` + Wifi bool `mapstructure:"wifi"` +} + +func (n *NetworkScrape) Unmarshal(c *confmap.Conf) error { + if err := c.Unmarshal(n, confmap.WithIgnoreUnused()); err != nil { + return err + } + if slices.Contains(n.Networks, "wlan0") { + n.Wifi = true + } + return nil +} + +type RouterScrape struct { + NetworkScrape `mapstructure:",squash"` +} + +// We can unmarshal an embedded struct with a custom `Unmarshal` method. +func Example_embeddedManualUnmarshaling() { + conf := confmap.NewFromStringMap(map[string]any{ + "networks": []string{"eth0", "eth1", "wlan0"}, + "enabled": true, + }) + scrapeInfo := &RouterScrape{} + if err := conf.Unmarshal(scrapeInfo); err != nil { + panic(err) + } + fmt.Printf("Configuration contains the following:\nNetworks: %q\nWifi: %v\nEnabled: %v\n", scrapeInfo.Networks, scrapeInfo.Wifi, scrapeInfo.Enabled) + //Output: Configuration contains the following: + // Networks: ["eth0" "eth1" "wlan0"] + // Wifi: true + // Enabled: true +} diff --git a/confmap/expand_test.go b/confmap/expand_test.go index 98ad790feeb..c1dc6646152 100644 --- a/confmap/expand_test.go +++ b/confmap/expand_test.go @@ -42,7 +42,7 @@ func TestResolverExpandEnvVars(t *testing.T) { for _, test := range testCases { t.Run(test.name, func(t *testing.T) { - resolver, err := NewResolver(ResolverSettings{URIs: []string{filepath.Join("testdata", test.name)}, Providers: makeMapProvidersMap(fileProvider, envProvider), Converters: nil}) + resolver, err := NewResolver(ResolverSettings{URIs: []string{filepath.Join("testdata", test.name)}, ProviderFactories: []ProviderFactory{fileProvider, envProvider}, ConverterFactories: nil}) require.NoError(t, err) // Test that expanded configs are the same with the simple config with no env vars. @@ -65,7 +65,7 @@ func TestResolverDoneNotExpandOldEnvVars(t *testing.T) { return NewRetrieved("some string") }) - resolver, err := NewResolver(ResolverSettings{URIs: []string{"test:"}, Providers: makeMapProvidersMap(fileProvider, envProvider, emptySchemeProvider), Converters: nil}) + resolver, err := NewResolver(ResolverSettings{URIs: []string{"test:"}, ProviderFactories: []ProviderFactory{fileProvider, envProvider, emptySchemeProvider}, ConverterFactories: nil}) require.NoError(t, err) // Test that expanded configs are the same with the simple config with no env vars. @@ -86,7 +86,7 @@ func TestResolverExpandMapAndSliceValues(t *testing.T) { return NewRetrieved(receiverExtraMapValue) }) - resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, testProvider), Converters: nil}) + resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, testProvider}, ConverterFactories: nil}) require.NoError(t, err) cfgMap, err := resolver.Resolve(context.Background()) @@ -295,7 +295,7 @@ func TestResolverExpandStringValues(t *testing.T) { return NewRetrieved(uri[5:]) }) - resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, newEnvProvider(), testProvider), Converters: nil}) + resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, newEnvProvider(), testProvider}, ConverterFactories: nil}) require.NoError(t, err) cfgMap, err := resolver.Resolve(context.Background()) @@ -305,7 +305,7 @@ func TestResolverExpandStringValues(t *testing.T) { } } -func newEnvProvider() Provider { +func newEnvProvider() ProviderFactory { return newFakeProvider("env", func(_ context.Context, uri string, _ WatcherFunc) (*Retrieved, error) { switch uri { case "env:COMPLEX_VALUE": @@ -369,7 +369,7 @@ func TestResolverExpandReturnError(t *testing.T) { return nil, myErr }) - resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, testProvider), Converters: nil}) + resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, testProvider}, ConverterFactories: nil}) require.NoError(t, err) _, err = resolver.Resolve(context.Background()) @@ -388,7 +388,7 @@ func TestResolverInfiniteExpand(t *testing.T) { return NewRetrieved(receiverValue) }) - resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, testProvider), Converters: nil}) + resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, testProvider}, ConverterFactories: nil}) require.NoError(t, err) _, err = resolver.Resolve(context.Background()) @@ -404,7 +404,7 @@ func TestResolverExpandInvalidScheme(t *testing.T) { panic("must not be called") }) - resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, testProvider), Converters: nil}) + resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, testProvider}, ConverterFactories: nil}) require.NoError(t, err) _, err = resolver.Resolve(context.Background()) @@ -421,7 +421,7 @@ func TestResolverExpandInvalidOpaqueValue(t *testing.T) { panic("must not be called") }) - resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, testProvider), Converters: nil}) + resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, testProvider}, ConverterFactories: nil}) require.NoError(t, err) _, err = resolver.Resolve(context.Background()) @@ -437,7 +437,7 @@ func TestResolverExpandUnsupportedScheme(t *testing.T) { panic("must not be called") }) - resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, testProvider), Converters: nil}) + resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, testProvider}, ConverterFactories: nil}) require.NoError(t, err) _, err = resolver.Resolve(context.Background()) @@ -453,7 +453,7 @@ func TestResolverExpandStringValueInvalidReturnValue(t *testing.T) { return NewRetrieved([]any{1243}) }) - resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, testProvider), Converters: nil}) + resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, testProvider}, ConverterFactories: nil}) require.NoError(t, err) _, err = resolver.Resolve(context.Background()) diff --git a/confmap/go.mod b/confmap/go.mod index 869cdedbe72..10e84cb18b5 100644 --- a/confmap/go.mod +++ b/confmap/go.mod @@ -6,16 +6,16 @@ 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.1.0 - github.com/stretchr/testify v1.8.4 + github.com/knadh/koanf/v2 v2.1.1 + github.com/stretchr/testify v1.9.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 + go.uber.org/zap v1.27.0 gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/kr/text v0.2.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 diff --git a/confmap/go.sum b/confmap/go.sum index 386dd5d4525..e70f902d5f5 100644 --- a/confmap/go.sum +++ b/confmap/go.sum @@ -1,4 +1,3 @@ -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= @@ -7,8 +6,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -19,12 +18,14 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx 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= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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= 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= diff --git a/confmap/provider.go b/confmap/provider.go index 91c2a60065a..95c0581327e 100644 --- a/confmap/provider.go +++ b/confmap/provider.go @@ -6,11 +6,30 @@ package confmap // import "go.opentelemetry.io/collector/confmap" import ( "context" "fmt" + + "go.uber.org/zap" ) // ProviderSettings are the settings to initialize a Provider. -// Any Provider should take this as a parameter in its constructor. -type ProviderSettings struct{} +type ProviderSettings struct { + // Logger is a zap.Logger that will be passed to Providers. + // Providers should be able to rely on the Logger being non-nil; + // when instantiating a Provider with a ProviderFactory, + // nil Logger references should be replaced with a no-op Logger. + Logger *zap.Logger +} + +// ProviderFactory defines a factory that can be used to instantiate +// new instances of a Provider. +type ProviderFactory = moduleFactory[Provider, ProviderSettings] + +// CreateProviderFunc is a function that creates a Provider instance. +type CreateProviderFunc = createConfmapFunc[Provider, ProviderSettings] + +// NewProviderFactory can be used to create a ProviderFactory. +func NewProviderFactory(f CreateProviderFunc) ProviderFactory { + return newConfmapModuleFactory(f) +} // 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, diff --git a/confmap/provider/envprovider/go.mod b/confmap/provider/envprovider/go.mod index 86036ea552f..9e9fed7326c 100644 --- a/confmap/provider/envprovider/go.mod +++ b/confmap/provider/envprovider/go.mod @@ -3,9 +3,10 @@ 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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/confmap v0.100.0 go.uber.org/goleak v1.3.0 + go.uber.org/zap v1.27.0 ) require ( @@ -13,7 +14,7 @@ require ( 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/knadh/koanf/v2 v2.1.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 diff --git a/confmap/provider/envprovider/go.sum b/confmap/provider/envprovider/go.sum index 69f4a4f6724..e70f902d5f5 100644 --- a/confmap/provider/envprovider/go.sum +++ b/confmap/provider/envprovider/go.sum @@ -6,8 +6,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -18,12 +18,14 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx 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= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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= 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= diff --git a/confmap/provider/envprovider/provider.go b/confmap/provider/envprovider/provider.go index 61e8df8fbbf..c153893cb87 100644 --- a/confmap/provider/envprovider/provider.go +++ b/confmap/provider/envprovider/provider.go @@ -9,37 +9,51 @@ import ( "os" "strings" + "go.uber.org/zap" + "go.opentelemetry.io/collector/confmap" "go.opentelemetry.io/collector/confmap/provider/internal" ) const schemeName = "env" -type provider struct{} +type provider struct { + logger *zap.Logger +} // 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{} +// +// Deprecated: [v0.99.0] Use NewFactory instead. +func NewWithSettings(ps confmap.ProviderSettings) confmap.Provider { + return &provider{ + logger: ps.Logger, + } } -// New returns a new confmap.Provider that reads the configuration from the given environment variable. +// NewFactory returns a factory for a 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 NewWithSettings(confmap.ProviderSettings{}) +func NewFactory() confmap.ProviderFactory { + return confmap.NewProviderFactory(NewWithSettings) } func (emp *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) } + envVarName := uri[len(schemeName)+1:] + val, exists := os.LookupEnv(envVarName) + if !exists { + emp.logger.Warn("Configuration references unset environment variable", zap.String("name", envVarName)) + } else if len(val) == 0 { + emp.logger.Info("Configuration references empty environment variable", zap.String("name", envVarName)) + } - return internal.NewRetrievedFromYAML([]byte(os.Getenv(uri[len(schemeName)+1:]))) + return internal.NewRetrievedFromYAML([]byte(val)) } func (*provider) Scheme() string { diff --git a/confmap/provider/envprovider/provider_test.go b/confmap/provider/envprovider/provider_test.go index d7bb0e2d992..c5fcbd91eee 100644 --- a/confmap/provider/envprovider/provider_test.go +++ b/confmap/provider/envprovider/provider_test.go @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.uber.org/zap" + "go.uber.org/zap/zaptest/observer" "go.opentelemetry.io/collector/confmap" "go.opentelemetry.io/collector/confmap/confmaptest" @@ -25,18 +27,18 @@ exporters: ` func TestValidateProviderScheme(t *testing.T) { - assert.NoError(t, confmaptest.ValidateProviderScheme(New())) + assert.NoError(t, confmaptest.ValidateProviderScheme(createProvider())) } func TestEmptyName(t *testing.T) { - env := New() + env := createProvider() _, err := env.Retrieve(context.Background(), "", nil) require.Error(t, err) assert.NoError(t, env.Shutdown(context.Background())) } func TestUnsupportedScheme(t *testing.T) { - env := New() + env := createProvider() _, err := env.Retrieve(context.Background(), "https://", nil) assert.Error(t, err) assert.NoError(t, env.Shutdown(context.Background())) @@ -45,7 +47,7 @@ func TestUnsupportedScheme(t *testing.T) { func TestInvalidYAML(t *testing.T) { const envName = "invalid-yaml" t.Setenv(envName, "[invalid,") - env := New() + env := createProvider() _, err := env.Retrieve(context.Background(), envSchemePrefix+envName, nil) assert.Error(t, err) assert.NoError(t, env.Shutdown(context.Background())) @@ -55,7 +57,7 @@ func TestEnv(t *testing.T) { const envName = "default-config" t.Setenv(envName, validYAML) - env := New() + env := createProvider() ret, err := env.Retrieve(context.Background(), envSchemePrefix+envName, nil) require.NoError(t, err) retMap, err := ret.AsConf() @@ -68,3 +70,74 @@ func TestEnv(t *testing.T) { assert.NoError(t, env.Shutdown(context.Background())) } + +func TestEnvWithLogger(t *testing.T) { + const envName = "default-config" + t.Setenv(envName, validYAML) + core, ol := observer.New(zap.WarnLevel) + logger := zap.New(core) + + env := NewWithSettings(confmap.ProviderSettings{Logger: logger}) + ret, err := env.Retrieve(context.Background(), envSchemePrefix+envName, nil) + require.NoError(t, err) + retMap, err := ret.AsConf() + assert.NoError(t, err) + expectedMap := confmap.NewFromStringMap(map[string]any{ + "processors::batch": nil, + "exporters::otlp::endpoint": "localhost:4317", + }) + assert.Equal(t, expectedMap.ToStringMap(), retMap.ToStringMap()) + + assert.NoError(t, env.Shutdown(context.Background())) + assert.Equal(t, 0, ol.Len()) +} + +func TestUnsetEnvWithLoggerWarn(t *testing.T) { + const envName = "default-config" + core, ol := observer.New(zap.WarnLevel) + logger := zap.New(core) + + env := NewWithSettings(confmap.ProviderSettings{Logger: logger}) + ret, err := env.Retrieve(context.Background(), envSchemePrefix+envName, nil) + require.NoError(t, err) + retMap, err := ret.AsConf() + assert.NoError(t, err) + expectedMap := confmap.NewFromStringMap(map[string]any{}) + assert.Equal(t, expectedMap.ToStringMap(), retMap.ToStringMap()) + + assert.NoError(t, env.Shutdown(context.Background())) + + assert.Equal(t, 1, ol.Len()) + logLine := ol.All()[0] + assert.Equal(t, "Configuration references unset environment variable", logLine.Message) + assert.Equal(t, zap.WarnLevel, logLine.Level) + assert.Equal(t, envName, logLine.Context[0].String) +} + +func TestEmptyEnvWithLoggerWarn(t *testing.T) { + const envName = "default-config" + t.Setenv(envName, "") + + core, ol := observer.New(zap.InfoLevel) + logger := zap.New(core) + + env := NewWithSettings(confmap.ProviderSettings{Logger: logger}) + ret, err := env.Retrieve(context.Background(), envSchemePrefix+envName, nil) + require.NoError(t, err) + retMap, err := ret.AsConf() + assert.NoError(t, err) + expectedMap := confmap.NewFromStringMap(map[string]any{}) + assert.Equal(t, expectedMap.ToStringMap(), retMap.ToStringMap()) + + assert.NoError(t, env.Shutdown(context.Background())) + + assert.Equal(t, 1, ol.Len()) + logLine := ol.All()[0] + assert.Equal(t, "Configuration references empty environment variable", logLine.Message) + assert.Equal(t, zap.InfoLevel, logLine.Level) + assert.Equal(t, envName, logLine.Context[0].String) +} + +func createProvider() confmap.Provider { + return NewFactory().Create(confmaptest.NewNopProviderSettings()) +} diff --git a/confmap/provider/fileprovider/go.mod b/confmap/provider/fileprovider/go.mod index bc546c4634b..08d0c0393b2 100644 --- a/confmap/provider/fileprovider/go.mod +++ b/confmap/provider/fileprovider/go.mod @@ -3,8 +3,8 @@ 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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/confmap v0.100.0 go.uber.org/goleak v1.3.0 ) @@ -13,11 +13,12 @@ require ( 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/knadh/koanf/v2 v2.1.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 go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/confmap/provider/fileprovider/go.sum b/confmap/provider/fileprovider/go.sum index 69f4a4f6724..e70f902d5f5 100644 --- a/confmap/provider/fileprovider/go.sum +++ b/confmap/provider/fileprovider/go.sum @@ -6,8 +6,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -18,12 +18,14 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx 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= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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= 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= diff --git a/confmap/provider/fileprovider/provider.go b/confmap/provider/fileprovider/provider.go index a4da3af387f..b1723ad16c6 100644 --- a/confmap/provider/fileprovider/provider.go +++ b/confmap/provider/fileprovider/provider.go @@ -18,7 +18,7 @@ const schemeName = "file" type provider struct{} -// New returns a new confmap.Provider that reads the configuration from a file. +// NewWithSettings 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: // @@ -33,11 +33,13 @@ 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) +// +// Deprecated: [v0.99.0] Use NewFactory instead. func NewWithSettings(confmap.ProviderSettings) confmap.Provider { return &provider{} } -// New returns a new confmap.Provider that reads the configuration from a file. +// NewFactory returns a factory for a confmap.Provider that reads the configuration from a file. // // This Provider supports "file" scheme, and can be called with a "uri" that follows: // @@ -52,9 +54,8 @@ func NewWithSettings(confmap.ProviderSettings) confmap.Provider { // `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 NewFactory() confmap.ProviderFactory { + return confmap.NewProviderFactory(NewWithSettings) } func (fmp *provider) Retrieve(_ context.Context, uri string, _ confmap.WatcherFunc) (*confmap.Retrieved, error) { diff --git a/confmap/provider/fileprovider/provider_test.go b/confmap/provider/fileprovider/provider_test.go index dfc70756d99..022bf8f1758 100644 --- a/confmap/provider/fileprovider/provider_test.go +++ b/confmap/provider/fileprovider/provider_test.go @@ -19,25 +19,25 @@ import ( const fileSchemePrefix = schemeName + ":" func TestValidateProviderScheme(t *testing.T) { - assert.NoError(t, confmaptest.ValidateProviderScheme(New())) + assert.NoError(t, confmaptest.ValidateProviderScheme(createProvider())) } func TestEmptyName(t *testing.T) { - fp := New() + fp := createProvider() _, err := fp.Retrieve(context.Background(), "", nil) require.Error(t, err) require.NoError(t, fp.Shutdown(context.Background())) } func TestUnsupportedScheme(t *testing.T) { - fp := New() + fp := createProvider() _, err := fp.Retrieve(context.Background(), "https://", nil) assert.Error(t, err) assert.NoError(t, fp.Shutdown(context.Background())) } func TestNonExistent(t *testing.T) { - fp := New() + fp := createProvider() _, err := fp.Retrieve(context.Background(), fileSchemePrefix+filepath.Join("testdata", "non-existent.yaml"), nil) assert.Error(t, err) _, err = fp.Retrieve(context.Background(), fileSchemePrefix+absolutePath(t, filepath.Join("testdata", "non-existent.yaml")), nil) @@ -46,7 +46,7 @@ func TestNonExistent(t *testing.T) { } func TestInvalidYAML(t *testing.T) { - fp := New() + fp := createProvider() _, err := fp.Retrieve(context.Background(), fileSchemePrefix+filepath.Join("testdata", "invalid-yaml.yaml"), nil) assert.Error(t, err) _, err = fp.Retrieve(context.Background(), fileSchemePrefix+absolutePath(t, filepath.Join("testdata", "invalid-yaml.yaml")), nil) @@ -55,7 +55,7 @@ func TestInvalidYAML(t *testing.T) { } func TestRelativePath(t *testing.T) { - fp := New() + fp := createProvider() ret, err := fp.Retrieve(context.Background(), fileSchemePrefix+filepath.Join("testdata", "default-config.yaml"), nil) require.NoError(t, err) retMap, err := ret.AsConf() @@ -69,7 +69,7 @@ func TestRelativePath(t *testing.T) { } func TestAbsolutePath(t *testing.T) { - fp := New() + fp := createProvider() ret, err := fp.Retrieve(context.Background(), fileSchemePrefix+absolutePath(t, filepath.Join("testdata", "default-config.yaml")), nil) require.NoError(t, err) retMap, err := ret.AsConf() @@ -87,3 +87,7 @@ func absolutePath(t *testing.T, relativePath string) string { require.NoError(t, err) return filepath.Join(dir, relativePath) } + +func createProvider() confmap.Provider { + return NewFactory().Create(confmaptest.NewNopProviderSettings()) +} diff --git a/confmap/provider/httpprovider/go.mod b/confmap/provider/httpprovider/go.mod index 130befa5dea..e1e476ae46c 100644 --- a/confmap/provider/httpprovider/go.mod +++ b/confmap/provider/httpprovider/go.mod @@ -3,8 +3,8 @@ 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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/confmap v0.100.0 go.uber.org/goleak v1.3.0 ) @@ -13,11 +13,12 @@ require ( 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/knadh/koanf/v2 v2.1.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 go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/confmap/provider/httpprovider/go.sum b/confmap/provider/httpprovider/go.sum index 69f4a4f6724..e70f902d5f5 100644 --- a/confmap/provider/httpprovider/go.sum +++ b/confmap/provider/httpprovider/go.sum @@ -6,8 +6,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -18,12 +18,14 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx 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= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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= 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= diff --git a/confmap/provider/httpprovider/provider.go b/confmap/provider/httpprovider/provider.go index 966faa510fb..6ed2b6d104c 100644 --- a/confmap/provider/httpprovider/provider.go +++ b/confmap/provider/httpprovider/provider.go @@ -13,16 +13,17 @@ import ( // This Provider supports "http" scheme. // // One example for HTTP URI is: http://localhost:3333/getConfig +// +// Deprecated: [v0.99.0] Use NewFactory instead. 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. +// NewFactory returns a factory for a 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 NewWithSettings(confmap.ProviderSettings{}) +func NewFactory() confmap.ProviderFactory { + return confmap.NewProviderFactory(NewWithSettings) } diff --git a/confmap/provider/httpprovider/provider_test.go b/confmap/provider/httpprovider/provider_test.go index b649b5d3d08..2a49c65ecaa 100644 --- a/confmap/provider/httpprovider/provider_test.go +++ b/confmap/provider/httpprovider/provider_test.go @@ -9,10 +9,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/confmap/confmaptest" ) func TestSupportedScheme(t *testing.T) { - fp := New() + fp := NewFactory().Create(confmaptest.NewNopProviderSettings()) assert.Equal(t, "http", fp.Scheme()) require.NoError(t, fp.Shutdown(context.Background())) } diff --git a/confmap/provider/httpsprovider/go.mod b/confmap/provider/httpsprovider/go.mod index 5bb4b5ae1d4..7275e193e52 100644 --- a/confmap/provider/httpsprovider/go.mod +++ b/confmap/provider/httpsprovider/go.mod @@ -3,8 +3,8 @@ 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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/confmap v0.100.0 go.uber.org/goleak v1.3.0 ) @@ -13,11 +13,12 @@ require ( 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/knadh/koanf/v2 v2.1.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 go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/confmap/provider/httpsprovider/go.sum b/confmap/provider/httpsprovider/go.sum index 69f4a4f6724..e70f902d5f5 100644 --- a/confmap/provider/httpsprovider/go.sum +++ b/confmap/provider/httpsprovider/go.sum @@ -6,8 +6,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -18,12 +18,14 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx 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= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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= 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= diff --git a/confmap/provider/httpsprovider/provider.go b/confmap/provider/httpsprovider/provider.go index 6db2cc9b151..0ee3672cf86 100644 --- a/confmap/provider/httpsprovider/provider.go +++ b/confmap/provider/httpsprovider/provider.go @@ -8,23 +8,24 @@ import ( "go.opentelemetry.io/collector/confmap/provider/internal/configurablehttpprovider" ) -// New returns a new confmap.Provider that reads the configuration from a https server. +// NewWithSettings 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.99.0] Use NewFactory instead. 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. +// NewFactory returns a factory for a 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 NewWithSettings(confmap.ProviderSettings{}) +func NewFactory() confmap.ProviderFactory { + return confmap.NewProviderFactory(NewWithSettings) } diff --git a/confmap/provider/httpsprovider/provider_test.go b/confmap/provider/httpsprovider/provider_test.go index f488fcc6abd..e1d895f510c 100644 --- a/confmap/provider/httpsprovider/provider_test.go +++ b/confmap/provider/httpsprovider/provider_test.go @@ -7,9 +7,11 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/confmap/confmaptest" ) func TestSupportedScheme(t *testing.T) { - fp := New() + fp := NewFactory().Create(confmaptest.NewNopProviderSettings()) assert.Equal(t, "https", fp.Scheme()) } diff --git a/confmap/provider/internal/configurablehttpprovider/provider_test.go b/confmap/provider/internal/configurablehttpprovider/provider_test.go index ad4659879c4..125c1cbdd80 100644 --- a/confmap/provider/internal/configurablehttpprovider/provider_test.go +++ b/confmap/provider/internal/configurablehttpprovider/provider_test.go @@ -123,7 +123,7 @@ func generateCertificate(hostname string) (cert string, key string, err error) { } func TestFunctionalityDownloadFileHTTP(t *testing.T) { - fp := newConfigurableHTTPProvider(HTTPScheme, confmap.ProviderSettings{}) + fp := newConfigurableHTTPProvider(HTTPScheme, confmaptest.NewNopProviderSettings()) ts := httptest.NewServer(http.HandlerFunc(answerGet)) defer ts.Close() _, err := fp.Retrieve(context.Background(), ts.URL, nil) @@ -211,7 +211,7 @@ func TestFunctionalityDownloadFileHTTPS(t *testing.T) { for _, tt := range tests { t.Run(tt.testName, func(t *testing.T) { - fp := newConfigurableHTTPProvider(HTTPSScheme, confmap.ProviderSettings{}) + fp := newConfigurableHTTPProvider(HTTPSScheme, confmaptest.NewNopProviderSettings()) // Parse url of the test server to get the port number. tsURL, err := url.Parse(ts.URL) require.NoError(t, err) @@ -230,19 +230,19 @@ func TestFunctionalityDownloadFileHTTPS(t *testing.T) { } func TestUnsupportedScheme(t *testing.T) { - fp := New(HTTPScheme, confmap.ProviderSettings{}) + fp := New(HTTPScheme, confmaptest.NewNopProviderSettings()) _, err := fp.Retrieve(context.Background(), "https://...", nil) assert.Error(t, err) assert.NoError(t, fp.Shutdown(context.Background())) - fp = New(HTTPSScheme, confmap.ProviderSettings{}) + fp = New(HTTPSScheme, confmaptest.NewNopProviderSettings()) _, 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, confmap.ProviderSettings{}) + fp := New(HTTPScheme, confmaptest.NewNopProviderSettings()) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) })) @@ -253,7 +253,7 @@ func TestEmptyURI(t *testing.T) { } func TestRetrieveFromShutdownServer(t *testing.T) { - fp := New(HTTPScheme, confmap.ProviderSettings{}) + fp := New(HTTPScheme, confmaptest.NewNopProviderSettings()) ts := httptest.NewServer(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})) ts.Close() _, err := fp.Retrieve(context.Background(), ts.URL, nil) @@ -262,7 +262,7 @@ func TestRetrieveFromShutdownServer(t *testing.T) { } func TestNonExistent(t *testing.T) { - fp := New(HTTPScheme, confmap.ProviderSettings{}) + fp := New(HTTPScheme, confmaptest.NewNopProviderSettings()) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) })) @@ -273,7 +273,7 @@ func TestNonExistent(t *testing.T) { } func TestInvalidYAML(t *testing.T) { - fp := New(HTTPScheme, confmap.ProviderSettings{}) + fp := New(HTTPScheme, confmaptest.NewNopProviderSettings()) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) _, err := w.Write([]byte("wrong : [")) @@ -288,17 +288,17 @@ func TestInvalidYAML(t *testing.T) { } func TestScheme(t *testing.T) { - fp := New(HTTPScheme, confmap.ProviderSettings{}) + fp := New(HTTPScheme, confmaptest.NewNopProviderSettings()) 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, confmap.ProviderSettings{}))) + assert.NoError(t, confmaptest.ValidateProviderScheme(New(HTTPScheme, confmaptest.NewNopProviderSettings()))) } func TestInvalidTransport(t *testing.T) { - fp := New("foo", confmap.ProviderSettings{}) + fp := New("foo", confmaptest.NewNopProviderSettings()) _, err := fp.Retrieve(context.Background(), "foo://..", nil) assert.Error(t, err) diff --git a/confmap/provider/yamlprovider/go.mod b/confmap/provider/yamlprovider/go.mod index 482eaa6531c..a44885cae0d 100644 --- a/confmap/provider/yamlprovider/go.mod +++ b/confmap/provider/yamlprovider/go.mod @@ -3,8 +3,8 @@ 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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/confmap v0.100.0 go.uber.org/goleak v1.3.0 ) @@ -13,11 +13,12 @@ require ( 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/knadh/koanf/v2 v2.1.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 go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/confmap/provider/yamlprovider/go.sum b/confmap/provider/yamlprovider/go.sum index 69f4a4f6724..e70f902d5f5 100644 --- a/confmap/provider/yamlprovider/go.sum +++ b/confmap/provider/yamlprovider/go.sum @@ -6,8 +6,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -18,12 +18,14 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx 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= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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= 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= diff --git a/confmap/provider/yamlprovider/provider.go b/confmap/provider/yamlprovider/provider.go index 45fca8a1fc4..4f5c327ce4b 100644 --- a/confmap/provider/yamlprovider/provider.go +++ b/confmap/provider/yamlprovider/provider.go @@ -25,11 +25,13 @@ type provider struct{} // Examples: // `yaml:processors::batch::timeout: 2s` // `yaml:processors::batch/foo::timeout: 3s` +// +// Deprecated: [v0.99.0] Use NewFactory instead. func NewWithSettings(confmap.ProviderSettings) confmap.Provider { return &provider{} } -// New returns a new confmap.Provider that allows to provide yaml bytes. +// NewFactory returns a factory for a confmap.Provider that allows to provide yaml bytes. // // This Provider supports "yaml" scheme, and can be called with a "uri" that follows: // @@ -38,9 +40,8 @@ func NewWithSettings(confmap.ProviderSettings) confmap.Provider { // Examples: // `yaml:processors::batch::timeout: 2s` // `yaml:processors::batch/foo::timeout: 3s` -// Deprecated: [v0.94.0] Use NewWithSettings instead. -func New() confmap.Provider { - return NewWithSettings(confmap.ProviderSettings{}) +func NewFactory() confmap.ProviderFactory { + return confmap.NewProviderFactory(NewWithSettings) } func (s *provider) Retrieve(_ context.Context, uri string, _ confmap.WatcherFunc) (*confmap.Retrieved, error) { diff --git a/confmap/provider/yamlprovider/provider_test.go b/confmap/provider/yamlprovider/provider_test.go index 6e366c1c273..4abee7e8580 100644 --- a/confmap/provider/yamlprovider/provider_test.go +++ b/confmap/provider/yamlprovider/provider_test.go @@ -9,29 +9,30 @@ import ( "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/confmap" "go.opentelemetry.io/collector/confmap/confmaptest" ) func TestValidateProviderScheme(t *testing.T) { - assert.NoError(t, confmaptest.ValidateProviderScheme(New())) + assert.NoError(t, confmaptest.ValidateProviderScheme(createProvider())) } func TestEmpty(t *testing.T) { - sp := New() + sp := createProvider() _, err := sp.Retrieve(context.Background(), "", nil) assert.Error(t, err) assert.NoError(t, sp.Shutdown(context.Background())) } func TestInvalidYAML(t *testing.T) { - sp := New() + sp := createProvider() _, err := sp.Retrieve(context.Background(), "yaml:[invalid,", nil) assert.Error(t, err) assert.NoError(t, sp.Shutdown(context.Background())) } func TestOneValue(t *testing.T) { - sp := New() + sp := createProvider() ret, err := sp.Retrieve(context.Background(), "yaml:processors::batch::timeout: 2s", nil) assert.NoError(t, err) retMap, err := ret.AsConf() @@ -47,7 +48,7 @@ func TestOneValue(t *testing.T) { } func TestNamedComponent(t *testing.T) { - sp := New() + sp := createProvider() ret, err := sp.Retrieve(context.Background(), "yaml:processors::batch/foo::timeout: 3s", nil) assert.NoError(t, err) retMap, err := ret.AsConf() @@ -63,7 +64,7 @@ func TestNamedComponent(t *testing.T) { } func TestMapEntry(t *testing.T) { - sp := New() + sp := createProvider() ret, err := sp.Retrieve(context.Background(), "yaml:processors: {batch/foo::timeout: 3s, batch::timeout: 2s}", nil) assert.NoError(t, err) retMap, err := ret.AsConf() @@ -82,7 +83,7 @@ func TestMapEntry(t *testing.T) { } func TestArrayEntry(t *testing.T) { - sp := New() + sp := createProvider() ret, err := sp.Retrieve(context.Background(), "yaml:service::extensions: [zpages, zpages/foo]", nil) assert.NoError(t, err) retMap, err := ret.AsConf() @@ -99,7 +100,7 @@ func TestArrayEntry(t *testing.T) { } func TestNewLine(t *testing.T) { - sp := New() + sp := createProvider() ret, err := sp.Retrieve(context.Background(), "yaml:processors::batch/foo::timeout: 3s\nprocessors::batch::timeout: 2s", nil) assert.NoError(t, err) retMap, err := ret.AsConf() @@ -118,7 +119,7 @@ func TestNewLine(t *testing.T) { } func TestDotSeparator(t *testing.T) { - sp := New() + sp := createProvider() ret, err := sp.Retrieve(context.Background(), "yaml:processors.batch.timeout: 4s", nil) assert.NoError(t, err) retMap, err := ret.AsConf() @@ -126,3 +127,7 @@ func TestDotSeparator(t *testing.T) { assert.Equal(t, map[string]any{"processors.batch.timeout": "4s"}, retMap.ToStringMap()) assert.NoError(t, sp.Shutdown(context.Background())) } + +func createProvider() confmap.Provider { + return NewFactory().Create(confmaptest.NewNopProviderSettings()) +} diff --git a/confmap/resolver.go b/confmap/resolver.go index f056d18d1ec..05f7f964d03 100644 --- a/confmap/resolver.go +++ b/confmap/resolver.go @@ -11,6 +11,7 @@ import ( "strings" "go.uber.org/multierr" + "go.uber.org/zap" ) // follows drive-letter specification: @@ -33,12 +34,32 @@ type ResolverSettings struct { // It is required to have at least one location. URIs []string + // ProviderFactories is a list of Provider creation functions. + // It is required to have at least one ProviderFactory + // if a Provider is not given. + ProviderFactories []ProviderFactory + // Providers is a map of pairs . // It is required to have at least one Provider. + // + // Deprecated: [v0.99.0] Use ProviderFactories instead Providers map[string]Provider - // MapConverters is a slice of Converter. + // ProviderSettings contains settings that will be passed to Provider + // factories when instantiating Providers. + ProviderSettings ProviderSettings + + // ConverterFactories is a slice of Converter creation functions. + ConverterFactories []ConverterFactory + + // Converters is a slice of Converters. + // + // Deprecated: [v0.99.0] Use ConverterFactories instead Converters []Converter + + // ConverterSettings contains settings that will be passed to Converter + // factories when instantiating Converters. + ConverterSettings ConverterSettings } // NewResolver returns a new Resolver that resolves configuration from multiple URIs. @@ -65,10 +86,42 @@ func NewResolver(set ResolverSettings) (*Resolver, error) { return nil, errors.New("invalid map resolver config: no URIs") } - if len(set.Providers) == 0 { + if len(set.ProviderFactories) == 0 && len(set.Providers) == 0 { return nil, errors.New("invalid map resolver config: no Providers") } + if set.ProviderSettings.Logger == nil { + set.ProviderSettings.Logger = zap.NewNop() + } + + var providers map[string]Provider + var converters []Converter + + if len(set.Providers) != 0 { + if len(set.ProviderFactories) != 0 { + return nil, errors.New("only one of ResolverSettings.Providers and ResolverSettings.ProviderFactories can be used") + } + providers = set.Providers + } else { + providers = make(map[string]Provider, len(set.ProviderFactories)) + for _, factory := range set.ProviderFactories { + provider := factory.Create(set.ProviderSettings) + providers[provider.Scheme()] = provider + } + } + + if len(set.Converters) != 0 { + if len(set.ConverterFactories) != 0 { + return nil, errors.New("only one of ResolverSettings.Converters and ResolverSettings.ConverterFactories can be used") + } + converters = set.Converters + } else { + converters = make([]Converter, len(set.ConverterFactories)) + for i, factory := range set.ConverterFactories { + converters[i] = factory.Create(set.ConverterSettings) + } + } + // Safe copy, ensures the slices and maps cannot be changed from the caller. uris := make([]location, len(set.URIs)) for i, uri := range set.URIs { @@ -83,28 +136,21 @@ func NewResolver(set ResolverSettings) (*Resolver, error) { if err != nil { return nil, err } - if _, ok := set.Providers[lURI.scheme]; !ok { + if _, ok := providers[lURI.scheme]; !ok { return nil, fmt.Errorf("unsupported scheme on URI %q", uri) } uris[i] = lURI } - providersCopy := make(map[string]Provider, len(set.Providers)) - for k, v := range set.Providers { - providersCopy[k] = v - } - convertersCopy := make([]Converter, len(set.Converters)) - copy(convertersCopy, set.Converters) return &Resolver{ uris: uris, - providers: providersCopy, - converters: convertersCopy, + providers: providers, + converters: converters, watcher: make(chan error, 1), }, nil } // Resolve returns the configuration as a Conf, or error otherwise. -// // Should never be called concurrently with itself, Watch or Shutdown. func (mr *Resolver) Resolve(ctx context.Context) (*Conf, error) { // First check if already an active watching, close that if any. diff --git a/confmap/resolver_test.go b/confmap/resolver_test.go index aa1442d161a..122009d0e0e 100644 --- a/confmap/resolver_test.go +++ b/confmap/resolver_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.uber.org/zap" ) type mockProvider struct { @@ -47,22 +48,49 @@ func (m *mockProvider) Shutdown(context.Context) error { return m.errS } +func newMockProvider(m *mockProvider) ProviderFactory { + return NewProviderFactory(func(_ ProviderSettings) Provider { + return m + }) +} + type fakeProvider struct { scheme string ret func(ctx context.Context, uri string, watcher WatcherFunc) (*Retrieved, error) + logger *zap.Logger } -func newFileProvider(t testing.TB) Provider { +func newFileProvider(t testing.TB) ProviderFactory { return newFakeProvider("file", func(_ context.Context, uri string, _ WatcherFunc) (*Retrieved, error) { return NewRetrieved(newConfFromFile(t, uri[5:])) }) } -func newFakeProvider(scheme string, ret func(ctx context.Context, uri string, watcher WatcherFunc) (*Retrieved, error)) Provider { - return &fakeProvider{ +func newFakeProvider(scheme string, ret func(ctx context.Context, uri string, watcher WatcherFunc) (*Retrieved, error)) ProviderFactory { + return NewProviderFactory(func(ps ProviderSettings) Provider { + return &fakeProvider{ + scheme: scheme, + ret: ret, + logger: ps.Logger, + } + }) +} + +func newObservableFileProvider(t testing.TB) (ProviderFactory, *fakeProvider) { + return newObservableProvider("file", func(_ context.Context, uri string, _ WatcherFunc) (*Retrieved, error) { + return NewRetrieved(newConfFromFile(t, uri[5:])) + }) +} + +func newObservableProvider(scheme string, ret func(ctx context.Context, uri string, watcher WatcherFunc) (*Retrieved, error)) (ProviderFactory, *fakeProvider) { + fp := &fakeProvider{ scheme: scheme, ret: ret, } + return NewProviderFactory(func(ps ProviderSettings) Provider { + fp.logger = ps.Logger + return fp + }), fp } func (f *fakeProvider) Retrieve(ctx context.Context, uri string, watcher WatcherFunc) (*Retrieved, error) { @@ -85,16 +113,8 @@ func (m *mockConverter) Convert(context.Context, *Conf) error { return errors.New("converter_err") } -func makeMapProvidersMap(providers ...Provider) map[string]Provider { - ret := make(map[string]Provider, len(providers)) - for _, provider := range providers { - ret[provider.Scheme()] = provider - } - return ret -} - func TestNewResolverInvalidScheme(t *testing.T) { - _, err := NewResolver(ResolverSettings{URIs: []string{"s_3:has invalid char"}, Providers: makeMapProvidersMap(&mockProvider{scheme: "s_3"})}) + _, err := NewResolver(ResolverSettings{URIs: []string{"s_3:has invalid char"}, ProviderFactories: []ProviderFactory{newMockProvider(&mockProvider{scheme: "s_3"})}}) assert.EqualError(t, err, `invalid uri: "s_3:has invalid char"`) } @@ -171,7 +191,17 @@ func TestResolverErrors(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - resolver, err := NewResolver(ResolverSettings{URIs: tt.locations, Providers: makeMapProvidersMap(tt.providers...), Converters: tt.converters}) + mockProviderFuncs := make([]ProviderFactory, len(tt.providers)) + for i, provider := range tt.providers { + p := provider + mockProviderFuncs[i] = NewProviderFactory(func(_ ProviderSettings) Provider { return p }) + } + converterFuncs := make([]ConverterFactory, len(tt.converters)) + for i, converter := range tt.converters { + c := converter + converterFuncs[i] = NewConverterFactory(func(_ ConverterSettings) Converter { return c }) + } + resolver, err := NewResolver(ResolverSettings{URIs: tt.locations, ProviderFactories: mockProviderFuncs, ConverterFactories: converterFuncs}) if tt.expectBuildErr { assert.Error(t, err) return @@ -251,10 +281,12 @@ func TestBackwardsCompatibilityForFilePath(t *testing.T) { t.Run(tt.name, func(t *testing.T) { resolver, err := NewResolver(ResolverSettings{ URIs: []string{tt.location}, - Providers: makeMapProvidersMap(newFakeProvider("file", func(_ context.Context, uri string, _ WatcherFunc) (*Retrieved, error) { - return nil, errors.New(uri) - })), - Converters: nil}) + ProviderFactories: []ProviderFactory{ + newFakeProvider("file", func(_ context.Context, uri string, _ WatcherFunc) (*Retrieved, error) { + return nil, errors.New(uri) + }), + }, + ConverterFactories: nil}) if tt.expectBuildErr { assert.Error(t, err) return @@ -270,11 +302,13 @@ func TestResolver(t *testing.T) { numCalls := atomic.Int32{} resolver, err := NewResolver(ResolverSettings{ URIs: []string{"mock:"}, - Providers: makeMapProvidersMap(&mockProvider{retM: map[string]any{}, closeFunc: func(context.Context) error { - numCalls.Add(1) - return nil - }}), - Converters: nil}) + ProviderFactories: []ProviderFactory{ + newMockProvider(&mockProvider{retM: map[string]any{}, closeFunc: func(context.Context) error { + numCalls.Add(1) + return nil + }}), + }, + ConverterFactories: nil}) require.NoError(t, err) _, errN := resolver.Resolve(context.Background()) assert.NoError(t, errN) @@ -303,33 +337,33 @@ func TestResolver(t *testing.T) { func TestResolverNewLinesInOpaqueValue(t *testing.T) { _, err := NewResolver(ResolverSettings{ - URIs: []string{"mock:receivers:\n nop:\n"}, - Providers: makeMapProvidersMap(&mockProvider{retM: map[string]any{}}), - Converters: nil}) + URIs: []string{"mock:receivers:\n nop:\n"}, + ProviderFactories: []ProviderFactory{newMockProvider(&mockProvider{retM: map[string]any{}})}, + ConverterFactories: nil}) assert.NoError(t, err) } func TestResolverNoLocations(t *testing.T) { _, err := NewResolver(ResolverSettings{ - URIs: []string{}, - Providers: makeMapProvidersMap(&mockProvider{}), - Converters: nil}) + URIs: []string{}, + ProviderFactories: []ProviderFactory{newMockProvider(&mockProvider{})}, + ConverterFactories: nil}) assert.Error(t, err) } func TestResolverNoProviders(t *testing.T) { _, err := NewResolver(ResolverSettings{ - URIs: []string{filepath.Join("testdata", "config.yaml")}, - Providers: nil, - Converters: nil}) + URIs: []string{filepath.Join("testdata", "config.yaml")}, + ProviderFactories: nil, + ConverterFactories: nil}) assert.Error(t, err) } func TestResolverShutdownClosesWatch(t *testing.T) { resolver, err := NewResolver(ResolverSettings{ - URIs: []string{filepath.Join("testdata", "config.yaml")}, - Providers: makeMapProvidersMap(newFileProvider(t)), - Converters: nil}) + URIs: []string{filepath.Join("testdata", "config.yaml")}, + ProviderFactories: []ProviderFactory{newFileProvider(t)}, + ConverterFactories: nil}) require.NoError(t, err) _, errN := resolver.Resolve(context.Background()) assert.NoError(t, errN) @@ -347,3 +381,51 @@ func TestResolverShutdownClosesWatch(t *testing.T) { assert.NoError(t, resolver.Shutdown(context.Background())) watcherWG.Wait() } + +func TestCantConfigureTwoProviderSettings(t *testing.T) { + _, err := NewResolver(ResolverSettings{ + URIs: []string{filepath.Join("testdata", "config.yaml")}, + ProviderFactories: []ProviderFactory{newFileProvider(t)}, + Providers: map[string]Provider{"mock": &mockProvider{}}, + ConverterFactories: nil, + }) + require.Error(t, err) +} + +func TestCantConfigureTwoConverterSettings(t *testing.T) { + _, err := NewResolver(ResolverSettings{ + URIs: []string{filepath.Join("testdata", "config.yaml")}, + ProviderFactories: []ProviderFactory{newFileProvider(t)}, + ConverterFactories: []ConverterFactory{NewConverterFactory(func(_ ConverterSettings) Converter { return &mockConverter{} })}, + Converters: []Converter{&mockConverter{err: errors.New("converter_err")}}, + }) + require.Error(t, err) +} + +func TestTakesInstantiatedProviders(t *testing.T) { + _, err := NewResolver(ResolverSettings{ + URIs: []string{filepath.Join("testdata", "config.yaml")}, + Providers: map[string]Provider{"mock": &mockProvider{}}, + ConverterFactories: nil, + }) + require.NoError(t, err) +} + +func TestTakesInstantiatedConverters(t *testing.T) { + _, err := NewResolver(ResolverSettings{ + URIs: []string{filepath.Join("testdata", "config.yaml")}, + ProviderFactories: []ProviderFactory{newFileProvider(t)}, + Converters: []Converter{&mockConverter{err: errors.New("converter_err")}}, + }) + require.NoError(t, err) +} + +func TestProvidesDefaultLogger(t *testing.T) { + factory, provider := newObservableFileProvider(t) + _, err := NewResolver(ResolverSettings{ + URIs: []string{filepath.Join("testdata", "config.yaml")}, + ProviderFactories: []ProviderFactory{factory}, + }) + require.NoError(t, err) + require.NotNil(t, provider.logger) +} diff --git a/connector/connectortest/connector.go b/connector/connectortest/connector.go index d30fb65b6a5..0aad0b71142 100644 --- a/connector/connectortest/connector.go +++ b/connector/connectortest/connector.go @@ -6,6 +6,8 @@ package connectortest // import "go.opentelemetry.io/collector/connector/connect import ( "context" + "github.com/google/uuid" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/connector" @@ -18,7 +20,7 @@ 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), + ID: component.NewIDWithName(nopType, uuid.NewString()), TelemetrySettings: componenttest.NewNopTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo(), } diff --git a/connector/forwardconnector/generated_component_test.go b/connector/forwardconnector/generated_component_test.go new file mode 100644 index 00000000000..9bbe4e5aa5f --- /dev/null +++ b/connector/forwardconnector/generated_component_test.go @@ -0,0 +1,88 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package forwardconnector + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/connector" + "go.opentelemetry.io/collector/connector/connectortest" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumertest" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "forward", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +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) + }{ + + { + name: "logs_to_logs", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + router := connector.NewLogsRouter(map[component.ID]consumer.Logs{component.NewID(component.DataTypeLogs): consumertest.NewNop()}) + return factory.CreateLogsToLogs(ctx, set, cfg, router) + }, + }, + + { + name: "metrics_to_metrics", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + router := connector.NewMetricsRouter(map[component.ID]consumer.Metrics{component.NewID(component.DataTypeMetrics): consumertest.NewNop()}) + return factory.CreateMetricsToMetrics(ctx, set, cfg, router) + }, + }, + + { + name: "traces_to_traces", + createFn: func(ctx context.Context, set connector.CreateSettings, cfg component.Config) (component.Component, error) { + router := connector.NewTracesRouter(map[component.ID]consumer.Traces{component.NewID(component.DataTypeTraces): consumertest.NewNop()}) + return factory.CreateTracesToTraces(ctx, set, cfg, router) + }, + }, + } + + 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) { + firstConnector, err := test.createFn(context.Background(), connectortest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + host := componenttest.NewNopHost() + 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())) + }) + } +} diff --git a/connector/forwardconnector/package_test.go b/connector/forwardconnector/generated_package_test.go similarity index 62% rename from connector/forwardconnector/package_test.go rename to connector/forwardconnector/generated_package_test.go index 54cc0fd73ce..6ea5f1097be 100644 --- a/connector/forwardconnector/package_test.go +++ b/connector/forwardconnector/generated_package_test.go @@ -1,5 +1,4 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 +// Code generated by mdatagen. DO NOT EDIT. package forwardconnector diff --git a/connector/forwardconnector/go.mod b/connector/forwardconnector/go.mod index 656652fbfe1..0f27694a228 100644 --- a/connector/forwardconnector/go.mod +++ b/connector/forwardconnector/go.mod @@ -3,13 +3,14 @@ module go.opentelemetry.io/collector/connector/forwardconnector go 1.21 require ( - github.com/stretchr/testify v1.8.4 - 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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/connector v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.0 go.uber.org/goleak v1.3.0 ) @@ -21,35 +22,34 @@ require ( 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/google/uuid 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.1 // 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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.opentelemetry.io/collector v0.100.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.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/net v0.24.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -61,6 +61,8 @@ replace go.opentelemetry.io/collector/connector => ../ replace go.opentelemetry.io/collector/pdata => ../../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata + replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/consumer => ../../consumer diff --git a/connector/forwardconnector/go.sum b/connector/forwardconnector/go.sum index 06616cda85d..4394e616fe3 100644 --- a/connector/forwardconnector/go.sum +++ b/connector/forwardconnector/go.sum @@ -14,13 +14,11 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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/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= @@ -29,8 +27,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -48,32 +46,32 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.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.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -89,16 +87,16 @@ 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -111,14 +109,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/connector/forwardconnector/internal/metadata/generated_status.go b/connector/forwardconnector/internal/metadata/generated_status.go index 201502cd3e2..25007e42e02 100644 --- a/connector/forwardconnector/internal/metadata/generated_status.go +++ b/connector/forwardconnector/internal/metadata/generated_status.go @@ -3,15 +3,11 @@ 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" + Type = component.MustNewType("forward") ) const ( @@ -19,11 +15,3 @@ const ( 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/internal/metadata/generated_telemetry.go b/connector/forwardconnector/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..bf218aec069 --- /dev/null +++ b/connector/forwardconnector/internal/metadata/generated_telemetry.go @@ -0,0 +1,18 @@ +// 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" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/connector/forwardconnector") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/connector/forwardconnector") +} diff --git a/connector/forwardconnector/internal/metadata/generated_telemetry_test.go b/connector/forwardconnector/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..658ab380f97 --- /dev/null +++ b/connector/forwardconnector/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/connector/forwardconnector", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/connector/forwardconnector", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/connector/go.mod b/connector/go.mod index 3e1b6496f98..fcf88fdc3e4 100644 --- a/connector/go.mod +++ b/connector/go.mod @@ -3,11 +3,13 @@ module go.opentelemetry.io/collector/connector 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/consumer v0.96.0 - go.opentelemetry.io/collector/pdata v1.3.0 + github.com/google/uuid v1.6.0 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/collector/pdata/testdata v0.100.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 @@ -21,34 +23,33 @@ require ( 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/knadh/koanf/v2 v2.1.1 // 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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 + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/confmap v0.100.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/metric v1.26.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.opentelemetry.io/otel/trace v1.26.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -65,3 +66,5 @@ replace go.opentelemetry.io/collector/consumer => ../consumer replace go.opentelemetry.io/collector/featuregate => ../featuregate replace go.opentelemetry.io/collector/pdata => ../pdata + +replace go.opentelemetry.io/collector/pdata/testdata => ../pdata/testdata diff --git a/connector/go.sum b/connector/go.sum index 06616cda85d..4394e616fe3 100644 --- a/connector/go.sum +++ b/connector/go.sum @@ -14,13 +14,11 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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/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= @@ -29,8 +27,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -48,32 +46,32 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.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.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -89,16 +87,16 @@ 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -111,14 +109,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/connector/logs_router.go b/connector/logs_router.go index e5594327ffc..0db9ea7799d 100644 --- a/connector/logs_router.go +++ b/connector/logs_router.go @@ -13,12 +13,6 @@ import ( "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 @@ -29,17 +23,17 @@ type LogsRouterAndConsumer interface { type logsRouter struct { consumer.Logs - consumers map[component.ID]consumer.Logs + baseRouter[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) + for _, cons := range cm { + consumers = append(consumers, cons) } return &logsRouter{ - Logs: fanoutconsumer.NewLogs(consumers), - consumers: cm, + Logs: fanoutconsumer.NewLogs(consumers), + baseRouter: newBaseRouter(fanoutconsumer.NewLogs, cm), } } diff --git a/connector/logs_router_test.go b/connector/logs_router_test.go index accce0a03cd..a4074762ac1 100644 --- a/connector/logs_router_test.go +++ b/connector/logs_router_test.go @@ -14,8 +14,8 @@ import ( "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" + "go.opentelemetry.io/collector/pdata/testdata" ) type mutatingLogsSink struct { diff --git a/connector/metrics_router.go b/connector/metrics_router.go index 8e2b8e900a1..3e688261bfe 100644 --- a/connector/metrics_router.go +++ b/connector/metrics_router.go @@ -4,21 +4,11 @@ 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 @@ -29,7 +19,7 @@ type MetricsRouterAndConsumer interface { type metricsRouter struct { consumer.Metrics - consumers map[component.ID]consumer.Metrics + baseRouter[consumer.Metrics] } func NewMetricsRouter(cm map[component.ID]consumer.Metrics) MetricsRouterAndConsumer { @@ -38,38 +28,9 @@ func NewMetricsRouter(cm map[component.ID]consumer.Metrics) MetricsRouterAndCons 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 + Metrics: fanoutconsumer.NewMetrics(consumers), + baseRouter: newBaseRouter(fanoutconsumer.NewMetrics, cm), } - return fanoutconsumer.NewMetrics(consumers), nil } func (r *metricsRouter) privateFunc() {} diff --git a/connector/metrics_router_test.go b/connector/metrics_router_test.go index 62dd54c11e0..c3fe824992a 100644 --- a/connector/metrics_router_test.go +++ b/connector/metrics_router_test.go @@ -14,8 +14,8 @@ import ( "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" + "go.opentelemetry.io/collector/pdata/testdata" ) type mutatingMetricsSink struct { diff --git a/connector/router.go b/connector/router.go new file mode 100644 index 00000000000..bba7ee76bba --- /dev/null +++ b/connector/router.go @@ -0,0 +1,55 @@ +// 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" +) + +type baseRouter[T any] struct { + fanout func([]T) T + consumers map[component.ID]T +} + +func newBaseRouter[T any](fanout func([]T) T, cm map[component.ID]T) baseRouter[T] { + consumers := make(map[component.ID]T, len(cm)) + for k, v := range cm { + consumers[k] = v + } + return baseRouter[T]{fanout: fanout, consumers: consumers} +} + +func (r *baseRouter[T]) PipelineIDs() []component.ID { + ids := make([]component.ID, 0, len(r.consumers)) + for id := range r.consumers { + ids = append(ids, id) + } + return ids +} + +func (r *baseRouter[T]) Consumer(pipelineIDs ...component.ID) (T, error) { + var ret T + if len(pipelineIDs) == 0 { + return ret, fmt.Errorf("missing consumers") + } + consumers := make([]T, 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 ret, errors + } + return r.fanout(consumers), nil +} diff --git a/connector/traces_router.go b/connector/traces_router.go index 97c31d7920c..84eb889c05a 100644 --- a/connector/traces_router.go +++ b/connector/traces_router.go @@ -4,21 +4,11 @@ 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 @@ -29,47 +19,18 @@ type TracesRouterAndConsumer interface { type tracesRouter struct { consumer.Traces - consumers map[component.ID]consumer.Traces + baseRouter[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) + for _, cons := range cm { + consumers = append(consumers, cons) } 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 + Traces: fanoutconsumer.NewTraces(consumers), + baseRouter: newBaseRouter(fanoutconsumer.NewTraces, cm), } - return fanoutconsumer.NewTraces(consumers), nil } func (r *tracesRouter) privateFunc() {} diff --git a/connector/traces_router_test.go b/connector/traces_router_test.go index 33a2124ed3e..8c93b10528a 100644 --- a/connector/traces_router_test.go +++ b/connector/traces_router_test.go @@ -14,8 +14,8 @@ import ( "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" + "go.opentelemetry.io/collector/pdata/testdata" ) type mutatingTracesSink struct { diff --git a/consumer/consumererror/signalerrors_test.go b/consumer/consumererror/signalerrors_test.go index 141db20202c..475d3173bb9 100644 --- a/consumer/consumererror/signalerrors_test.go +++ b/consumer/consumererror/signalerrors_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opentelemetry.io/collector/internal/testdata" + "go.opentelemetry.io/collector/pdata/testdata" ) func TestTraces(t *testing.T) { diff --git a/consumer/consumertest/sink_test.go b/consumer/consumertest/sink_test.go index 24c1f6fac8b..bd29ebc6aef 100644 --- a/consumer/consumertest/sink_test.go +++ b/consumer/consumertest/sink_test.go @@ -10,10 +10,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/collector/pdata/testdata" ) func TestTracesSink(t *testing.T) { diff --git a/consumer/go.mod b/consumer/go.mod index a0d4cd6f95f..f054b0b3a0d 100644 --- a/consumer/go.mod +++ b/consumer/go.mod @@ -3,44 +3,35 @@ module go.opentelemetry.io/collector/consumer go 1.21 require ( - github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector v0.96.0 - go.opentelemetry.io/collector/pdata v1.3.0 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/collector/pdata/testdata v0.100.0 go.uber.org/goleak v1.3.0 ) require ( github.com/davecgh/go-spew v1.1.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/kr/text v0.2.0 // 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.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/net v0.23.0 // indirect + golang.org/x/sys v0.18.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.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/featuregate => ../featuregate - replace go.opentelemetry.io/collector/pdata => ../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../pdata/testdata + 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/config/configtelemetry => ../config/configtelemetry diff --git a/consumer/go.sum b/consumer/go.sum index 834ba473908..458a9f2f0c1 100644 --- a/consumer/go.sum +++ b/consumer/go.sum @@ -4,10 +4,6 @@ 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/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= @@ -30,8 +26,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/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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -47,16 +43,16 @@ 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 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/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.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= @@ -69,14 +65,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/docs/design.md b/docs/design.md deleted file mode 100644 index 51ed65bbbe5..00000000000 --- a/docs/design.md +++ /dev/null @@ -1,205 +0,0 @@ -# OpenTelemetry Collector Architecture - -This document describes the architecture design and implementation of the -OpenTelemetry Collector. - -## Summary - -OpenTelemetry Collector is an executable that can receive telemetry data, optionally process it, and export it further. - -The Collector supports several popular open-source protocols for receiving and sending telemetry data as well as offering a pluggable architecture for adding more protocols. - -Data receiving, processing, and exporting is done using [Pipelines](#pipelines). The Collector can be configured to have one or more pipelines. Each pipeline includes: - -- a set of [Receivers](#receivers) that receive the data -- a series of optional [Processors](#processors) that get the data from receivers and process it -- a set of [Exporters](#exporters) which get the data from processors and send it further outside the Collector. - -The same receiver can be included in multiple pipelines and multiple pipelines can include the same Exporter. - -## Pipelines - -A pipeline defines a path the data follows in the Collector starting from reception, then further processing or modification and finally exiting the Collector via exporters. - -Pipelines can operate on 3 telemetry data types: traces, metrics, and logs. The data type is a property of the pipeline defined by its configuration. Receivers, processors, and exporters used in a pipeline must support the particular data type otherwise `ErrDataTypeIsNotSupported` will be reported when the configuration is loaded. A pipeline can be depicted the following way: - -![Pipelines](images/design-pipelines.png) - -There can be one or more receivers in a pipeline. Data from all receivers is pushed to the first processor, which performs a processing on it and then pushes it to the next processor (or it may drop the data, e.g. if it is a “sampling” processor) and so on until the last processor in the pipeline pushes the data to the exporters. Each exporter gets a copy of each data element. The last processor uses a `fanoutconsumer` to fan out the data to multiple exporters. - -The pipeline is constructed during Collector startup based on pipeline definition in the configuration. - -A pipeline configuration typically looks like this: - -```yaml -service: - pipelines: # section that can contain multiple subsections, one per pipeline - traces: # type of the pipeline - receivers: [otlp, jaeger, zipkin] - processors: [memory_limiter, batch] - exporters: [otlp, jaeger, zipkin] -``` - -The above example defines a pipeline for “traces” type of telemetry data, with 3 receivers, 2 processors and 3 exporters. - -For details of config file format see [this document](https://docs.google.com/document/d/1NeheFG7DmcUYo_h2vLtNRlia9x5wOJMlV4QKEK05FhQ/edit#). - -### Receivers - -Receivers typically listen on a network port and receive telemetry data. Usually one receiver is configured to send received data to one pipeline, however it is also possible to configure the same receiver to send the same received data to multiple pipelines. This can be done by simply listing the same receiver in the “receivers” key of several pipelines: - -```yaml -receivers: - otlp: - protocols: - grpc: - endpoint: localhost:4317 - -service: - pipelines: - traces: # a pipeline of “traces” type - receivers: [otlp] - processors: [memory_limiter, batch] - exporters: [jaeger] - traces/2: # another pipeline of “traces” type - receivers: [otlp] - processors: [batch] - exporters: [opencensus] -``` - -In the above example `otlp` receiver will send the same data to pipeline `traces` and to pipeline `traces/2`. (Note: the configuration uses composite key names in the form of `type[/name]` as defined in [this document](https://docs.google.com/document/d/1NeheFG7DmcUYo_h2vLtNRlia9x5wOJMlV4QKEK05FhQ/edit#)). - -When the Collector loads this config the result will look like this (part of processors and exporters are omitted from the diagram for brevity): - - -![Receivers](images/design-receivers.png) - -Important: when the same receiver is referenced in more than one pipeline the Collector will create only one receiver instance at runtime that will send the data to a fan out consumer, which in turn will send the data to the first processor of each pipeline. The data propagation from receiver to the fan out consumer and then to processors is done via a synchronous function call. This means that if one processor blocks the call the other pipelines that are attached to this receiver will be blocked from receiving the same data and the receiver itself will stop processing and forwarding newly received data. - -### Exporters - -Exporters typically forward the data they get to a destination on a network (but they can also send it elsewhere, e.g `logging` exporter writes the telemetry data to the logging destination). - -The configuration allows to have multiple exporters of the same type, even in the same pipeline. For example one can have 2 `otlp` exporters defined each one sending to a different OTLP endpoint, e.g.: - -```yaml -exporters: - otlp/1: - endpoint: example.com:4317 - otlp/2: - endpoint: localhost:14317 -``` - -Usually an exporter gets the data from one pipeline, however it is possible to configure multiple pipelines to send data to the same exporter, e.g.: - -```yaml -exporters: - jaeger: - protocols: - grpc: - endpoint: localhost:14250 - -service: - pipelines: - traces: # a pipeline of “traces” type - receivers: [zipkin] - processors: [memory_limiter] - exporters: [jaeger] - traces/2: # another pipeline of “traces” type - receivers: [otlp] - processors: [batch] - exporters: [jaeger] -``` - -In the above example `jaeger` exporter will get data from pipeline `traces` and from pipeline `traces/2`. When the Collector loads this config the result will look like this (part of processors and receivers are omitted from the diagram for brevity): - - -![Exporters](images/design-exporters.png) - -### Processors - -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. - -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: - -```yaml -processors: - batch: - send_batch_size: 10000 - timeout: 10s - -service: - pipelines: - traces: # a pipeline of “traces” type - receivers: [zipkin] - processors: [batch] - exporters: [jaeger] - traces/2: # another pipeline of “traces” type - receivers: [otlp] - processors: [batch] - exporters: [otlp] -``` - -When the Collector loads this config the result will look like this: - - -![Processors](images/design-processors.png) - -Note that each `batch` processor is an independent instance, although both are configured the same way, i.e. each have a `send_batch_size` of 10000. - -The same name of the processor MUST NOT be referenced multiple times in the `processors` key of a single pipeline. - -## Running as an Agent - -On a typical VM/container, there are user applications running in some -processes/pods with OpenTelemetry Library (Library). Previously, Library did -all the recording, collecting, sampling and aggregation on traces/metrics/logs, -and exported them to other persistent storage backends via the Library -exporters, or displayed them on local zpages. This pattern has several -drawbacks, for example: - -1. For each OpenTelemetry Library, exporters/zpages need to be re-implemented - in native languages. -2. In some programming languages (e.g Ruby, PHP), it is difficult to do the - stats aggregation in process. -3. To enable exporting OpenTelemetry spans/stats/metrics, application users - need to manually add library exporters and redeploy their binaries. This is - especially difficult when there’s already an incident and users want to use - OpenTelemetry to investigate what’s going on right away. -4. Application users need to take the responsibility in configuring and - initializing exporters. This is error-prone (e.g they may not set up the - correct credentials\monitored resources), and users may be reluctant to - “pollute” their code with OpenTelemetry. - -To resolve the issues above, you can run OpenTelemetry Collector as an Agent. -The Agent runs as a daemon in the VM/container and can be deployed independent -of Library. Once Agent is deployed and running, it should be able to retrieve -traces/metrics/logs from Library, export them to other backends. We MAY also -give Agent the ability to push configurations (e.g sampling probability) to -Library. For those languages that cannot do stats aggregation in process, they -should also be able to send raw measurements and have Agent do the aggregation. - - -![agent-architecture](images/design-collector-agent.png) - -For developers/maintainers of other libraries: Agent can also -accept traces/metrics/logs from other tracing/monitoring libraries, such as -Zipkin, Prometheus, etc. This is done by adding specific receivers. See -[Receivers](#receivers) for details. - -## Running as a Gateway - -The OpenTelemetry Collector can run as a Gateway instance and receives spans -and metrics exported by one or more Agents or Libraries, or by -tasks/agents that emit in one of the supported protocols. The Collector is -configured to send data to the configured exporter(s). The following figure -summarizes the deployment architecture: - - -![OpenTelemetry Collector Architecture](images/design-collector-service.png "OpenTelemetry Collector Architecture") - -The OpenTelemetry Collector can also be deployed in other configurations, such -as receiving data from other agents or clients in one of the formats supported -by its receivers. diff --git a/docs/ga-roadmap.md b/docs/ga-roadmap.md index 2f204ac9f74..c3497140f75 100644 --- a/docs/ga-roadmap.md +++ b/docs/ga-roadmap.md @@ -1,167 +1,57 @@ -# Collector GA Roadmap +# Collector v1 Roadmap -This document defines the roadmap followed by the OpenTelemetry Collector, -along with tentative dates and requirements for GA (stability). - -In this document, the term “OpenTelemetry Collector packages" refers to all the golang -modules and packages that are part of the “OpenTelemetry Collector” ecosystem which -include the [core](https://github.com/open-telemetry/opentelemetry-collector) and -[contrib](https://github.com/open-telemetry/opentelemetry-collector-contrib). - -In this document, the terms "OpenTelemetry Collector" and "Collector" both specifically -refer to the entire OpenTelemetry Collector ecosystem’s including core and contrib. -These terms do not refer to the specification or the Client libraries in this document. - -## Current Status - -The OpenTelemetry Collector ecosystem right now has a lot of packages that are in different -stages of stability (experimental, alpha, beta, etc.). All these packages have different -public APIs/Interfaces (e.g. code API, configuration, etc.). - -A significant amount of legacy code was inherited from the Collector's ancestor -[OpenCensus Service](https://github.com/census-instrumentation/opencensus-service), since then -the Collector changed the internal data model and other significant changes were made. - -Trying to mark the entire ecosystem GA, at the same moment, will be a significant effort and -will take a significant amount of time. +This document contains the roadmap for the Collector. The main goal of this roadmap is to provide clarity on the areas of focus in order to release a v1 of the Collector. ## Proposal -This document proposes a GA Roadmap based on multiple phases, where different parts of the -collector will be released as stable at different moments of time. - -At this moment we are completely defining only the first two phases of the process, and the -next phases will be defined at a later stage once the Collector maintainers will have -better understanding of the process and implications. - -The primary focus is on the tracing parts. When other signal's data models (proto definition) -will be marked as stable, the amount of work necessary to stabilize their APIs will be minimal: -`pdata` is auto-generated so all changes that we do for trace will apply to all of them, -`consumer` is minimal interface, `component` as well. - -Metrics components such as (`receiver/prometheus`, `exporter/prometheusremotewrite`) are -explicitly left out of this roadmap document because metrics data model is not complete. -When that work finishes, we can add them to the Phase 3, or later. - -### Phase 1 - -**Key Results:** At the end of this phase the Collector’s core API will be marked as Stable. - -At the end of this phase we want to achieve core APIs stability. This will allow developers -to implement custom components and extend the collector will be marked as stable. -The complete list of the packages/modules will be finalized during the first action item of -this phase, but the tentative list is: - -* `consumer` - * Official internal data model `pdata`. - * Interfaces and utils to build a Consumer for (trace, metrics, logs). -* `config` - * Core `config` including service definition, component definition will be stabilized. - * To be determined which config helpers will be marked as stable (e.g. configgrpc, etc.). -* `component` - * Interfaces and utils to build a Collector component (receiver, processor, exporter, extension). -* `obsreport` - * Focus on the public API of this package. It is out of scope to ensure stability for the - metrics emitted (focus in phase 2). -* `service` - * Public API to construct a OpenTelemetry Collector Service. - -**Action Items:** - -* Create a new milestone for this phase, create issues for all the other action items and add -them to the milestone. -* Agreement on all packages/modules that will be marked as stable during this phase. -* Write a version doc as per [version and stability document](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md). - * Previously it was discussed that for the Collector it is fine to release stable golang modules - that contain APIs marked as experimental. - * Define status schema (experimental/stable), what are they applicable to every module. -* Investigate if splitting into smaller, more granular, modules is possible. - * Define the modules schema, try to not break everyone. - See [here](https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository). - * Investigate how can we release multiple golang modules from the same repo, without asking - people that consume them to use a replace statement. See problem in contrib. - * Investigate how to release test-only utils. -* Review all public APIs and godocs for modules that we want to release in this phase. - * Fix all critical issues, and remove unnecessary (“When in doubt leave it out”) public APIs. - * Remove all already deprecated code from the stable modules. -* Transition to opentelemetry-go trace library from opencensus? -* Investigate if any config helper needs to be released as stable, if any do the review of -the public API, godoc and configuration. -* Investigate tools that check for API compatibility for go modules, enable them for modules -that we mark as stable. - -### Phase 2 - -**Key Results:** At the end of this phase the Collector’s end-to-end support for OTLP traces -only be marked as GA. - -At the end of this phase we want to ensure that the Collector can be run in production, it can receive -OTLP trace traffic and emit OTLP trace traffic. The complete list of the packages/modules will be -finalized during the first part of this phase, but the tentative list is: - -* `receiver` - * `receiverhelper` - without scraper utils in this phase. - * `otlp` -* `processor` - * `processorhelper` - * `batch` - * `memory_limiter` -* `exporter` - * `exporterhelper` - * `otlp` - * `otlphttp` -* `extension` - * `extensionhelper` - * `healthcheck` -* `obsreport` - * Stabilize the observability metrics (user public metrics). - -**Action Items:** - -* Create a new milestone for this phase, create issues for all the other action items and add them -to the milestone. -* Agreement on all packages/modules that will be marked as stable during this phase. -* Review all public APIs and godocs for modules that we want to release in this phase. - * Fix all critical issues, and remove unnecessary (“When in doubt leave it out”) public APIs. - * Remove all already deprecated code from the stable modules. -* Review all public configuration for all the modules, fix issues. -* Setup a proper loadtest environment and continuously publish results. -* Ensure correctness tests produce the expected results, improve until confident that a binary -that passes them is good to be shipped. -* Enable security checks on every PR (currently some are ignored like `codeql`). - -### Phase 3 - -**Key Results:** At the end of this phase all Collector’s core components (receivers, -processors, exporters, extensions) for traces only will be marked as GA. - -At the end of this phase we want to ensure that the Collector can be run in production, it can receive the -trace traffic and emit OTLP trace traffic. The complete list of the packages/modules will be finalized -during the first part of this phase, but the tentative list is: - -* `receiver` - * `jaeger` - * `opencensus` - * `zipkin` -* `processor` - * `spantransformer` - there are good reasons to merge `attributes` and `span`. - * `resource` - * `filter` - we will consider offering a filter processor for all telemetry signals not just for metrics -* `exporter` - * `jaeger` - * `opencensus` - * `zipkin` -* `extension` - * `pprof` - * `zpages` - -TODO: Add action items list. - -### Phase N - -TODO: Add more phases if/when necessary. - -## Alternatives - -One alternative proposal is to try to GA all packages at the same time. This proposal was rejected -because of the complexity and size of the ecosystem that may force the GA process to take too much time. +The proposed approach to delivering a stable release of the OpenTelemetry Collector is to produce a distribution of the Collector that contains a minimum set of components which have been stabilized. By doing so, the project contributors will ensure dependencies of those components have also been released under a stable version. + +The proposed distribution is set to include the following components only: + +- OTLP receiver +- OTLP exporter +- OTLP HTTP exporter + +These modules depend on a list of other modules, the full list is available in issue [#9375](https://github.com/open-telemetry/opentelemetry-collector/issues/9375). + +All stabilized modules will conform to the API expectations outlined in the [VERSIONING.md](../VERSIONING.md) document. + +## Out of scope + +Explicitly, the following are not in the scope of v1 for the purposes of this document: + +* stabilization of additional components/APIs needed by distribution maintainers. Vendors are not the audience +* Collector Builder +* telemetrygen +* mdatagen +* Operator + +Those components are free to pursue v1 at their own pace and may be the focus of future stability work. + +## Additional Requirements + +The following is a list of requirements for this minimal Collector distribution to be deemed as 1.0: + +* The Collector must be observable + * Metrics and traces should be produced for data in the hot path + * Metrics should be documented in the end-user documentation + * Metrics, or a subset of them, should be marked as stable in the documentation + * Logs should be produced for Collector lifecycle events + * Stability expectations and lifecycle for telemetry should be documented, so that users can know what they can rely on for their dashboards and alerts +* The Collector must be scalable + * Backpressure from the exporter all the way back to the receiver should be supported + * Queueing must be supported to handle increased loads + * Performance metrics are in place and follow best practices for benchmarking + * Individual components must: + * Have their lifecycle expectations enshrined in tests + * Have goleak enabled +* End-user documentation should be provided as part of the official project’s documentation under opentelemetry.io, including: + * Getting started with the Collector + * Available (stable) components and how to use them + * Blueprints for common use cases + * Error scenarios and error propagation + * Troubleshooting and how to obtain telemetry from the Collector for the purposes of bug reporting + * Queueing, batching, and handling of backpressure +* The Collector must be supported + * Processes, workflows and expectations regarding support, bug reporting and questions should be documented. + * A minimum support period for 1.0 is documented, similarly to [API and SDK](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md#api-support) stability guarantees. diff --git a/docs/images/design-collector-agent.png b/docs/images/design-collector-agent.png deleted file mode 100644 index 7f50eb66fa6b61b3350e34e93ff3296b97a3d20b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 98922 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 SZslFzPgY7%GE2h1_x}KSE48u! diff --git a/docs/images/design-collector-service.png b/docs/images/design-collector-service.png deleted file mode 100644 index 83f75e950f868f99d122dd81f15d1c451417eb7d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109843 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∨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ʛmfxLQ=Yd70Ep&8s5f_xfWk_AZ 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 ngU_!TSr%r8e*6%(sl_Uzq4X^$m8d9v6 diff --git a/docs/images/design-exporters.png b/docs/images/design-exporters.png deleted file mode 100644 index d19d41d36d31bee1572f75ac4832dd2965d77f9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36684 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 z 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 Ltxc{N9gO%7`w4bK diff --git a/docs/images/design-receivers.png b/docs/images/design-receivers.png deleted file mode 100644 index ca1f647bb695b83020c12210e4b57b67a23b4204..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47509 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 diff --git a/docs/images/opentelemetry-service-deployment-models.png b/docs/images/opentelemetry-service-deployment-models.png deleted file mode 100644 index b977c0de0158d69345d8255672d6b9e382e5b2b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78430 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 diff --git a/docs/images/zpages-example.png b/docs/images/zpages-example.png deleted file mode 100644 index 168004dd6fcef7cdf2cae1483b98340ec502dd6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 373980 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 ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata + replace go.opentelemetry.io/collector/receiver => ../../receiver replace go.opentelemetry.io/collector/extension => ../../extension diff --git a/exporter/debugexporter/go.sum b/exporter/debugexporter/go.sum index dbdb92fd3bb..7bbf6704ff6 100644 --- a/exporter/debugexporter/go.sum +++ b/exporter/debugexporter/go.sum @@ -1,7 +1,7 @@ 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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -16,13 +16,11 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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/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= @@ -31,8 +29,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -50,32 +48,32 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.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.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -91,16 +89,16 @@ 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -113,14 +111,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/exporter/debugexporter/internal/metadata/generated_status.go b/exporter/debugexporter/internal/metadata/generated_status.go index 18587820654..608b23c1536 100644 --- a/exporter/debugexporter/internal/metadata/generated_status.go +++ b/exporter/debugexporter/internal/metadata/generated_status.go @@ -3,15 +3,11 @@ 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" + Type = component.MustNewType("debug") ) const ( @@ -19,11 +15,3 @@ const ( 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/internal/metadata/generated_telemetry.go b/exporter/debugexporter/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..abe43e7fa07 --- /dev/null +++ b/exporter/debugexporter/internal/metadata/generated_telemetry.go @@ -0,0 +1,18 @@ +// 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" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/exporter/debugexporter") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/exporter/debugexporter") +} diff --git a/exporter/debugexporter/internal/metadata/generated_telemetry_test.go b/exporter/debugexporter/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..ed6c580e677 --- /dev/null +++ b/exporter/debugexporter/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/exporter/debugexporter", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/exporter/debugexporter", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/exporter/exporterbatcher/batch_func.go b/exporter/exporterbatcher/batch_func.go new file mode 100644 index 00000000000..0298276ba7b --- /dev/null +++ b/exporter/exporterbatcher/batch_func.go @@ -0,0 +1,24 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterbatcher // import "go.opentelemetry.io/collector/exporter/exporterbatcher" + +import "context" + +// BatchMergeFunc is a function that merges two requests into a single request. +// Do not mutate the requests passed to the function if error can be returned after mutation or if the exporter is +// marked as not mutable. +// Experimental: This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. +type BatchMergeFunc[T any] func(context.Context, T, T) (T, error) + +// BatchMergeSplitFunc is a function that merge and/or splits one or two requests into multiple requests based on the +// configured limit provided in MaxSizeConfig. +// All the returned requests MUST have a number of items that does not exceed the maximum number of items. +// Size of the last returned request MUST be less or equal than the size of any other returned request. +// The original request MUST not be mutated if error is returned after mutation or if the exporter is +// marked as not mutable. The length of the returned slice MUST not be 0. The optionalReq argument can be nil, +// make sure to check it before using. +// Experimental: This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. +type BatchMergeSplitFunc[T any] func(ctx context.Context, cfg MaxSizeConfig, optionalReq T, req T) ([]T, error) diff --git a/exporter/exporterbatcher/config.go b/exporter/exporterbatcher/config.go new file mode 100644 index 00000000000..239dc2dd4fe --- /dev/null +++ b/exporter/exporterbatcher/config.go @@ -0,0 +1,70 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterbatcher // import "go.opentelemetry.io/collector/exporter/exporterbatcher" + +import ( + "errors" + "time" +) + +// Config defines a configuration for batching requests based on a timeout and a minimum number of items. +// MaxSizeItems defines batch splitting functionality if it's more than zero. +// Experimental: This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. +type Config struct { + // Enabled indicates whether to not enqueue batches before sending to the consumerSender. + Enabled bool `mapstructure:"enabled"` + + // FlushTimeout sets the time after which a batch will be sent regardless of its size. + FlushTimeout time.Duration `mapstructure:"flush_timeout"` + + MinSizeConfig `mapstructure:",squash"` + MaxSizeConfig `mapstructure:",squash"` +} + +// MinSizeConfig defines the configuration for the minimum number of items in a batch. +// Experimental: This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. +type MinSizeConfig struct { + // MinSizeItems is the number of items (spans, data points or log records for OTLP) at which the batch should be + // sent regardless of the timeout. There is no guarantee that the batch size always greater than this value. + // This option requires the Request to implement RequestItemsCounter interface. Otherwise, it will be ignored. + MinSizeItems int `mapstructure:"min_size_items"` +} + +// MaxSizeConfig defines the configuration for the maximum number of items in a batch. +// Experimental: This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. +type MaxSizeConfig struct { + // MaxSizeItems is the maximum number of the batch items, i.e. spans, data points or log records for OTLP. + // If the batch size exceeds this value, it will be broken up into smaller batches if possible. + // Setting this value to zero disables the maximum size limit. + MaxSizeItems int `mapstructure:"max_size_items"` +} + +func (c Config) Validate() error { + if c.MinSizeItems < 0 { + return errors.New("min_size_items must be greater than or equal to zero") + } + if c.MaxSizeItems < 0 { + return errors.New("max_size_items must be greater than or equal to zero") + } + if c.MaxSizeItems != 0 && c.MaxSizeItems < c.MinSizeItems { + return errors.New("max_size_items must be greater than or equal to min_size_items") + } + if c.FlushTimeout <= 0 { + return errors.New("timeout must be greater than zero") + } + return nil +} + +func NewDefaultConfig() Config { + return Config{ + Enabled: true, + FlushTimeout: 200 * time.Millisecond, + MinSizeConfig: MinSizeConfig{ + MinSizeItems: 8192, + }, + } +} diff --git a/exporter/exporterbatcher/config_test.go b/exporter/exporterbatcher/config_test.go new file mode 100644 index 00000000000..337f83ce318 --- /dev/null +++ b/exporter/exporterbatcher/config_test.go @@ -0,0 +1,30 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterbatcher + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestConfig_Validate(t *testing.T) { + cfg := NewDefaultConfig() + assert.NoError(t, cfg.Validate()) + + cfg.MinSizeItems = -1 + assert.EqualError(t, cfg.Validate(), "min_size_items must be greater than or equal to zero") + + cfg = NewDefaultConfig() + cfg.FlushTimeout = 0 + assert.EqualError(t, cfg.Validate(), "timeout must be greater than zero") + + cfg.MaxSizeItems = -1 + assert.EqualError(t, cfg.Validate(), "max_size_items must be greater than or equal to zero") + + cfg = NewDefaultConfig() + cfg.MaxSizeItems = 20000 + cfg.MinSizeItems = 20001 + assert.EqualError(t, cfg.Validate(), "max_size_items must be greater than or equal to min_size_items") +} diff --git a/exporter/exporterhelper/README.md b/exporter/exporterhelper/README.md index 06ce55ae626..e32c948c924 100644 --- a/exporter/exporterhelper/README.md +++ b/exporter/exporterhelper/README.md @@ -31,10 +31,6 @@ valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". ### Persistent Queue -**Status: [alpha]** - -> :warning: The capability is under development. To use it, a storage extension needs to be set up. - To use the persistent queue, the following setting needs to be set: - `sending_queue` @@ -44,7 +40,7 @@ To use the persistent queue, the following setting needs to be 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). -When persistent queue is enabled, the batches are being buffered using the provided storage extension - [filestorage] is a popular and safe choice. If the collector instance is killed while having some items in the persistent queue, on restart the items will be be picked and the exporting is continued. +When persistent queue is enabled, the batches are being buffered using the provided storage extension - [filestorage] is a popular and safe choice. If the collector instance is killed while having some items in the persistent queue, on restart the items will be picked and the exporting is continued. ``` ┌─Consumer #1─┐ @@ -66,19 +62,19 @@ When persistent queue is enabled, the batches are being buffered using the provi │ │ │ │ │ │ │ 3 │ ├───► (in progress) write read └─────┬─────┘ ├───►│ └───┘ │ index index │ │ │ │ - ▲ │ │ └─────────────┘ - │ │ │ - │ currently │ ┌─Consumer #4─┐ - │ dispatched │ │ ┌───┐ │ Temporary - │ └───►│ │ 4 │ ├───► failure - │ │ └───┘ │ │ - │ │ │ │ - │ └─────────────┘ │ - │ ▲ │ - │ └── Retry ───────┤ - │ │ - │ │ - └────────────────────────────────────── Requeuing ◄────── Retry limit exceeded ───┘ + │ │ └─────────────┘ + │ │ + currently │ ┌─Consumer #4─┐ + dispatched │ │ ┌───┐ │ Temporary + └───►│ │ 4 │ ├───► failure + │ └───┘ │ │ + │ │ │ + └─────────────┘ │ + ▲ │ + └── Retry ───────┤ + │ + │ + X ◄────── Retry limit exceeded ───┘ ``` Example: diff --git a/exporter/exporterhelper/batch_sender.go b/exporter/exporterhelper/batch_sender.go new file mode 100644 index 00000000000..29065bfe980 --- /dev/null +++ b/exporter/exporterhelper/batch_sender.go @@ -0,0 +1,223 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterhelper // import "go.opentelemetry.io/collector/exporter/exporterhelper" + +import ( + "context" + "sync" + "sync/atomic" + "time" + + "go.uber.org/zap" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exporterbatcher" +) + +// batchSender is a component that places requests into batches before passing them to the downstream senders. +// Batches are sent out with any of the following conditions: +// - batch size reaches cfg.MinSizeItems +// - cfg.FlushTimeout is elapsed since the timestamp when the previous batch was sent out. +// - concurrencyLimit is reached. +type batchSender struct { + baseRequestSender + cfg exporterbatcher.Config + mergeFunc exporterbatcher.BatchMergeFunc[Request] + mergeSplitFunc exporterbatcher.BatchMergeSplitFunc[Request] + + // concurrencyLimit is the maximum number of goroutines that can be blocked by the batcher. + // If this number is reached and all the goroutines are busy, the batch will be sent right away. + // Populated from the number of queue consumers if queue is enabled. + concurrencyLimit uint64 + activeRequests atomic.Uint64 + + resetTimerCh chan struct{} + + mu sync.Mutex + activeBatch *batch + + logger *zap.Logger + + shutdownCh chan struct{} + stopped *atomic.Bool +} + +// newBatchSender returns a new batch consumer component. +func newBatchSender(cfg exporterbatcher.Config, set exporter.CreateSettings, + mf exporterbatcher.BatchMergeFunc[Request], msf exporterbatcher.BatchMergeSplitFunc[Request]) *batchSender { + bs := &batchSender{ + activeBatch: newEmptyBatch(), + cfg: cfg, + logger: set.Logger, + mergeFunc: mf, + mergeSplitFunc: msf, + shutdownCh: make(chan struct{}), + stopped: &atomic.Bool{}, + resetTimerCh: make(chan struct{}), + } + return bs +} + +func (bs *batchSender) Start(_ context.Context, _ component.Host) error { + timer := time.NewTimer(bs.cfg.FlushTimeout) + go func() { + for { + select { + case <-bs.shutdownCh: + bs.mu.Lock() + if bs.activeBatch.request != nil { + bs.exportActiveBatch() + } + bs.mu.Unlock() + if !timer.Stop() { + <-timer.C + } + return + case <-timer.C: + bs.mu.Lock() + if bs.activeBatch.request != nil { + bs.exportActiveBatch() + } + bs.mu.Unlock() + timer.Reset(bs.cfg.FlushTimeout) + case <-bs.resetTimerCh: + if !timer.Stop() { + <-timer.C + } + timer.Reset(bs.cfg.FlushTimeout) + } + } + }() + + return nil +} + +type batch struct { + ctx context.Context + request Request + done chan struct{} + err error +} + +func newEmptyBatch() *batch { + return &batch{ + ctx: context.Background(), + done: make(chan struct{}), + } +} + +// exportActiveBatch exports the active batch asynchronously and replaces it with a new one. +// Caller must hold the lock. +func (bs *batchSender) exportActiveBatch() { + go func(b *batch) { + b.err = b.request.Export(b.ctx) + close(b.done) + }(bs.activeBatch) + bs.activeBatch = newEmptyBatch() +} + +// isActiveBatchReady returns true if the active batch is ready to be exported. +// The batch is ready if it has reached the minimum size or the concurrency limit is reached. +// Caller must hold the lock. +func (bs *batchSender) isActiveBatchReady() bool { + return bs.activeBatch.request.ItemsCount() >= bs.cfg.MinSizeItems || + (bs.concurrencyLimit > 0 && bs.activeRequests.Load() >= bs.concurrencyLimit) +} + +func (bs *batchSender) send(ctx context.Context, req Request) error { + // Stopped batch sender should act as pass-through to allow the queue to be drained. + if bs.stopped.Load() { + return bs.nextSender.send(ctx, req) + } + + if bs.cfg.MaxSizeItems > 0 { + return bs.sendMergeSplitBatch(ctx, req) + } + return bs.sendMergeBatch(ctx, req) +} + +// sendMergeSplitBatch sends the request to the batch which may be split into multiple requests. +func (bs *batchSender) sendMergeSplitBatch(ctx context.Context, req Request) error { + bs.mu.Lock() + bs.activeRequests.Add(1) + defer bs.activeRequests.Add(^uint64(0)) + + reqs, err := bs.mergeSplitFunc(ctx, bs.cfg.MaxSizeConfig, bs.activeBatch.request, req) + if err != nil || len(reqs) == 0 { + bs.mu.Unlock() + return err + } + if len(reqs) == 1 || bs.activeBatch.request != nil { + bs.updateActiveBatch(ctx, reqs[0]) + batch := bs.activeBatch + if bs.isActiveBatchReady() || len(reqs) > 1 { + bs.exportActiveBatch() + bs.resetTimerCh <- struct{}{} + } + bs.mu.Unlock() + <-batch.done + if batch.err != nil { + return batch.err + } + reqs = reqs[1:] + } else { + bs.mu.Unlock() + } + + // Intentionally do not put the last request in the active batch to not block it. + // TODO: Consider including the partial request in the error to avoid double publishing. + for _, r := range reqs { + if err := r.Export(ctx); err != nil { + return err + } + } + return nil +} + +// sendMergeBatch sends the request to the batch and waits for the batch to be exported. +func (bs *batchSender) sendMergeBatch(ctx context.Context, req Request) error { + bs.mu.Lock() + bs.activeRequests.Add(1) + defer bs.activeRequests.Add(^uint64(0)) + + if bs.activeBatch.request != nil { + var err error + req, err = bs.mergeFunc(ctx, bs.activeBatch.request, req) + if err != nil { + bs.mu.Unlock() + return err + } + } + bs.updateActiveBatch(ctx, req) + batch := bs.activeBatch + if bs.isActiveBatchReady() { + bs.exportActiveBatch() + bs.resetTimerCh <- struct{}{} + } + bs.mu.Unlock() + <-batch.done + return batch.err +} + +// updateActiveBatch update the active batch to the new merged request and context. +// The context is only set once and is not updated after the first call. +// Merging the context would be complex and require an additional goroutine to handle the context cancellation. +// We take the approach of using the context from the first request since it's likely to have the shortest timeout. +func (bs *batchSender) updateActiveBatch(ctx context.Context, req Request) { + if bs.activeBatch.request == nil { + bs.activeBatch.ctx = ctx + } + bs.activeBatch.request = req +} + +func (bs *batchSender) Shutdown(context.Context) error { + bs.stopped.Store(true) + close(bs.shutdownCh) + // Wait for the active requests to finish. + for bs.activeRequests.Load() > 0 { + time.Sleep(10 * time.Millisecond) + } + return nil +} diff --git a/exporter/exporterhelper/batch_sender_test.go b/exporter/exporterhelper/batch_sender_test.go new file mode 100644 index 00000000000..15d05b066f4 --- /dev/null +++ b/exporter/exporterhelper/batch_sender_test.go @@ -0,0 +1,448 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterhelper // import "go.opentelemetry.io/collector/exporter/exporterhelper" + +import ( + "context" + "errors" + "fmt" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/exporter/exporterbatcher" + "go.opentelemetry.io/collector/exporter/exporterqueue" +) + +func TestBatchSender_Merge(t *testing.T) { + cfg := exporterbatcher.NewDefaultConfig() + cfg.MinSizeItems = 10 + cfg.FlushTimeout = 100 * time.Millisecond + + tests := []struct { + name string + batcherOption Option + }{ + { + name: "split_disabled", + batcherOption: WithBatcher(cfg, WithRequestBatchFuncs(fakeBatchMergeFunc, fakeBatchMergeSplitFunc)), + }, + { + name: "split_high_limit", + batcherOption: func() Option { + c := cfg + c.MaxSizeItems = 1000 + return WithBatcher(c, WithRequestBatchFuncs(fakeBatchMergeFunc, fakeBatchMergeSplitFunc)) + }(), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + be := queueBatchExporter(t, tt.batcherOption) + + require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) + t.Cleanup(func() { + require.NoError(t, be.Shutdown(context.Background())) + }) + + sink := newFakeRequestSink() + + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 8, sink: sink})) + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 3, sink: sink})) + + // the first two requests should be merged into one and sent by reaching the minimum items size + assert.Eventually(t, func() bool { + return sink.requestsCount.Load() == 1 && sink.itemsCount.Load() == 11 + }, 50*time.Millisecond, 10*time.Millisecond) + + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 3, sink: sink})) + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 1, sink: sink})) + + // the third and fifth requests should be sent by reaching the timeout + // the fourth request should be ignored because of the merge error. + time.Sleep(50 * time.Millisecond) + + // should be ignored because of the merge error. + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 3, sink: sink, + mergeErr: errors.New("merge error")})) + + assert.Equal(t, uint64(1), sink.requestsCount.Load()) + assert.Eventually(t, func() bool { + return sink.requestsCount.Load() == 2 && sink.itemsCount.Load() == 15 + }, 100*time.Millisecond, 10*time.Millisecond) + }) + } +} + +func TestBatchSender_BatchExportError(t *testing.T) { + cfg := exporterbatcher.NewDefaultConfig() + cfg.MinSizeItems = 10 + tests := []struct { + name string + batcherOption Option + expectedRequests uint64 + expectedItems uint64 + }{ + { + name: "merge_only", + batcherOption: WithBatcher(cfg, WithRequestBatchFuncs(fakeBatchMergeFunc, fakeBatchMergeSplitFunc)), + }, + { + name: "merge_without_split_triggered", + batcherOption: func() Option { + c := cfg + c.MaxSizeItems = 200 + return WithBatcher(c, WithRequestBatchFuncs(fakeBatchMergeFunc, fakeBatchMergeSplitFunc)) + }(), + }, + { + name: "merge_with_split_triggered", + batcherOption: func() Option { + c := cfg + c.MaxSizeItems = 20 + return WithBatcher(c, WithRequestBatchFuncs(fakeBatchMergeFunc, fakeBatchMergeSplitFunc)) + }(), + expectedRequests: 1, + expectedItems: 20, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + be := queueBatchExporter(t, tt.batcherOption) + + require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) + t.Cleanup(func() { + require.NoError(t, be.Shutdown(context.Background())) + }) + + sink := newFakeRequestSink() + + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 4, sink: sink})) + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 4, sink: sink})) + + // the first two requests should be blocked by the batchSender. + time.Sleep(50 * time.Millisecond) + assert.Equal(t, uint64(0), sink.requestsCount.Load()) + + // the third request should trigger the export and cause an error. + errReq := &fakeRequest{items: 20, exportErr: errors.New("transient error"), sink: sink} + require.NoError(t, be.send(context.Background(), errReq)) + + // the batch should be dropped since the queue doesn't have requeuing enabled. + assert.Eventually(t, func() bool { + return sink.requestsCount.Load() == tt.expectedRequests && + sink.itemsCount.Load() == tt.expectedItems && + be.batchSender.(*batchSender).activeRequests.Load() == uint64(0) && + be.queueSender.(*queueSender).queue.Size() == 0 + }, 100*time.Millisecond, 10*time.Millisecond) + }) + } +} + +func TestBatchSender_MergeOrSplit(t *testing.T) { + cfg := exporterbatcher.NewDefaultConfig() + cfg.MinSizeItems = 5 + cfg.MaxSizeItems = 10 + cfg.FlushTimeout = 100 * time.Millisecond + be := queueBatchExporter(t, WithBatcher(cfg, WithRequestBatchFuncs(fakeBatchMergeFunc, fakeBatchMergeSplitFunc))) + + require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) + t.Cleanup(func() { + require.NoError(t, be.Shutdown(context.Background())) + }) + + sink := newFakeRequestSink() + + // should be sent right away by reaching the minimum items size. + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 8, sink: sink})) + assert.Eventually(t, func() bool { + return sink.requestsCount.Load() == 1 && sink.itemsCount.Load() == 8 + }, 50*time.Millisecond, 10*time.Millisecond) + + // big request should be broken down into two requests, both are sent right away. + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 17, sink: sink})) + + assert.Eventually(t, func() bool { + return sink.requestsCount.Load() == 3 && sink.itemsCount.Load() == 25 + }, 50*time.Millisecond, 10*time.Millisecond) + + // request that cannot be split should be dropped. + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 11, sink: sink, + mergeErr: errors.New("split error")})) + + // big request should be broken down into two requests, both are sent right away. + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 13, sink: sink})) + + assert.Eventually(t, func() bool { + return sink.requestsCount.Load() == 5 && sink.itemsCount.Load() == 38 + }, 50*time.Millisecond, 10*time.Millisecond) + + fmt.Println("TestBatchSender_MergeOrSplit") +} + +func TestBatchSender_Shutdown(t *testing.T) { + batchCfg := exporterbatcher.NewDefaultConfig() + batchCfg.MinSizeItems = 10 + be := queueBatchExporter(t, WithBatcher(batchCfg, WithRequestBatchFuncs(fakeBatchMergeFunc, fakeBatchMergeSplitFunc))) + + require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) + + sink := newFakeRequestSink() + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 3, sink: sink})) + + // To make the request reached the batchSender before shutdown. + time.Sleep(50 * time.Millisecond) + + require.NoError(t, be.Shutdown(context.Background())) + + // shutdown should force sending the batch + assert.Equal(t, uint64(1), sink.requestsCount.Load()) + assert.Equal(t, uint64(3), sink.itemsCount.Load()) +} + +func TestBatchSender_Disabled(t *testing.T) { + cfg := exporterbatcher.NewDefaultConfig() + cfg.Enabled = false + cfg.MaxSizeItems = 5 + be, err := newBaseExporter(defaultSettings, defaultType, newNoopObsrepSender, + WithBatcher(cfg, WithRequestBatchFuncs(fakeBatchMergeFunc, fakeBatchMergeSplitFunc))) + require.NotNil(t, be) + require.NoError(t, err) + + require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) + t.Cleanup(func() { + require.NoError(t, be.Shutdown(context.Background())) + }) + + sink := newFakeRequestSink() + // should be sent right away without splitting because batching is disabled. + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 8, sink: sink})) + assert.Equal(t, uint64(1), sink.requestsCount.Load()) + assert.Equal(t, uint64(8), sink.itemsCount.Load()) +} + +func TestBatchSender_InvalidMergeSplitFunc(t *testing.T) { + invalidMergeSplitFunc := func(_ context.Context, _ exporterbatcher.MaxSizeConfig, _ Request, req2 Request) ([]Request, + error) { + // reply with invalid 0 length slice if req2 is more than 20 items + if req2.(*fakeRequest).items > 20 { + return []Request{}, nil + } + // otherwise reply with a single request. + return []Request{req2}, nil + } + cfg := exporterbatcher.NewDefaultConfig() + cfg.FlushTimeout = 50 * time.Millisecond + cfg.MaxSizeItems = 20 + be := queueBatchExporter(t, WithBatcher(cfg, WithRequestBatchFuncs(fakeBatchMergeFunc, invalidMergeSplitFunc))) + + require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) + t.Cleanup(func() { + require.NoError(t, be.Shutdown(context.Background())) + }) + + sink := newFakeRequestSink() + // first request should be ignored due to invalid merge/split function. + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 30, sink: sink})) + // second request should be sent after reaching the timeout. + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 15, sink: sink})) + assert.Eventually(t, func() bool { + return sink.requestsCount.Load() == 1 && sink.itemsCount.Load() == 15 + }, 100*time.Millisecond, 10*time.Millisecond) +} + +func TestBatchSender_PostShutdown(t *testing.T) { + be, err := newBaseExporter(defaultSettings, defaultType, newNoopObsrepSender, + WithBatcher(exporterbatcher.NewDefaultConfig(), WithRequestBatchFuncs(fakeBatchMergeFunc, + fakeBatchMergeSplitFunc))) + require.NotNil(t, be) + require.NoError(t, err) + assert.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) + assert.NoError(t, be.Shutdown(context.Background())) + + // Closed batch sender should act as a pass-through to not block queue draining. + sink := newFakeRequestSink() + require.NoError(t, be.send(context.Background(), &fakeRequest{items: 8, sink: sink})) + assert.Equal(t, uint64(1), sink.requestsCount.Load()) + assert.Equal(t, uint64(8), sink.itemsCount.Load()) +} + +func TestBatchSender_ConcurrencyLimitReached(t *testing.T) { + qCfg := exporterqueue.NewDefaultConfig() + qCfg.NumConsumers = 2 + be, err := newBaseExporter(defaultSettings, defaultType, newNoopObsrepSender, + WithBatcher(exporterbatcher.NewDefaultConfig(), WithRequestBatchFuncs(fakeBatchMergeFunc, fakeBatchMergeSplitFunc)), + WithRequestQueue(qCfg, exporterqueue.NewMemoryQueueFactory[Request]())) + require.NotNil(t, be) + require.NoError(t, err) + assert.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) + t.Cleanup(func() { + assert.NoError(t, be.Shutdown(context.Background())) + }) + + sink := newFakeRequestSink() + assert.NoError(t, be.send(context.Background(), &fakeRequest{items: 8, sink: sink})) + + // the second request should be sent by reaching max concurrency limit. + assert.NoError(t, be.send(context.Background(), &fakeRequest{items: 8, sink: sink})) + + assert.Eventually(t, func() bool { + return sink.requestsCount.Load() == 1 && sink.itemsCount.Load() == 16 + }, 100*time.Millisecond, 10*time.Millisecond) +} + +func TestBatchSender_BatchBlocking(t *testing.T) { + bCfg := exporterbatcher.NewDefaultConfig() + bCfg.MinSizeItems = 3 + be, err := newBaseExporter(defaultSettings, defaultType, newNoopObsrepSender, + WithBatcher(bCfg, WithRequestBatchFuncs(fakeBatchMergeFunc, fakeBatchMergeSplitFunc))) + require.NotNil(t, be) + require.NoError(t, err) + require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) + + sink := newFakeRequestSink() + + // send 6 blocking requests + wg := sync.WaitGroup{} + for i := 0; i < 6; i++ { + wg.Add(1) + go func() { + assert.NoError(t, be.send(context.Background(), &fakeRequest{items: 1, sink: sink, delay: 10 * time.Millisecond})) + wg.Done() + }() + } + wg.Wait() + + // should be sent in two batches since the batch size is 3 + assert.Equal(t, uint64(2), sink.requestsCount.Load()) + assert.Equal(t, uint64(6), sink.itemsCount.Load()) + + require.NoError(t, be.Shutdown(context.Background())) +} + +// Validate that the batch is cancelled once the first request in the request is cancelled +func TestBatchSender_BatchCancelled(t *testing.T) { + bCfg := exporterbatcher.NewDefaultConfig() + bCfg.MinSizeItems = 2 + be, err := newBaseExporter(defaultSettings, defaultType, newNoopObsrepSender, + WithBatcher(bCfg, WithRequestBatchFuncs(fakeBatchMergeFunc, fakeBatchMergeSplitFunc))) + require.NotNil(t, be) + require.NoError(t, err) + require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) + + sink := newFakeRequestSink() + + // send 2 blocking requests + wg := sync.WaitGroup{} + ctx, cancel := context.WithCancel(context.Background()) + wg.Add(1) + go func() { + assert.ErrorIs(t, be.send(ctx, &fakeRequest{items: 1, sink: sink, delay: 100 * time.Millisecond}), context.Canceled) + wg.Done() + }() + wg.Add(1) + go func() { + time.Sleep(20 * time.Millisecond) // ensure this call is the second + assert.ErrorIs(t, be.send(context.Background(), &fakeRequest{items: 1, sink: sink, delay: 100 * time.Millisecond}), context.Canceled) + wg.Done() + }() + cancel() // canceling the first request should cancel the whole batch + wg.Wait() + + // nothing should be delivered + assert.Equal(t, uint64(0), sink.requestsCount.Load()) + assert.Equal(t, uint64(0), sink.itemsCount.Load()) + + require.NoError(t, be.Shutdown(context.Background())) +} + +func TestBatchSender_DrainActiveRequests(t *testing.T) { + bCfg := exporterbatcher.NewDefaultConfig() + bCfg.MinSizeItems = 2 + be, err := newBaseExporter(defaultSettings, defaultType, newNoopObsrepSender, + WithBatcher(bCfg, WithRequestBatchFuncs(fakeBatchMergeFunc, fakeBatchMergeSplitFunc))) + require.NotNil(t, be) + require.NoError(t, err) + require.NoError(t, be.Start(context.Background(), componenttest.NewNopHost())) + + sink := newFakeRequestSink() + + // send 3 blocking requests with a timeout + go func() { + assert.NoError(t, be.send(context.Background(), &fakeRequest{items: 1, sink: sink, delay: 40 * time.Millisecond})) + }() + go func() { + assert.NoError(t, be.send(context.Background(), &fakeRequest{items: 1, sink: sink, delay: 40 * time.Millisecond})) + }() + go func() { + assert.NoError(t, be.send(context.Background(), &fakeRequest{items: 1, sink: sink, delay: 40 * time.Millisecond})) + }() + + // give time for the first two requests to be batched + time.Sleep(20 * time.Millisecond) + + // Shutdown should force the active batch to be dispatched and wait for all batches to be delivered. + // It should take 120 milliseconds to complete. + require.NoError(t, be.Shutdown(context.Background())) + + assert.Equal(t, uint64(2), sink.requestsCount.Load()) + assert.Equal(t, uint64(3), sink.itemsCount.Load()) +} + +func TestBatchSender_WithBatcherOption(t *testing.T) { + tests := []struct { + name string + opts []Option + expectedErr bool + }{ + { + name: "no_funcs_set", + opts: []Option{WithBatcher(exporterbatcher.NewDefaultConfig())}, + expectedErr: true, + }, + { + name: "funcs_set_internally", + opts: []Option{withBatchFuncs(fakeBatchMergeFunc, fakeBatchMergeSplitFunc), WithBatcher(exporterbatcher.NewDefaultConfig())}, + expectedErr: false, + }, + { + name: "funcs_set_twice", + opts: []Option{ + withBatchFuncs(fakeBatchMergeFunc, fakeBatchMergeSplitFunc), + WithBatcher(exporterbatcher.NewDefaultConfig(), WithRequestBatchFuncs(fakeBatchMergeFunc, + fakeBatchMergeSplitFunc)), + }, + expectedErr: true, + }, + { + name: "nil_funcs", + opts: []Option{WithBatcher(exporterbatcher.NewDefaultConfig(), WithRequestBatchFuncs(nil, nil))}, + expectedErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + be, err := newBaseExporter(defaultSettings, defaultType, newNoopObsrepSender, tt.opts...) + if tt.expectedErr { + assert.Nil(t, be) + assert.Error(t, err) + } else { + assert.NotNil(t, be) + assert.NoError(t, err) + } + }) + } +} + +func queueBatchExporter(t *testing.T, batchOption Option) *baseExporter { + be, err := newBaseExporter(defaultSettings, defaultType, newNoopObsrepSender, batchOption, + WithRequestQueue(exporterqueue.NewDefaultConfig(), exporterqueue.NewMemoryQueueFactory[Request]())) + require.NotNil(t, be) + require.NoError(t, err) + return be +} diff --git a/exporter/exporterhelper/common.go b/exporter/exporterhelper/common.go index 509570960e8..aa84e9019f2 100644 --- a/exporter/exporterhelper/common.go +++ b/exporter/exporterhelper/common.go @@ -5,6 +5,7 @@ package exporterhelper // import "go.opentelemetry.io/collector/exporter/exporte import ( "context" + "fmt" "go.uber.org/multierr" "go.uber.org/zap" @@ -13,6 +14,7 @@ import ( "go.opentelemetry.io/collector/config/configretry" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exporterbatcher" "go.opentelemetry.io/collector/exporter/exporterqueue" ) @@ -42,41 +44,45 @@ func (b *baseRequestSender) setNextSender(nextSender requestSender) { type obsrepSenderFactory func(obsrep *ObsReport) requestSender // Option apply changes to baseExporter. -type Option func(*baseExporter) +type Option func(*baseExporter) error // WithStart overrides the default Start function for an exporter. // The default start function does nothing and always returns nil. func WithStart(start component.StartFunc) Option { - return func(o *baseExporter) { + return func(o *baseExporter) error { o.StartFunc = start + return nil } } // WithShutdown overrides the default Shutdown function for an exporter. // The default shutdown function does nothing and always returns nil. func WithShutdown(shutdown component.ShutdownFunc) Option { - return func(o *baseExporter) { + return func(o *baseExporter) error { o.ShutdownFunc = shutdown + return nil } } // WithTimeout overrides the default TimeoutSettings for an exporter. // The default TimeoutSettings is 5 seconds. func WithTimeout(timeoutSettings TimeoutSettings) Option { - return func(o *baseExporter) { + return func(o *baseExporter) error { o.timeoutSender.cfg = timeoutSettings + return nil } } // 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) { + return func(o *baseExporter) error { if !config.Enabled { o.exportFailureMessage += " Try enabling retry_on_failure config option to retry on retryable errors." - return + return nil } o.retrySender = newRetrySender(config, o.set) + return nil } } @@ -84,13 +90,13 @@ func WithRetry(config configretry.BackOffConfig) Option { // The default QueueSettings is to disable queueing. // This option cannot be used with the new exporter helpers New[Traces|Metrics|Logs]RequestExporter. func WithQueue(config QueueSettings) Option { - return func(o *baseExporter) { + return func(o *baseExporter) error { if o.marshaler == nil || o.unmarshaler == nil { - panic("WithQueue option is not available for the new request exporters, use WithRequestQueue instead") + return fmt.Errorf("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 + return nil } qf := exporterqueue.NewPersistentQueueFactory[Request](config.StorageID, exporterqueue.PersistentQueueSettings[Request]{ Marshaler: o.marshaler, @@ -105,27 +111,29 @@ func WithQueue(config QueueSettings) Option { QueueSize: config.QueueSize, }) o.queueSender = newQueueSender(q, o.set, config.NumConsumers, o.exportFailureMessage) + return nil } } // 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 +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. func WithRequestQueue(cfg exporterqueue.Config, queueFactory exporterqueue.Factory[Request]) Option { - return func(o *baseExporter) { + return func(o *baseExporter) error { if o.marshaler != nil || o.unmarshaler != nil { - panic("WithRequestQueue option must be used with the new request exporters only, use WithQueue instead") + return fmt.Errorf("WithRequestQueue option must be used with the new request exporters only, use WithQueue instead") } if !cfg.Enabled { o.exportFailureMessage += " Try enabling sending_queue to survive temporary failures." - return + return nil } set := exporterqueue.Settings{ DataType: o.signal, ExporterSettings: o.set, } o.queueSender = newQueueSender(queueFactory(context.Background(), set, cfg), o.set, cfg.NumConsumers, o.exportFailureMessage) + return nil } } @@ -133,24 +141,80 @@ func WithRequestQueue(cfg exporterqueue.Config, queueFactory exporterqueue.Facto // The default is non-mutable data. // TODO: Verify if we can change the default to be mutable as we do for processors. func WithCapabilities(capabilities consumer.Capabilities) Option { - return func(o *baseExporter) { + return func(o *baseExporter) error { o.consumerOptions = append(o.consumerOptions, consumer.WithCapabilities(capabilities)) + return nil + } +} + +// BatcherOption apply changes to batcher sender. +type BatcherOption func(*batchSender) error + +// WithRequestBatchFuncs sets the functions for merging and splitting batches for an exporter built for custom request types. +func WithRequestBatchFuncs(mf exporterbatcher.BatchMergeFunc[Request], msf exporterbatcher.BatchMergeSplitFunc[Request]) BatcherOption { + return func(bs *batchSender) error { + if mf == nil || msf == nil { + return fmt.Errorf("WithRequestBatchFuncs must be provided with non-nil functions") + } + if bs.mergeFunc != nil || bs.mergeSplitFunc != nil { + return fmt.Errorf("WithRequestBatchFuncs can only be used once with request-based exporters") + } + bs.mergeFunc = mf + bs.mergeSplitFunc = msf + return nil + } +} + +// WithBatcher enables batching for an exporter based on custom request types. +// For now, it can be used only with the New[Traces|Metrics|Logs]RequestExporter exporter helpers and +// WithRequestBatchFuncs provided. +// 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 WithBatcher(cfg exporterbatcher.Config, opts ...BatcherOption) Option { + return func(o *baseExporter) error { + if !cfg.Enabled { + return nil + } + + bs := newBatchSender(cfg, o.set, o.batchMergeFunc, o.batchMergeSplitfunc) + for _, opt := range opts { + if err := opt(bs); err != nil { + return err + } + } + if bs.mergeFunc == nil || bs.mergeSplitFunc == nil { + return fmt.Errorf("WithRequestBatchFuncs must be provided for the batcher applied to the request-based exporters") + } + o.batchSender = bs + return nil } } // 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) { + return func(o *baseExporter) error { o.marshaler = marshaler + return nil } } // 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) { + return func(o *baseExporter) error { o.unmarshaler = unmarshaler + return nil + } +} + +// withBatchFuncs is used to set the functions for merging and splitting batches for OLTP-based exporters. +// It must be provided as the first option when creating a new exporter helper. +func withBatchFuncs(mf exporterbatcher.BatchMergeFunc[Request], msf exporterbatcher.BatchMergeSplitFunc[Request]) Option { + return func(o *baseExporter) error { + o.batchMergeFunc = mf + o.batchMergeSplitfunc = msf + return nil } } @@ -159,9 +223,13 @@ type baseExporter struct { component.StartFunc component.ShutdownFunc + signal component.DataType + + batchMergeFunc exporterbatcher.BatchMergeFunc[Request] + batchMergeSplitfunc exporterbatcher.BatchMergeSplitFunc[Request] + marshaler exporterqueue.Marshaler[Request] unmarshaler exporterqueue.Unmarshaler[Request] - signal component.DataType set exporter.CreateSettings obsrep *ObsReport @@ -172,6 +240,7 @@ type baseExporter struct { // Chain of senders that the exporter helper applies before passing the data to the actual exporter. // The data is handled by each sender in the respective order starting from the queueSender. // Most of the senders are optional, and initialized with a no-op path-through sender. + batchSender requestSender queueSender requestSender obsrepSender requestSender retrySender requestSender @@ -189,6 +258,7 @@ func newBaseExporter(set exporter.CreateSettings, signal component.DataType, osf be := &baseExporter{ signal: signal, + batchSender: &baseRequestSender{}, queueSender: &baseRequestSender{}, obsrepSender: osf(obsReport), retrySender: &baseRequestSender{}, @@ -199,10 +269,23 @@ func newBaseExporter(set exporter.CreateSettings, signal component.DataType, osf } for _, op := range options { - op(be) + err = multierr.Append(err, op(be)) + } + if err != nil { + return nil, err } + be.connectSenders() + if bs, ok := be.batchSender.(*batchSender); ok { + // If queue sender is enabled assign to the batch sender the same number of workers. + if qs, ok := be.queueSender.(*queueSender); ok { + bs.concurrencyLimit = uint64(qs.numConsumers) + } + // Batcher sender mutates the data. + be.consumerOptions = append(be.consumerOptions, consumer.WithCapabilities(consumer.Capabilities{MutatesData: true})) + } + return be, nil } @@ -218,7 +301,8 @@ func (be *baseExporter) send(ctx context.Context, req Request) error { // connectSenders connects the senders in the predefined order. func (be *baseExporter) connectSenders() { - be.queueSender.setNextSender(be.obsrepSender) + be.queueSender.setNextSender(be.batchSender) + be.batchSender.setNextSender(be.obsrepSender) be.obsrepSender.setNextSender(be.retrySender) be.retrySender.setNextSender(be.timeoutSender) } @@ -229,7 +313,12 @@ func (be *baseExporter) Start(ctx context.Context, host component.Host) error { return err } - // If no error then start the queueSender. + // If no error then start the batchSender. + if err := be.batchSender.Start(ctx, host); err != nil { + return err + } + + // Last start the queueSender. return be.queueSender.Start(ctx, host) } @@ -237,6 +326,8 @@ func (be *baseExporter) Shutdown(ctx context.Context) error { return multierr.Combine( // First shutdown the retry sender, so the queue sender can flush the queue without retries. be.retrySender.Shutdown(ctx), + // Then shutdown the batch sender + be.batchSender.Shutdown(ctx), // Then shutdown the queue sender. be.queueSender.Shutdown(ctx), // Last shutdown the wrapped exporter itself. diff --git a/exporter/exporterhelper/common_test.go b/exporter/exporterhelper/common_test.go index e3a584b17b1..e134affeaaa 100644 --- a/exporter/exporterhelper/common_test.go +++ b/exporter/exporterhelper/common_test.go @@ -71,16 +71,15 @@ func TestQueueOptionsWithRequestExporter(t *testing.T) { require.Nil(t, err) 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(), defaultType, newNoopObsrepSender, - withMarshaler(mockRequestMarshaler), withUnmarshaler(mockRequestUnmarshaler(&mockRequest{})), - WithRetry(configretry.NewDefaultBackOffConfig()), - WithRequestQueue(exporterqueue.NewDefaultConfig(), exporterqueue.NewMemoryQueueFactory[Request]())) - }) + _, err = newBaseExporter(exportertest.NewNopCreateSettings(), defaultType, newNoopObsrepSender, + WithRetry(configretry.NewDefaultBackOffConfig()), WithQueue(NewDefaultQueueSettings())) + require.Error(t, err) + + _, err = newBaseExporter(exportertest.NewNopCreateSettings(), defaultType, newNoopObsrepSender, + withMarshaler(mockRequestMarshaler), withUnmarshaler(mockRequestUnmarshaler(&mockRequest{})), + WithRetry(configretry.NewDefaultBackOffConfig()), + WithRequestQueue(exporterqueue.NewDefaultConfig(), exporterqueue.NewMemoryQueueFactory[Request]())) + require.Error(t, err) } func TestBaseExporterLogging(t *testing.T) { diff --git a/exporter/exporterhelper/logs.go b/exporter/exporterhelper/logs.go index ce70230e321..2706ec7fe92 100644 --- a/exporter/exporterhelper/logs.go +++ b/exporter/exporterhelper/logs.go @@ -82,12 +82,15 @@ func NewLogsExporter( if pusher == nil { return nil, errNilPushLogsData } - logsOpts := []Option{withMarshaler(logsRequestMarshaler), withUnmarshaler(newLogsRequestUnmarshalerFunc(pusher))} + logsOpts := []Option{ + withMarshaler(logsRequestMarshaler), withUnmarshaler(newLogsRequestUnmarshalerFunc(pusher)), + withBatchFuncs(mergeLogs, mergeSplitLogs), + } return NewLogsRequestExporter(ctx, set, requestFromLogs(pusher), append(logsOpts, options...)...) } // 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 +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type RequestFromLogsFunc func(context.Context, plog.Logs) (Request, error) @@ -99,7 +102,7 @@ func requestFromLogs(pusher consumer.ConsumeLogsFunc) RequestFromLogsFunc { } // NewLogsRequestExporter creates new logs exporter based on custom LogsConverter and RequestSender. -// This API is at the early stage of development and may change without backward compatibility +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. func NewLogsRequestExporter( _ context.Context, diff --git a/exporter/exporterhelper/logs_batch.go b/exporter/exporterhelper/logs_batch.go new file mode 100644 index 00000000000..296538bc0e0 --- /dev/null +++ b/exporter/exporterhelper/logs_batch.go @@ -0,0 +1,137 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterhelper // import "go.opentelemetry.io/collector/exporter/exporterhelper" + +import ( + "context" + "errors" + + "go.opentelemetry.io/collector/exporter/exporterbatcher" + "go.opentelemetry.io/collector/pdata/plog" +) + +// mergeLogs merges two logs requests into one. +func mergeLogs(_ context.Context, r1 Request, r2 Request) (Request, error) { + lr1, ok1 := r1.(*logsRequest) + lr2, ok2 := r2.(*logsRequest) + if !ok1 || !ok2 { + return nil, errors.New("invalid input type") + } + lr2.ld.ResourceLogs().MoveAndAppendTo(lr1.ld.ResourceLogs()) + return lr1, nil +} + +// mergeSplitLogs splits and/or merges the logs into multiple requests based on the MaxSizeConfig. +func mergeSplitLogs(_ context.Context, cfg exporterbatcher.MaxSizeConfig, r1 Request, r2 Request) ([]Request, error) { + var ( + res []Request + destReq *logsRequest + capacityLeft = cfg.MaxSizeItems + ) + for _, req := range []Request{r1, r2} { + if req == nil { + continue + } + srcReq, ok := req.(*logsRequest) + if !ok { + return nil, errors.New("invalid input type") + } + if srcReq.ld.LogRecordCount() <= capacityLeft { + if destReq == nil { + destReq = srcReq + } else { + srcReq.ld.ResourceLogs().MoveAndAppendTo(destReq.ld.ResourceLogs()) + } + capacityLeft -= destReq.ld.LogRecordCount() + continue + } + + for { + extractedLogs := extractLogs(srcReq.ld, capacityLeft) + if extractedLogs.LogRecordCount() == 0 { + break + } + capacityLeft -= extractedLogs.LogRecordCount() + if destReq == nil { + destReq = &logsRequest{ld: extractedLogs, pusher: srcReq.pusher} + } else { + extractedLogs.ResourceLogs().MoveAndAppendTo(destReq.ld.ResourceLogs()) + } + // Create new batch once capacity is reached. + if capacityLeft == 0 { + res = append(res, destReq) + destReq = nil + capacityLeft = cfg.MaxSizeItems + } + } + } + + if destReq != nil { + res = append(res, destReq) + } + return res, nil +} + +// extractLogs extracts logs from the input logs and returns a new logs with the specified number of log records. +func extractLogs(srcLogs plog.Logs, count int) plog.Logs { + destLogs := plog.NewLogs() + srcLogs.ResourceLogs().RemoveIf(func(srcRL plog.ResourceLogs) bool { + if count == 0 { + return false + } + needToExtract := resourceLogsCount(srcRL) > count + if needToExtract { + srcRL = extractResourceLogs(srcRL, count) + } + count -= resourceLogsCount(srcRL) + srcRL.MoveTo(destLogs.ResourceLogs().AppendEmpty()) + return !needToExtract + }) + return destLogs +} + +// extractResourceLogs extracts resource logs and returns a new resource logs with the specified number of log records. +func extractResourceLogs(srcRL plog.ResourceLogs, count int) plog.ResourceLogs { + destRL := plog.NewResourceLogs() + destRL.SetSchemaUrl(srcRL.SchemaUrl()) + srcRL.Resource().CopyTo(destRL.Resource()) + srcRL.ScopeLogs().RemoveIf(func(srcSL plog.ScopeLogs) bool { + if count == 0 { + return false + } + needToExtract := srcSL.LogRecords().Len() > count + if needToExtract { + srcSL = extractScopeLogs(srcSL, count) + } + count -= srcSL.LogRecords().Len() + srcSL.MoveTo(destRL.ScopeLogs().AppendEmpty()) + return !needToExtract + }) + return destRL +} + +// extractScopeLogs extracts scope logs and returns a new scope logs with the specified number of log records. +func extractScopeLogs(srcSL plog.ScopeLogs, count int) plog.ScopeLogs { + destSL := plog.NewScopeLogs() + destSL.SetSchemaUrl(srcSL.SchemaUrl()) + srcSL.Scope().CopyTo(destSL.Scope()) + srcSL.LogRecords().RemoveIf(func(srcLR plog.LogRecord) bool { + if count == 0 { + return false + } + srcLR.MoveTo(destSL.LogRecords().AppendEmpty()) + count-- + return true + }) + return destSL +} + +// resourceLogsCount calculates the total number of log records in the plog.ResourceLogs. +func resourceLogsCount(rl plog.ResourceLogs) int { + count := 0 + for k := 0; k < rl.ScopeLogs().Len(); k++ { + count += rl.ScopeLogs().At(k).LogRecords().Len() + } + return count +} diff --git a/exporter/exporterhelper/logs_batch_test.go b/exporter/exporterhelper/logs_batch_test.go new file mode 100644 index 00000000000..72255ff551e --- /dev/null +++ b/exporter/exporterhelper/logs_batch_test.go @@ -0,0 +1,159 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterhelper + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/exporter/exporterbatcher" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/testdata" +) + +func TestMergeLogs(t *testing.T) { + lr1 := &logsRequest{ld: testdata.GenerateLogs(2)} + lr2 := &logsRequest{ld: testdata.GenerateLogs(3)} + res, err := mergeLogs(context.Background(), lr1, lr2) + assert.Nil(t, err) + assert.Equal(t, 5, res.(*logsRequest).ld.LogRecordCount()) +} + +func TestMergeLogsInvalidInput(t *testing.T) { + lr1 := &tracesRequest{td: testdata.GenerateTraces(2)} + lr2 := &logsRequest{ld: testdata.GenerateLogs(3)} + _, err := mergeLogs(context.Background(), lr1, lr2) + assert.Error(t, err) +} + +func TestMergeSplitLogs(t *testing.T) { + tests := []struct { + name string + cfg exporterbatcher.MaxSizeConfig + lr1 Request + lr2 Request + expected []*logsRequest + }{ + { + name: "both_requests_empty", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + lr1: &logsRequest{ld: plog.NewLogs()}, + lr2: &logsRequest{ld: plog.NewLogs()}, + expected: []*logsRequest{{ld: plog.NewLogs()}}, + }, + { + name: "both_requests_nil", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + lr1: nil, + lr2: nil, + expected: []*logsRequest{}, + }, + { + name: "first_request_empty", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + lr1: &logsRequest{ld: plog.NewLogs()}, + lr2: &logsRequest{ld: testdata.GenerateLogs(5)}, + expected: []*logsRequest{{ld: testdata.GenerateLogs(5)}}, + }, + { + name: "first_requests_nil", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + lr1: nil, + lr2: &logsRequest{ld: testdata.GenerateLogs(5)}, + expected: []*logsRequest{{ld: testdata.GenerateLogs(5)}}, + }, + { + name: "first_nil_second_empty", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + lr1: nil, + lr2: &logsRequest{ld: plog.NewLogs()}, + expected: []*logsRequest{{ld: plog.NewLogs()}}, + }, + { + name: "merge_only", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + lr1: &logsRequest{ld: testdata.GenerateLogs(4)}, + lr2: &logsRequest{ld: testdata.GenerateLogs(6)}, + expected: []*logsRequest{{ld: func() plog.Logs { + logs := testdata.GenerateLogs(4) + testdata.GenerateLogs(6).ResourceLogs().MoveAndAppendTo(logs.ResourceLogs()) + return logs + }()}}, + }, + { + name: "split_only", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 4}, + lr1: nil, + lr2: &logsRequest{ld: testdata.GenerateLogs(10)}, + expected: []*logsRequest{ + {ld: testdata.GenerateLogs(4)}, + {ld: testdata.GenerateLogs(4)}, + {ld: testdata.GenerateLogs(2)}, + }, + }, + { + name: "merge_and_split", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + lr1: &logsRequest{ld: testdata.GenerateLogs(8)}, + lr2: &logsRequest{ld: testdata.GenerateLogs(20)}, + expected: []*logsRequest{ + {ld: func() plog.Logs { + logs := testdata.GenerateLogs(8) + testdata.GenerateLogs(2).ResourceLogs().MoveAndAppendTo(logs.ResourceLogs()) + return logs + }()}, + {ld: testdata.GenerateLogs(10)}, + {ld: testdata.GenerateLogs(8)}, + }, + }, + { + name: "scope_logs_split", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 4}, + lr1: &logsRequest{ld: func() plog.Logs { + ld := testdata.GenerateLogs(4) + ld.ResourceLogs().At(0).ScopeLogs().AppendEmpty().LogRecords().AppendEmpty().Body().SetStr("extra log") + return ld + }()}, + lr2: &logsRequest{ld: testdata.GenerateLogs(2)}, + expected: []*logsRequest{ + {ld: testdata.GenerateLogs(4)}, + {ld: func() plog.Logs { + ld := testdata.GenerateLogs(0) + ld.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().AppendEmpty().Body().SetStr("extra log") + testdata.GenerateLogs(2).ResourceLogs().MoveAndAppendTo(ld.ResourceLogs()) + return ld + }()}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res, err := mergeSplitLogs(context.Background(), tt.cfg, tt.lr1, tt.lr2) + assert.Nil(t, err) + assert.Equal(t, len(tt.expected), len(res)) + for i, r := range res { + assert.Equal(t, tt.expected[i], r.(*logsRequest)) + } + }) + + } +} + +func TestMergeSplitLogsInvalidInput(t *testing.T) { + r1 := &tracesRequest{td: testdata.GenerateTraces(2)} + r2 := &logsRequest{ld: testdata.GenerateLogs(3)} + _, err := mergeSplitLogs(context.Background(), exporterbatcher.MaxSizeConfig{}, r1, r2) + assert.Error(t, err) +} + +func TestExtractLogs(t *testing.T) { + for i := 0; i < 10; i++ { + ld := testdata.GenerateLogs(10) + extractedLogs := extractLogs(ld, i) + assert.Equal(t, i, extractedLogs.LogRecordCount()) + assert.Equal(t, 10-i, ld.LogRecordCount()) + } +} diff --git a/exporter/exporterhelper/logs_test.go b/exporter/exporterhelper/logs_test.go index e42af577b2c..827a383e279 100644 --- a/exporter/exporterhelper/logs_test.go +++ b/exporter/exporterhelper/logs_test.go @@ -28,8 +28,8 @@ import ( "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/pdata/plog" + "go.opentelemetry.io/collector/pdata/testdata" ) const ( diff --git a/exporter/exporterhelper/metrics.go b/exporter/exporterhelper/metrics.go index ab7d65dae65..83db18229dd 100644 --- a/exporter/exporterhelper/metrics.go +++ b/exporter/exporterhelper/metrics.go @@ -82,12 +82,15 @@ func NewMetricsExporter( if pusher == nil { return nil, errNilPushMetricsData } - metricsOpts := []Option{withMarshaler(metricsRequestMarshaler), withUnmarshaler(newMetricsRequestUnmarshalerFunc(pusher))} + metricsOpts := []Option{ + withMarshaler(metricsRequestMarshaler), withUnmarshaler(newMetricsRequestUnmarshalerFunc(pusher)), + withBatchFuncs(mergeMetrics, mergeSplitMetrics), + } return NewMetricsRequestExporter(ctx, set, requestFromMetrics(pusher), append(metricsOpts, options...)...) } // RequestFromMetricsFunc converts pdata.Metrics into a user-defined request. -// This API is at the early stage of development and may change without backward compatibility +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type RequestFromMetricsFunc func(context.Context, pmetric.Metrics) (Request, error) @@ -99,7 +102,7 @@ func requestFromMetrics(pusher consumer.ConsumeMetricsFunc) RequestFromMetricsFu } // NewMetricsRequestExporter creates a new metrics exporter based on a custom MetricsConverter and RequestSender. -// This API is at the early stage of development and may change without backward compatibility +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. func NewMetricsRequestExporter( _ context.Context, diff --git a/exporter/exporterhelper/metrics_batch.go b/exporter/exporterhelper/metrics_batch.go new file mode 100644 index 00000000000..1a6448c8496 --- /dev/null +++ b/exporter/exporterhelper/metrics_batch.go @@ -0,0 +1,236 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterhelper // import "go.opentelemetry.io/collector/exporter/exporterhelper" + +import ( + "context" + "errors" + + "go.opentelemetry.io/collector/exporter/exporterbatcher" + "go.opentelemetry.io/collector/pdata/pmetric" +) + +// mergeMetrics merges two metrics requests into one. +func mergeMetrics(_ context.Context, r1 Request, r2 Request) (Request, error) { + mr1, ok1 := r1.(*metricsRequest) + mr2, ok2 := r2.(*metricsRequest) + if !ok1 || !ok2 { + return nil, errors.New("invalid input type") + } + mr2.md.ResourceMetrics().MoveAndAppendTo(mr1.md.ResourceMetrics()) + return mr1, nil +} + +// mergeSplitMetrics splits and/or merges the metrics into multiple requests based on the MaxSizeConfig. +func mergeSplitMetrics(_ context.Context, cfg exporterbatcher.MaxSizeConfig, r1 Request, r2 Request) ([]Request, error) { + var ( + res []Request + destReq *metricsRequest + capacityLeft = cfg.MaxSizeItems + ) + for _, req := range []Request{r1, r2} { + if req == nil { + continue + } + srcReq, ok := req.(*metricsRequest) + if !ok { + return nil, errors.New("invalid input type") + } + if srcReq.md.DataPointCount() <= capacityLeft { + if destReq == nil { + destReq = srcReq + } else { + srcReq.md.ResourceMetrics().MoveAndAppendTo(destReq.md.ResourceMetrics()) + } + capacityLeft -= destReq.md.DataPointCount() + continue + } + + for { + extractedMetrics := extractMetrics(srcReq.md, capacityLeft) + if extractedMetrics.DataPointCount() == 0 { + break + } + capacityLeft -= extractedMetrics.DataPointCount() + if destReq == nil { + destReq = &metricsRequest{md: extractedMetrics, pusher: srcReq.pusher} + } else { + extractedMetrics.ResourceMetrics().MoveAndAppendTo(destReq.md.ResourceMetrics()) + } + // Create new batch once capacity is reached. + if capacityLeft == 0 { + res = append(res, destReq) + destReq = nil + capacityLeft = cfg.MaxSizeItems + } + } + } + + if destReq != nil { + res = append(res, destReq) + } + + return res, nil +} + +// extractMetrics extracts metrics from srcMetrics until count of data points is reached. +func extractMetrics(srcMetrics pmetric.Metrics, count int) pmetric.Metrics { + destMetrics := pmetric.NewMetrics() + srcMetrics.ResourceMetrics().RemoveIf(func(srcRM pmetric.ResourceMetrics) bool { + if count == 0 { + return false + } + needToExtract := resourceDataPointsCount(srcRM) > count + if needToExtract { + srcRM = extractResourceMetrics(srcRM, count) + } + count -= resourceDataPointsCount(srcRM) + srcRM.MoveTo(destMetrics.ResourceMetrics().AppendEmpty()) + return !needToExtract + }) + return destMetrics +} + +// extractResourceMetrics extracts resource metrics and returns a new resource metrics with the specified number of data points. +func extractResourceMetrics(srcRM pmetric.ResourceMetrics, count int) pmetric.ResourceMetrics { + destRM := pmetric.NewResourceMetrics() + destRM.SetSchemaUrl(srcRM.SchemaUrl()) + srcRM.Resource().CopyTo(destRM.Resource()) + srcRM.ScopeMetrics().RemoveIf(func(srcSM pmetric.ScopeMetrics) bool { + if count == 0 { + return false + } + needToExtract := scopeDataPointsCount(srcSM) > count + if needToExtract { + srcSM = extractScopeMetrics(srcSM, count) + } + count -= scopeDataPointsCount(srcSM) + srcSM.MoveTo(destRM.ScopeMetrics().AppendEmpty()) + return !needToExtract + }) + return destRM +} + +// extractScopeMetrics extracts scope metrics and returns a new scope metrics with the specified number of data points. +func extractScopeMetrics(srcSM pmetric.ScopeMetrics, count int) pmetric.ScopeMetrics { + destSM := pmetric.NewScopeMetrics() + destSM.SetSchemaUrl(srcSM.SchemaUrl()) + srcSM.Scope().CopyTo(destSM.Scope()) + srcSM.Metrics().RemoveIf(func(srcMetric pmetric.Metric) bool { + if count == 0 { + return false + } + needToExtract := metricDataPointCount(srcMetric) > count + if needToExtract { + srcMetric = extractMetricDataPoints(srcMetric, count) + } + count -= metricDataPointCount(srcMetric) + srcMetric.MoveTo(destSM.Metrics().AppendEmpty()) + return !needToExtract + }) + return destSM +} + +func extractMetricDataPoints(srcMetric pmetric.Metric, count int) pmetric.Metric { + destMetric := pmetric.NewMetric() + switch srcMetric.Type() { + case pmetric.MetricTypeGauge: + extractGaugeDataPoints(srcMetric.Gauge(), count, destMetric.SetEmptyGauge()) + case pmetric.MetricTypeSum: + extractSumDataPoints(srcMetric.Sum(), count, destMetric.SetEmptySum()) + case pmetric.MetricTypeHistogram: + extractHistogramDataPoints(srcMetric.Histogram(), count, destMetric.SetEmptyHistogram()) + case pmetric.MetricTypeExponentialHistogram: + extractExponentialHistogramDataPoints(srcMetric.ExponentialHistogram(), count, + destMetric.SetEmptyExponentialHistogram()) + case pmetric.MetricTypeSummary: + extractSummaryDataPoints(srcMetric.Summary(), count, destMetric.SetEmptySummary()) + } + return destMetric +} + +func extractGaugeDataPoints(srcGauge pmetric.Gauge, count int, destGauge pmetric.Gauge) { + srcGauge.DataPoints().RemoveIf(func(srcDP pmetric.NumberDataPoint) bool { + if count == 0 { + return false + } + srcDP.MoveTo(destGauge.DataPoints().AppendEmpty()) + count-- + return true + }) +} + +func extractSumDataPoints(srcSum pmetric.Sum, count int, destSum pmetric.Sum) { + srcSum.DataPoints().RemoveIf(func(srcDP pmetric.NumberDataPoint) bool { + if count == 0 { + return false + } + srcDP.MoveTo(destSum.DataPoints().AppendEmpty()) + count-- + return true + }) +} + +func extractHistogramDataPoints(srcHistogram pmetric.Histogram, count int, destHistogram pmetric.Histogram) { + srcHistogram.DataPoints().RemoveIf(func(srcDP pmetric.HistogramDataPoint) bool { + if count == 0 { + return false + } + srcDP.MoveTo(destHistogram.DataPoints().AppendEmpty()) + count-- + return true + }) +} + +func extractExponentialHistogramDataPoints(srcExponentialHistogram pmetric.ExponentialHistogram, count int, destExponentialHistogram pmetric.ExponentialHistogram) { + srcExponentialHistogram.DataPoints().RemoveIf(func(srcDP pmetric.ExponentialHistogramDataPoint) bool { + if count == 0 { + return false + } + srcDP.MoveTo(destExponentialHistogram.DataPoints().AppendEmpty()) + count-- + return true + }) +} + +func extractSummaryDataPoints(srcSummary pmetric.Summary, count int, destSummary pmetric.Summary) { + srcSummary.DataPoints().RemoveIf(func(srcDP pmetric.SummaryDataPoint) bool { + if count == 0 { + return false + } + srcDP.MoveTo(destSummary.DataPoints().AppendEmpty()) + count-- + return true + }) +} + +func resourceDataPointsCount(rm pmetric.ResourceMetrics) (count int) { + for i := 0; i < rm.ScopeMetrics().Len(); i++ { + count += scopeDataPointsCount(rm.ScopeMetrics().At(i)) + } + return count +} + +func scopeDataPointsCount(sm pmetric.ScopeMetrics) (count int) { + for i := 0; i < sm.Metrics().Len(); i++ { + count += metricDataPointCount(sm.Metrics().At(i)) + } + return count +} + +func metricDataPointCount(m pmetric.Metric) int { + switch m.Type() { + case pmetric.MetricTypeGauge: + return m.Gauge().DataPoints().Len() + case pmetric.MetricTypeSum: + return m.Sum().DataPoints().Len() + case pmetric.MetricTypeHistogram: + return m.Histogram().DataPoints().Len() + case pmetric.MetricTypeExponentialHistogram: + return m.ExponentialHistogram().DataPoints().Len() + case pmetric.MetricTypeSummary: + return m.Summary().DataPoints().Len() + } + return 0 +} diff --git a/exporter/exporterhelper/metrics_batch_test.go b/exporter/exporterhelper/metrics_batch_test.go new file mode 100644 index 00000000000..9a5bc9815a9 --- /dev/null +++ b/exporter/exporterhelper/metrics_batch_test.go @@ -0,0 +1,166 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterhelper + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/exporter/exporterbatcher" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/testdata" +) + +func TestMergeMetrics(t *testing.T) { + mr1 := &metricsRequest{md: testdata.GenerateMetrics(2)} + mr2 := &metricsRequest{md: testdata.GenerateMetrics(3)} + res, err := mergeMetrics(context.Background(), mr1, mr2) + assert.Nil(t, err) + assert.Equal(t, 5, res.(*metricsRequest).md.MetricCount()) +} + +func TestMergeMetricsInvalidInput(t *testing.T) { + mr1 := &tracesRequest{td: testdata.GenerateTraces(2)} + mr2 := &metricsRequest{md: testdata.GenerateMetrics(3)} + _, err := mergeMetrics(context.Background(), mr1, mr2) + assert.Error(t, err) +} + +func TestMergeSplitMetrics(t *testing.T) { + tests := []struct { + name string + cfg exporterbatcher.MaxSizeConfig + mr1 Request + mr2 Request + expected []*metricsRequest + }{ + { + name: "both_requests_empty", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + mr1: &metricsRequest{md: pmetric.NewMetrics()}, + mr2: &metricsRequest{md: pmetric.NewMetrics()}, + expected: []*metricsRequest{{md: pmetric.NewMetrics()}}, + }, + { + name: "both_requests_nil", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + mr1: nil, + mr2: nil, + expected: []*metricsRequest{}, + }, + { + name: "first_request_empty", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + mr1: &metricsRequest{md: pmetric.NewMetrics()}, + mr2: &metricsRequest{md: testdata.GenerateMetrics(5)}, + expected: []*metricsRequest{{md: testdata.GenerateMetrics(5)}}, + }, + { + name: "first_requests_nil", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + mr1: nil, + mr2: &metricsRequest{md: testdata.GenerateMetrics(5)}, + expected: []*metricsRequest{{md: testdata.GenerateMetrics(5)}}, + }, + { + name: "first_nil_second_empty", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + mr1: nil, + mr2: &metricsRequest{md: pmetric.NewMetrics()}, + expected: []*metricsRequest{{md: pmetric.NewMetrics()}}, + }, + { + name: "merge_only", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 60}, + mr1: &metricsRequest{md: testdata.GenerateMetrics(10)}, + mr2: &metricsRequest{md: testdata.GenerateMetrics(14)}, + expected: []*metricsRequest{{md: func() pmetric.Metrics { + metrics := testdata.GenerateMetrics(10) + testdata.GenerateMetrics(14).ResourceMetrics().MoveAndAppendTo(metrics.ResourceMetrics()) + return metrics + }()}}, + }, + { + name: "split_only", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 14}, + mr1: nil, + mr2: &metricsRequest{md: testdata.GenerateMetrics(15)}, // 15 metrics, 30 data points + expected: []*metricsRequest{ + {md: testdata.GenerateMetrics(7)}, // 7 metrics, 14 data points + {md: testdata.GenerateMetrics(7)}, // 7 metrics, 14 data points + {md: testdata.GenerateMetrics(1)}, // 1 metric, 2 data points + }, + }, + { + name: "split_and_merge", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 28}, + mr1: &metricsRequest{md: testdata.GenerateMetrics(7)}, // 7 metrics, 14 data points + mr2: &metricsRequest{md: testdata.GenerateMetrics(25)}, // 25 metrics, 50 data points + expected: []*metricsRequest{ + {md: func() pmetric.Metrics { + metrics := testdata.GenerateMetrics(7) + testdata.GenerateMetrics(7).ResourceMetrics().MoveAndAppendTo(metrics.ResourceMetrics()) + return metrics + }()}, + {md: testdata.GenerateMetrics(14)}, // 14 metrics, 28 data points + {md: testdata.GenerateMetrics(4)}, // 4 metrics, 8 data points + }, + }, + { + name: "scope_metrics_split", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 8}, + mr1: &metricsRequest{md: func() pmetric.Metrics { + md := testdata.GenerateMetrics(4) + extraScopeMetrics := md.ResourceMetrics().At(0).ScopeMetrics().AppendEmpty() + testdata.GenerateMetrics(4).ResourceMetrics().At(0).ScopeMetrics().At(0).MoveTo(extraScopeMetrics) + extraScopeMetrics.Scope().SetName("extra scope") + return md + }()}, + mr2: nil, + expected: []*metricsRequest{ + {md: testdata.GenerateMetrics(4)}, + {md: func() pmetric.Metrics { + md := testdata.GenerateMetrics(4) + md.ResourceMetrics().At(0).ScopeMetrics().At(0).Scope().SetName("extra scope") + return md + }()}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res, err := mergeSplitMetrics(context.Background(), tt.cfg, tt.mr1, tt.mr2) + assert.Nil(t, err) + assert.Equal(t, len(tt.expected), len(res)) + for i := range res { + assert.Equal(t, tt.expected[i], res[i].(*metricsRequest)) + } + }) + } +} + +func TestMergeSplitMetricsInvalidInput(t *testing.T) { + r1 := &tracesRequest{td: testdata.GenerateTraces(2)} + r2 := &metricsRequest{md: testdata.GenerateMetrics(3)} + _, err := mergeSplitMetrics(context.Background(), exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, r1, r2) + assert.Error(t, err) +} + +func TestExtractMetrics(t *testing.T) { + for i := 0; i < 20; i++ { + md := testdata.GenerateMetrics(10) + extractedMetrics := extractMetrics(md, i) + assert.Equal(t, i, extractedMetrics.DataPointCount()) + assert.Equal(t, 20-i, md.DataPointCount()) + } +} + +func TestExtractMetricsInvalidMetric(t *testing.T) { + md := testdata.GenerateMetricsMetricTypeInvalid() + extractedMetrics := extractMetrics(md, 10) + assert.Equal(t, testdata.GenerateMetricsMetricTypeInvalid(), extractedMetrics) + assert.Equal(t, 0, md.ResourceMetrics().Len()) +} diff --git a/exporter/exporterhelper/metrics_test.go b/exporter/exporterhelper/metrics_test.go index ddbefeb71f2..6ae88c4feaf 100644 --- a/exporter/exporterhelper/metrics_test.go +++ b/exporter/exporterhelper/metrics_test.go @@ -28,8 +28,8 @@ import ( "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/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/testdata" ) const ( diff --git a/exporter/exporterhelper/obsexporter.go b/exporter/exporterhelper/obsexporter.go index f42c0195f49..ed490144242 100644 --- a/exporter/exporterhelper/obsexporter.go +++ b/exporter/exporterhelper/obsexporter.go @@ -20,7 +20,7 @@ import ( ) const ( - exporterScope = obsmetrics.Scope + obsmetrics.NameSep + obsmetrics.ExporterKey + exporterScope = obsmetrics.Scope + obsmetrics.SpanNameSep + obsmetrics.ExporterKey ) // ObsReport is a helper to add observability to an exporter. @@ -78,55 +78,55 @@ func (or *ObsReport) createOtelMetrics(cfg ObsReportSettings) error { var errors, err error or.sentSpans, err = meter.Int64Counter( - obsmetrics.ExporterPrefix+obsmetrics.SentSpansKey, + obsmetrics.ExporterMetricPrefix+obsmetrics.SentSpansKey, metric.WithDescription("Number of spans successfully sent to destination."), metric.WithUnit("1")) errors = multierr.Append(errors, err) or.failedToSendSpans, err = meter.Int64Counter( - obsmetrics.ExporterPrefix+obsmetrics.FailedToSendSpansKey, + obsmetrics.ExporterMetricPrefix+obsmetrics.FailedToSendSpansKey, metric.WithDescription("Number of spans in failed attempts to send to destination."), metric.WithUnit("1")) errors = multierr.Append(errors, err) or.failedToEnqueueSpans, err = meter.Int64Counter( - obsmetrics.ExporterPrefix+obsmetrics.FailedToEnqueueSpansKey, + obsmetrics.ExporterMetricPrefix+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, + obsmetrics.ExporterMetricPrefix+obsmetrics.SentMetricPointsKey, metric.WithDescription("Number of metric points successfully sent to destination."), metric.WithUnit("1")) errors = multierr.Append(errors, err) or.failedToSendMetricPoints, err = meter.Int64Counter( - obsmetrics.ExporterPrefix+obsmetrics.FailedToSendMetricPointsKey, + obsmetrics.ExporterMetricPrefix+obsmetrics.FailedToSendMetricPointsKey, metric.WithDescription("Number of metric points in failed attempts to send to destination."), metric.WithUnit("1")) errors = multierr.Append(errors, err) or.failedToEnqueueMetricPoints, err = meter.Int64Counter( - obsmetrics.ExporterPrefix+obsmetrics.FailedToEnqueueMetricPointsKey, + obsmetrics.ExporterMetricPrefix+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, + obsmetrics.ExporterMetricPrefix+obsmetrics.SentLogRecordsKey, metric.WithDescription("Number of log record successfully sent to destination."), metric.WithUnit("1")) errors = multierr.Append(errors, err) or.failedToSendLogRecords, err = meter.Int64Counter( - obsmetrics.ExporterPrefix+obsmetrics.FailedToSendLogRecordsKey, + obsmetrics.ExporterMetricPrefix+obsmetrics.FailedToSendLogRecordsKey, metric.WithDescription("Number of log records in failed attempts to send to destination."), metric.WithUnit("1")) errors = multierr.Append(errors, err) or.failedToEnqueueLogRecords, err = meter.Int64Counter( - obsmetrics.ExporterPrefix+obsmetrics.FailedToEnqueueLogRecordsKey, + obsmetrics.ExporterMetricPrefix+obsmetrics.FailedToEnqueueLogRecordsKey, metric.WithDescription("Number of log records failed to be added to the sending queue."), metric.WithUnit("1")) errors = multierr.Append(errors, err) diff --git a/exporter/exporterhelper/queue_sender.go b/exporter/exporterhelper/queue_sender.go index 3092c60c98f..3e539d7f9a0 100644 --- a/exporter/exporterhelper/queue_sender.go +++ b/exporter/exporterhelper/queue_sender.go @@ -31,7 +31,9 @@ var ( type QueueSettings struct { // Enabled indicates whether to not enqueue batches before sending to the consumerSender. Enabled bool `mapstructure:"enabled"` - // NumConsumers is the number of consumers from the queue. + // NumConsumers is the number of consumers from the queue. Defaults to 10. + // If batching is enabled, a combined batch cannot contain more requests than the number of consumers. + // So it's recommended to set higher number of consumers if batching is enabled. NumConsumers int `mapstructure:"num_consumers"` // QueueSize is the maximum number of batches allowed in queue at a given time. QueueSize int `mapstructure:"queue_size"` @@ -73,6 +75,7 @@ type queueSender struct { baseRequestSender fullName string queue exporterqueue.Queue[Request] + numConsumers int traceAttribute attribute.KeyValue logger *zap.Logger meter otelmetric.Meter @@ -87,6 +90,7 @@ func newQueueSender(q exporterqueue.Queue[Request], set exporter.CreateSettings, qs := &queueSender{ fullName: set.ID.String(), queue: q, + numConsumers: numConsumers, traceAttribute: attribute.String(obsmetrics.ExporterKey, set.ID.String()), logger: set.TelemetrySettings.Logger, meter: set.TelemetrySettings.MeterProvider.Meter(scopeName), diff --git a/exporter/exporterhelper/request.go b/exporter/exporterhelper/request.go index 03276f9c19e..fa6856d385a 100644 --- a/exporter/exporterhelper/request.go +++ b/exporter/exporterhelper/request.go @@ -8,7 +8,7 @@ import ( ) // Request represents a single request that can be sent to an external endpoint. -// This API is at the early stage of development and may change without backward compatibility +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type Request interface { // Export exports the request to an external endpoint. @@ -23,7 +23,7 @@ type Request interface { // 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 +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type RequestErrorHandler interface { Request @@ -33,10 +33,12 @@ type RequestErrorHandler interface { } // 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) // 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) diff --git a/exporter/exporterhelper/request_test.go b/exporter/exporterhelper/request_test.go index 18e8228f946..fe373c67e12 100644 --- a/exporter/exporterhelper/request_test.go +++ b/exporter/exporterhelper/request_test.go @@ -5,25 +5,117 @@ package exporterhelper import ( "context" + "sync/atomic" + "time" + "go.opentelemetry.io/collector/exporter/exporterbatcher" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/ptrace" ) +type fakeRequestSink struct { + requestsCount *atomic.Uint64 + itemsCount *atomic.Uint64 +} + +func newFakeRequestSink() *fakeRequestSink { + return &fakeRequestSink{ + requestsCount: &atomic.Uint64{}, + itemsCount: &atomic.Uint64{}, + } +} + type fakeRequest struct { - items int - err error + items int + exportErr error + mergeErr error + delay time.Duration + sink *fakeRequestSink } -func (r fakeRequest) Export(context.Context) error { - return r.err +func (r *fakeRequest) Export(ctx context.Context) error { + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(r.delay): + } + if r.exportErr != nil { + return r.exportErr + } + if r.sink != nil { + r.sink.requestsCount.Add(1) + r.sink.itemsCount.Add(uint64(r.items)) + } + return nil } -func (r fakeRequest) ItemsCount() int { +func (r *fakeRequest) ItemsCount() int { return r.items } +func fakeBatchMergeFunc(_ context.Context, r1 Request, r2 Request) (Request, error) { + if r1 == nil { + return r2, nil + } + fr1 := r1.(*fakeRequest) + fr2 := r2.(*fakeRequest) + if fr2.mergeErr != nil { + return nil, fr2.mergeErr + } + return &fakeRequest{ + items: fr1.items + fr2.items, + sink: fr1.sink, + exportErr: fr2.exportErr, + delay: fr1.delay + fr2.delay, + }, nil +} + +func fakeBatchMergeSplitFunc(ctx context.Context, cfg exporterbatcher.MaxSizeConfig, r1 Request, r2 Request) ([]Request, error) { + maxItems := cfg.MaxSizeItems + if maxItems == 0 { + r, err := fakeBatchMergeFunc(ctx, r1, r2) + return []Request{r}, err + } + + if r2.(*fakeRequest).mergeErr != nil { + return nil, r2.(*fakeRequest).mergeErr + } + + fr2 := r2.(*fakeRequest) + fr2 = &fakeRequest{items: fr2.items, sink: fr2.sink, exportErr: fr2.exportErr, delay: fr2.delay} + var res []Request + + // fill fr1 to maxItems if it's not nil + if r1 != nil { + fr1 := r1.(*fakeRequest) + fr1 = &fakeRequest{items: fr1.items, sink: fr1.sink, exportErr: fr1.exportErr, delay: fr1.delay} + if fr2.items <= maxItems-fr1.items { + fr1.items += fr2.items + if fr2.exportErr != nil { + fr1.exportErr = fr2.exportErr + } + return []Request{fr1}, nil + } + // if split is needed, we don't propagate exportErr from fr2 to fr1 to test more cases + fr2.items -= maxItems - fr1.items + fr1.items = maxItems + res = append(res, fr1) + } + + // split fr2 to maxItems + for { + if fr2.items <= maxItems { + res = append(res, &fakeRequest{items: fr2.items, sink: fr2.sink, exportErr: fr2.exportErr, delay: fr2.delay}) + break + } + res = append(res, &fakeRequest{items: maxItems, sink: fr2.sink, exportErr: fr2.exportErr, delay: fr2.delay}) + fr2.items -= maxItems + } + + return res, nil +} + type fakeRequestConverter struct { metricsError error tracesError error @@ -32,13 +124,13 @@ type fakeRequestConverter struct { } func (frc *fakeRequestConverter) requestFromMetricsFunc(_ context.Context, md pmetric.Metrics) (Request, error) { - return fakeRequest{items: md.DataPointCount(), err: frc.requestError}, frc.metricsError + return &fakeRequest{items: md.DataPointCount(), exportErr: frc.requestError}, frc.metricsError } func (frc *fakeRequestConverter) requestFromTracesFunc(_ context.Context, md ptrace.Traces) (Request, error) { - return fakeRequest{items: md.SpanCount(), err: frc.requestError}, frc.tracesError + return &fakeRequest{items: md.SpanCount(), exportErr: frc.requestError}, frc.tracesError } func (frc *fakeRequestConverter) requestFromLogsFunc(_ context.Context, md plog.Logs) (Request, error) { - return fakeRequest{items: md.LogRecordCount(), err: frc.requestError}, frc.logsError + return &fakeRequest{items: md.LogRecordCount(), exportErr: frc.requestError}, frc.logsError } diff --git a/exporter/exporterhelper/retry_sender_test.go b/exporter/exporterhelper/retry_sender_test.go index 96b4904f372..d3863097326 100644 --- a/exporter/exporterhelper/retry_sender_test.go +++ b/exporter/exporterhelper/retry_sender_test.go @@ -22,7 +22,7 @@ import ( "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/exporter/exporterqueue" "go.opentelemetry.io/collector/exporter/exportertest" - "go.opentelemetry.io/collector/internal/testdata" + "go.opentelemetry.io/collector/pdata/testdata" ) func mockRequestUnmarshaler(mr Request) exporterqueue.Unmarshaler[Request] { diff --git a/exporter/exporterhelper/traces.go b/exporter/exporterhelper/traces.go index 778c0d63989..6f5f39f3de5 100644 --- a/exporter/exporterhelper/traces.go +++ b/exporter/exporterhelper/traces.go @@ -82,12 +82,15 @@ func NewTracesExporter( if pusher == nil { return nil, errNilPushTraceData } - tracesOpts := []Option{withMarshaler(tracesRequestMarshaler), withUnmarshaler(newTraceRequestUnmarshalerFunc(pusher))} + tracesOpts := []Option{ + withMarshaler(tracesRequestMarshaler), withUnmarshaler(newTraceRequestUnmarshalerFunc(pusher)), + withBatchFuncs(mergeTraces, mergeSplitTraces), + } return NewTracesRequestExporter(ctx, set, requestFromTraces(pusher), append(tracesOpts, options...)...) } // RequestFromTracesFunc converts ptrace.Traces into a user-defined Request. -// This API is at the early stage of development and may change without backward compatibility +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type RequestFromTracesFunc func(context.Context, ptrace.Traces) (Request, error) @@ -99,7 +102,7 @@ func requestFromTraces(pusher consumer.ConsumeTracesFunc) RequestFromTracesFunc } // NewTracesRequestExporter creates a new traces exporter based on a custom TracesConverter and RequestSender. -// This API is at the early stage of development and may change without backward compatibility +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. func NewTracesRequestExporter( _ context.Context, diff --git a/exporter/exporterhelper/traces_batch.go b/exporter/exporterhelper/traces_batch.go new file mode 100644 index 00000000000..1bdada95b7b --- /dev/null +++ b/exporter/exporterhelper/traces_batch.go @@ -0,0 +1,139 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterhelper // import "go.opentelemetry.io/collector/exporter/exporterhelper" + +import ( + "context" + "errors" + + "go.opentelemetry.io/collector/exporter/exporterbatcher" + "go.opentelemetry.io/collector/pdata/ptrace" +) + +// mergeTraces merges two traces requests into one. +func mergeTraces(_ context.Context, r1 Request, r2 Request) (Request, error) { + tr1, ok1 := r1.(*tracesRequest) + tr2, ok2 := r2.(*tracesRequest) + if !ok1 || !ok2 { + return nil, errors.New("invalid input type") + } + tr2.td.ResourceSpans().MoveAndAppendTo(tr1.td.ResourceSpans()) + return tr1, nil +} + +// mergeSplitTraces splits and/or merges the traces into multiple requests based on the MaxSizeConfig. +func mergeSplitTraces(_ context.Context, cfg exporterbatcher.MaxSizeConfig, r1 Request, r2 Request) ([]Request, error) { + var ( + res []Request + destReq *tracesRequest + capacityLeft = cfg.MaxSizeItems + ) + for _, req := range []Request{r1, r2} { + if req == nil { + continue + } + srcReq, ok := req.(*tracesRequest) + if !ok { + return nil, errors.New("invalid input type") + } + if srcReq.td.SpanCount() <= capacityLeft { + if destReq == nil { + destReq = srcReq + } else { + srcReq.td.ResourceSpans().MoveAndAppendTo(destReq.td.ResourceSpans()) + } + capacityLeft -= destReq.td.SpanCount() + continue + } + + for { + extractedTraces := extractTraces(srcReq.td, capacityLeft) + if extractedTraces.SpanCount() == 0 { + break + } + capacityLeft -= extractedTraces.SpanCount() + if destReq == nil { + destReq = &tracesRequest{td: extractedTraces, pusher: srcReq.pusher} + } else { + extractedTraces.ResourceSpans().MoveAndAppendTo(destReq.td.ResourceSpans()) + } + // Create new batch once capacity is reached. + if capacityLeft == 0 { + res = append(res, destReq) + destReq = nil + capacityLeft = cfg.MaxSizeItems + } + } + } + + if destReq != nil { + res = append(res, destReq) + } + return res, nil +} + +// extractTraces extracts a new traces with a maximum number of spans. +func extractTraces(srcTraces ptrace.Traces, count int) ptrace.Traces { + destTraces := ptrace.NewTraces() + srcTraces.ResourceSpans().RemoveIf(func(srcRS ptrace.ResourceSpans) bool { + if count == 0 { + return false + } + needToExtract := resourceTracesCount(srcRS) > count + if needToExtract { + srcRS = extractResourceSpans(srcRS, count) + } + count -= resourceTracesCount(srcRS) + srcRS.MoveTo(destTraces.ResourceSpans().AppendEmpty()) + return !needToExtract + }) + return destTraces +} + +// extractResourceSpans extracts spans and returns a new resource spans with the specified number of spans. +func extractResourceSpans(srcRS ptrace.ResourceSpans, count int) ptrace.ResourceSpans { + destRS := ptrace.NewResourceSpans() + destRS.SetSchemaUrl(srcRS.SchemaUrl()) + srcRS.Resource().CopyTo(destRS.Resource()) + srcRS.ScopeSpans().RemoveIf(func(srcSS ptrace.ScopeSpans) bool { + if count == 0 { + return false + } + needToExtract := srcSS.Spans().Len() > count + if needToExtract { + srcSS = extractScopeSpans(srcSS, count) + } + count -= srcSS.Spans().Len() + srcSS.MoveTo(destRS.ScopeSpans().AppendEmpty()) + return !needToExtract + }) + srcRS.Resource().CopyTo(destRS.Resource()) + return destRS +} + +// extractScopeSpans extracts spans and returns a new scope spans with the specified number of spans. +func extractScopeSpans(srcSS ptrace.ScopeSpans, count int) ptrace.ScopeSpans { + destSS := ptrace.NewScopeSpans() + destSS.SetSchemaUrl(srcSS.SchemaUrl()) + srcSS.Scope().CopyTo(destSS.Scope()) + srcSS.Spans().RemoveIf(func(srcSpan ptrace.Span) bool { + if count == 0 { + return false + } + srcSpan.MoveTo(destSS.Spans().AppendEmpty()) + count-- + return true + }) + return destSS +} + +// resourceTracesCount calculates the total number of spans in the pdata.ResourceSpans. +func resourceTracesCount(rs ptrace.ResourceSpans) int { + count := 0 + rs.ScopeSpans().RemoveIf(func(ss ptrace.ScopeSpans) bool { + count += ss.Spans().Len() + return false + }) + return count +} diff --git a/exporter/exporterhelper/traces_batch_test.go b/exporter/exporterhelper/traces_batch_test.go new file mode 100644 index 00000000000..5779b731b63 --- /dev/null +++ b/exporter/exporterhelper/traces_batch_test.go @@ -0,0 +1,159 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exporterhelper + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/collector/exporter/exporterbatcher" + "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/collector/pdata/testdata" +) + +func TestMergeTraces(t *testing.T) { + tr1 := &tracesRequest{td: testdata.GenerateTraces(2)} + tr2 := &tracesRequest{td: testdata.GenerateTraces(3)} + res, err := mergeTraces(context.Background(), tr1, tr2) + assert.Nil(t, err) + assert.Equal(t, 5, res.(*tracesRequest).td.SpanCount()) +} + +func TestMergeTracesInvalidInput(t *testing.T) { + tr1 := &logsRequest{ld: testdata.GenerateLogs(2)} + tr2 := &tracesRequest{td: testdata.GenerateTraces(3)} + _, err := mergeTraces(context.Background(), tr1, tr2) + assert.Error(t, err) +} + +func TestMergeSplitTraces(t *testing.T) { + tests := []struct { + name string + cfg exporterbatcher.MaxSizeConfig + tr1 Request + tr2 Request + expected []*tracesRequest + }{ + { + name: "both_requests_empty", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + tr1: &tracesRequest{td: ptrace.NewTraces()}, + tr2: &tracesRequest{td: ptrace.NewTraces()}, + expected: []*tracesRequest{{td: ptrace.NewTraces()}}, + }, + { + name: "both_requests_nil", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + tr1: nil, + tr2: nil, + expected: []*tracesRequest{}, + }, + { + name: "first_request_empty", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + tr1: &tracesRequest{td: ptrace.NewTraces()}, + tr2: &tracesRequest{td: testdata.GenerateTraces(5)}, + expected: []*tracesRequest{{td: testdata.GenerateTraces(5)}}, + }, + { + name: "second_request_empty", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + tr1: &tracesRequest{td: testdata.GenerateTraces(5)}, + tr2: &tracesRequest{td: ptrace.NewTraces()}, + expected: []*tracesRequest{{td: testdata.GenerateTraces(5)}}, + }, + { + name: "first_nil_second_empty", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + tr1: nil, + tr2: &tracesRequest{td: ptrace.NewTraces()}, + expected: []*tracesRequest{{td: ptrace.NewTraces()}}, + }, + { + name: "merge_only", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + tr1: &tracesRequest{td: testdata.GenerateTraces(5)}, + tr2: &tracesRequest{td: testdata.GenerateTraces(5)}, + expected: []*tracesRequest{{td: func() ptrace.Traces { + td := testdata.GenerateTraces(5) + testdata.GenerateTraces(5).ResourceSpans().MoveAndAppendTo(td.ResourceSpans()) + return td + }()}}, + }, + { + name: "split_only", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 4}, + tr1: nil, + tr2: &tracesRequest{td: testdata.GenerateTraces(10)}, + expected: []*tracesRequest{ + {td: testdata.GenerateTraces(4)}, + {td: testdata.GenerateTraces(4)}, + {td: testdata.GenerateTraces(2)}, + }, + }, + { + name: "split_and_merge", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + tr1: &tracesRequest{td: testdata.GenerateTraces(4)}, + tr2: &tracesRequest{td: testdata.GenerateTraces(20)}, + expected: []*tracesRequest{ + {td: func() ptrace.Traces { + td := testdata.GenerateTraces(4) + testdata.GenerateTraces(6).ResourceSpans().MoveAndAppendTo(td.ResourceSpans()) + return td + }()}, + {td: testdata.GenerateTraces(10)}, + {td: testdata.GenerateTraces(4)}, + }, + }, + { + name: "scope_spans_split", + cfg: exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, + tr1: &tracesRequest{td: func() ptrace.Traces { + td := testdata.GenerateTraces(10) + extraScopeTraces := testdata.GenerateTraces(5) + extraScopeTraces.ResourceSpans().At(0).ScopeSpans().At(0).Scope().SetName("extra scope") + extraScopeTraces.ResourceSpans().MoveAndAppendTo(td.ResourceSpans()) + return td + }()}, + tr2: nil, + expected: []*tracesRequest{ + {td: testdata.GenerateTraces(10)}, + {td: func() ptrace.Traces { + td := testdata.GenerateTraces(5) + td.ResourceSpans().At(0).ScopeSpans().At(0).Scope().SetName("extra scope") + return td + }()}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res, err := mergeSplitTraces(context.Background(), tt.cfg, tt.tr1, tt.tr2) + assert.Nil(t, err) + assert.Equal(t, len(tt.expected), len(res)) + for i := range res { + assert.Equal(t, tt.expected[i], res[i].(*tracesRequest)) + } + }) + } +} + +func TestMergeSplitTracesInvalidInput(t *testing.T) { + r1 := &tracesRequest{td: testdata.GenerateTraces(2)} + r2 := &metricsRequest{md: testdata.GenerateMetrics(3)} + _, err := mergeSplitTraces(context.Background(), exporterbatcher.MaxSizeConfig{MaxSizeItems: 10}, r1, r2) + assert.Error(t, err) +} + +func TestExtractTraces(t *testing.T) { + for i := 0; i < 10; i++ { + td := testdata.GenerateTraces(10) + extractedTraces := extractTraces(td, i) + assert.Equal(t, i, extractedTraces.SpanCount()) + assert.Equal(t, 10-i, td.SpanCount()) + } +} diff --git a/exporter/exporterhelper/traces_test.go b/exporter/exporterhelper/traces_test.go index 0c8bec25f5f..42810bc8bb1 100644 --- a/exporter/exporterhelper/traces_test.go +++ b/exporter/exporterhelper/traces_test.go @@ -28,8 +28,8 @@ import ( "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/pdata/ptrace" + "go.opentelemetry.io/collector/pdata/testdata" ) const ( diff --git a/exporter/exporterqueue/config.go b/exporter/exporterqueue/config.go index ac888a0c227..fcc0e0e57b1 100644 --- a/exporter/exporterqueue/config.go +++ b/exporter/exporterqueue/config.go @@ -11,7 +11,7 @@ import ( // 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 +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type Config struct { // Enabled indicates whether to not enqueue batches before exporting. @@ -23,7 +23,7 @@ type Config struct { } // NewDefaultConfig returns the default Config. -// This API is at the early stage of development and may change without backward compatibility +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. func NewDefaultConfig() Config { return Config{ @@ -51,7 +51,7 @@ func (qCfg *Config) Validate() error { // 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 +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type PersistentQueueConfig struct { Config `mapstructure:",squash"` diff --git a/exporter/exporterqueue/queue.go b/exporter/exporterqueue/queue.go index 556dce9f9c2..5b568851b66 100644 --- a/exporter/exporterqueue/queue.go +++ b/exporter/exporterqueue/queue.go @@ -11,9 +11,14 @@ import ( "go.opentelemetry.io/collector/exporter/internal/queue" ) +// ErrQueueIsFull is the error that Queue returns when full. +// Experimental: This API is at the early stage of development and may change without backward compatibility +// until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. +var ErrQueueIsFull = queue.ErrQueueIsFull + // 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 +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type Queue[T any] queue.Queue[T] @@ -24,22 +29,22 @@ type Settings struct { } // 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 +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type 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 +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type 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 +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type Factory[T any] func(context.Context, Settings, Config) Queue[T] // 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 +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. func NewMemoryQueueFactory[T itemsCounter]() Factory[T] { return func(_ context.Context, _ Settings, cfg Config) Queue[T] { @@ -51,7 +56,7 @@ func NewMemoryQueueFactory[T itemsCounter]() Factory[T] { } // PersistentQueueSettings defines developer settings for the persistent queue factory. -// This API is at the early stage of development and may change without backward compatibility +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. type PersistentQueueSettings[T any] struct { // Marshaler is used to serialize queue elements before storing them in the persistent storage. @@ -62,7 +67,7 @@ type PersistentQueueSettings[T any] struct { // 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 +// Experimental: This API is at the early stage of development and may change without backward compatibility // until https://github.com/open-telemetry/opentelemetry-collector/issues/8122 is resolved. func NewPersistentQueueFactory[T itemsCounter](storageID *component.ID, factorySettings PersistentQueueSettings[T]) Factory[T] { if storageID == nil { @@ -90,7 +95,7 @@ func sizerFromConfig[T itemsCounter](Config) queue.Sizer[T] { return &queue.RequestSizer[T]{} } -func capacityFromConfig(cfg Config) int { +func capacityFromConfig(cfg Config) int64 { // TODO: Handle other ways to measure the queue size once they are added. - return cfg.QueueSize + return int64(cfg.QueueSize) } diff --git a/exporter/exportertest/nop_exporter.go b/exporter/exportertest/nop_exporter.go index e7e9f350331..6589d867bec 100644 --- a/exporter/exportertest/nop_exporter.go +++ b/exporter/exportertest/nop_exporter.go @@ -6,6 +6,8 @@ package exportertest // import "go.opentelemetry.io/collector/exporter/exportert import ( "context" + "github.com/google/uuid" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/consumer/consumertest" @@ -17,7 +19,7 @@ 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), + ID: component.NewIDWithName(nopType, uuid.NewString()), TelemetrySettings: componenttest.NewNopTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo(), } diff --git a/exporter/go.mod b/exporter/go.mod index e353c8a8bd8..47b4d59cfe9 100644 --- a/exporter/go.mod +++ b/exporter/go.mod @@ -3,25 +3,27 @@ module go.opentelemetry.io/collector/exporter go 1.21 require ( - github.com/cenkalti/backoff/v4 v4.2.1 - 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/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 + github.com/cenkalti/backoff/v4 v4.3.0 + github.com/google/uuid v1.6.0 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/config/configretry v0.100.0 + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/extension v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/collector/pdata/testdata v0.100.0 + go.opentelemetry.io/collector/receiver v0.100.0 + go.opentelemetry.io/otel v1.26.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/sdk v1.26.0 + go.opentelemetry.io/otel/trace v1.26.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 - golang.org/x/sys v0.17.0 - google.golang.org/grpc v1.62.0 + golang.org/x/sys v0.19.0 + google.golang.org/grpc v1.63.2 ) require ( @@ -32,27 +34,26 @@ require ( 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/knadh/koanf/v2 v2.1.1 // 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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 + go.opentelemetry.io/collector/confmap v0.100.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + golang.org/x/net v0.24.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -70,6 +71,8 @@ replace go.opentelemetry.io/collector/featuregate => ../featuregate replace go.opentelemetry.io/collector/pdata => ../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../pdata/testdata + replace go.opentelemetry.io/collector/receiver => ../receiver retract v0.76.0 // Depends on retracted pdata v1.0.0-rc10 module diff --git a/exporter/go.sum b/exporter/go.sum index dbdb92fd3bb..7bbf6704ff6 100644 --- a/exporter/go.sum +++ b/exporter/go.sum @@ -1,7 +1,7 @@ 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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -16,13 +16,11 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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/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= @@ -31,8 +29,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -50,32 +48,32 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.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.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -91,16 +89,16 @@ 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -113,14 +111,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/exporter/internal/common/logging_exporter.go b/exporter/internal/common/logging_exporter.go index 026018465f4..1d34f1f5620 100644 --- a/exporter/internal/common/logging_exporter.go +++ b/exporter/internal/common/logging_exporter.go @@ -1,6 +1,10 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +// NOTE: If you are making changes to this file, consider whether you want to make similar changes +// to the Debug exporter in /exporter/debugexporter/exporter.go, which has similar logic. +// This is especially important for security issues. + package common // import "go.opentelemetry.io/collector/exporter/internal/common" import ( diff --git a/exporter/internal/common/logging_exporter_test.go b/exporter/internal/common/logging_exporter_test.go index e087b52cd1a..763f649daba 100644 --- a/exporter/internal/common/logging_exporter_test.go +++ b/exporter/internal/common/logging_exporter_test.go @@ -13,10 +13,10 @@ import ( "go.opentelemetry.io/collector/config/configtelemetry" "go.opentelemetry.io/collector/exporter/exportertest" - "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/collector/pdata/testdata" ) func TestLoggingTracesExporterNoErrors(t *testing.T) { diff --git a/exporter/internal/otlptext/logs_test.go b/exporter/internal/otlptext/logs_test.go index 1055c30d2d2..a1d15676d1a 100644 --- a/exporter/internal/otlptext/logs_test.go +++ b/exporter/internal/otlptext/logs_test.go @@ -13,9 +13,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/testdata" ) func TestLogsText(t *testing.T) { diff --git a/exporter/internal/otlptext/metrics_test.go b/exporter/internal/otlptext/metrics_test.go index 989b65b399e..b2772b17953 100644 --- a/exporter/internal/otlptext/metrics_test.go +++ b/exporter/internal/otlptext/metrics_test.go @@ -12,8 +12,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/testdata" ) func TestMetricsText(t *testing.T) { diff --git a/exporter/internal/otlptext/traces_test.go b/exporter/internal/otlptext/traces_test.go index f3a7fdad6ab..2c4b69280a1 100644 --- a/exporter/internal/otlptext/traces_test.go +++ b/exporter/internal/otlptext/traces_test.go @@ -12,8 +12,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/collector/pdata/testdata" ) func TestTracesText(t *testing.T) { diff --git a/exporter/internal/queue/bounded_memory_queue.go b/exporter/internal/queue/bounded_memory_queue.go index 9f85e8496bf..98e1b281176 100644 --- a/exporter/internal/queue/bounded_memory_queue.go +++ b/exporter/internal/queue/bounded_memory_queue.go @@ -16,43 +16,38 @@ import ( // the producer are dropped. type boundedMemoryQueue[T any] struct { component.StartFunc - *queueCapacityLimiter[T] - items chan queueRequest[T] + *sizedChannel[memQueueEl[T]] + sizer Sizer[T] } // MemoryQueueSettings defines internal parameters for boundedMemoryQueue creation. type MemoryQueueSettings[T any] struct { Sizer Sizer[T] - Capacity int + Capacity int64 } // 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), + sizedChannel: newSizedChannel[memQueueEl[T]](set.Capacity, nil, 0), + sizer: set.Sizer, } } // 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 + return q.sizedChannel.push(memQueueEl[T]{ctx: ctx, req: req}, q.sizer.Sizeof(req), 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 + item, ok := q.sizedChannel.pop(func(el memQueueEl[T]) int64 { return q.sizer.Sizeof(el.req) }) if !ok { return false } - q.queueCapacityLimiter.release(item.req) // the memory queue doesn't handle consume errors _ = consumeFunc(item.ctx, item.req) return true @@ -60,11 +55,11 @@ func (q *boundedMemoryQueue[T]) Consume(consumeFunc func(context.Context, T) err // Shutdown closes the queue channel to initiate draining of the queue. func (q *boundedMemoryQueue[T]) Shutdown(context.Context) error { - close(q.items) + q.sizedChannel.shutdown() return nil } -type queueRequest[T any] struct { +type memQueueEl[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 index d861893eda9..ae98dca41f1 100644 --- a/exporter/internal/queue/bounded_memory_queue_test.go +++ b/exporter/internal/queue/bounded_memory_queue_test.go @@ -133,7 +133,7 @@ func benchmarkQueueUsage(b *testing.B, sizer Sizer[fakeReq], requestsCount int) 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}) + q := NewBoundedMemoryQueue[fakeReq](MemoryQueueSettings[fakeReq]{Sizer: sizer, Capacity: int64(10 * requestsCount)}) consumers := NewQueueConsumers(q, 1, func(context.Context, fakeReq) error { wg.Done() return nil @@ -156,3 +156,11 @@ func TestZeroSizeNoConsumers(t *testing.T) { assert.NoError(t, q.Shutdown(context.Background())) } + +type fakeReq struct { + itemsCount int +} + +func (r fakeReq) ItemsCount() int { + return r.itemsCount +} diff --git a/exporter/internal/queue/persistent_queue.go b/exporter/internal/queue/persistent_queue.go index b6e5d2be4dd..07b0d1fb628 100644 --- a/exporter/internal/queue/persistent_queue.go +++ b/exporter/internal/queue/persistent_queue.go @@ -10,7 +10,6 @@ import ( "fmt" "strconv" "sync" - "sync/atomic" "go.uber.org/multierr" "go.uber.org/zap" @@ -44,7 +43,10 @@ import ( // index index x // xxxx deleted type persistentQueue[T any] struct { - *queueCapacityLimiter[T] + // sizedChannel is used by the persistent queue for two purposes: + // 1. a communication channel notifying the consumer that a new item is available. + // 2. capacity control based on the size of the items. + *sizedChannel[permanentQueueEl] set PersistentQueueSettings[T] logger *zap.Logger @@ -53,14 +55,10 @@ type persistentQueue[T any] struct { // 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 @@ -86,7 +84,7 @@ var ( type PersistentQueueSettings[T any] struct { Sizer Sizer[T] - Capacity int + Capacity int64 DataType component.DataType StorageID component.ID Marshaler func(req T) ([]byte, error) @@ -98,12 +96,9 @@ type PersistentQueueSettings[T any] struct { 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), + set: set, + logger: set.ExporterSettings.Logger, + isRequestSized: isRequestSized, } } @@ -148,39 +143,49 @@ func (pq *persistentQueue[T]) initPersistentContiguousStorage(ctx context.Contex 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{}{} - } + initIndexSize := pq.writeIndex - pq.readIndex + + var ( + initEls []permanentQueueEl + initQueueSize uint64 + ) - // 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 { + // Pre-allocate the communication channel with the size of the restored queue. + if initIndexSize > 0 { + initQueueSize = initIndexSize // 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 + if !pq.isRequestSized { + if restoredQueueSize, err := pq.restoreQueueSizeFromStorage(ctx); err == nil { + initQueueSize = restoredQueueSize + } } - 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)) - } + // Ensure the communication channel filled with evenly sized elements up to the total restored queue size. + initEls = make([]permanentQueueEl, initIndexSize) + } + + pq.sizedChannel = newSizedChannel[permanentQueueEl](pq.set.Capacity, initEls, int64(initQueueSize)) +} + +// permanentQueueEl is the type of the elements passed to the sizedChannel by the persistentQueue. +type permanentQueueEl struct{} + +// restoreQueueSizeFromStorage restores the queue size from storage. +func (pq *persistentQueue[T]) restoreQueueSizeFromStorage(ctx context.Context) (uint64, error) { + val, err := pq.client.Get(ctx, queueSizeKey) + 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)) } + return 0, err } + return bytesToItemIndex(val) } // Consume applies the provided function on the head of queue. @@ -188,14 +193,24 @@ func (pq *persistentQueue[T]) initPersistentContiguousStorage(ctx context.Contex // 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 { + var ( + req T + onProcessingFinished func(error) + consumed bool + ) + // 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 + _, ok := pq.sizedChannel.pop(func(permanentQueueEl) int64 { + req, onProcessingFinished, consumed = pq.getNextItem(context.Background()) + if !consumed { + return 0 + } + return pq.set.Sizer.Sizeof(req) + }) if !ok { return false } - - req, onProcessingFinished, consumed := pq.getNextItem(context.Background()) if consumed { onProcessingFinished(consumeFunc(context.Background(), req)) return true @@ -203,31 +218,24 @@ func (pq *persistentQueue[T]) Consume(consumeFunc func(context.Context, T) error } } -// 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) + // If the queue is not initialized, there is nothing to shut down. + if pq.client == nil { + return nil + } + pq.mu.Lock() defer pq.mu.Unlock() + backupErr := pq.backupQueueSize(ctx) + pq.sizedChannel.shutdown() // 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), - ) + return multierr.Combine(backupErr, 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 { @@ -258,34 +266,31 @@ func (pq *persistentQueue[T]) Offer(ctx context.Context, req T) error { // 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 - } + err := pq.sizedChannel.push(permanentQueueEl{}, pq.set.Sizer.Sizeof(req), func() error { + itemKey := getItemKey(pq.writeIndex) + newIndex := pq.writeIndex + 1 + + reqBuf, err := pq.set.Marshaler(req) + if err != nil { + return err + } - itemKey := getItemKey(pq.writeIndex) - newIndex := pq.writeIndex + 1 + // 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 { + return storageErr + } - reqBuf, err := pq.set.Marshaler(req) + pq.writeIndex = newIndex + return nil + }) 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 { @@ -337,16 +342,6 @@ func (pq *persistentQueue[T]) getNextItem(ctx context.Context) (T, func(error), 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++ @@ -371,29 +366,18 @@ func (pq *persistentQueue[T]) getNextItem(ctx context.Context) (T, func(error), 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 + // 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.readIndex % 10) == 0 { + if qsErr := pq.backupQueueSize(ctx); qsErr != nil { + pq.logger.Error("Error writing queue size to storage", zap.Error(err)) + } } - pq.initQueueSize.Add(^(reqSize - 1)) - return - } - // Otherwise, decrease the current queue size. - pq.queueCapacityLimiter.release(req) + // Ensure the used size and the channel size are in sync. + pq.sizedChannel.syncSize() + + }, true } // retrieveAndEnqueueNotDispatchedReqs gets the items for which sending was not finished, cleans the storage diff --git a/exporter/internal/queue/persistent_queue_test.go b/exporter/internal/queue/persistent_queue_test.go index 2b525fa792f..6385088d5b1 100644 --- a/exporter/internal/queue/persistent_queue_test.go +++ b/exporter/internal/queue/persistent_queue_test.go @@ -54,7 +54,7 @@ func (nh *mockHost) GetExtensions() map[component.ID]component.Component { } // 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, +func createAndStartTestPersistentQueue(t *testing.T, sizer Sizer[tracesRequest], capacity int64, numConsumers int, consumeFunc func(_ context.Context, item tracesRequest) error) Queue[tracesRequest] { pq := NewPersistentQueue[tracesRequest](PersistentQueueSettings[tracesRequest]{ Sizer: sizer, @@ -90,16 +90,16 @@ func createTestPersistentQueueWithClient(client storage.Client) *persistentQueue return pq } -func createTestPersistentQueueWithRequestsCapacity(t testing.TB, ext storage.Extension, capacity int) *persistentQueue[tracesRequest] { +func createTestPersistentQueueWithRequestsCapacity(t testing.TB, ext storage.Extension, capacity int64) *persistentQueue[tracesRequest] { return createTestPersistentQueueWithCapacityLimiter(t, ext, &RequestSizer[tracesRequest]{}, capacity) } -func createTestPersistentQueueWithItemsCapacity(t testing.TB, ext storage.Extension, capacity int) *persistentQueue[tracesRequest] { +func createTestPersistentQueueWithItemsCapacity(t testing.TB, ext storage.Extension, capacity int64) *persistentQueue[tracesRequest] { return createTestPersistentQueueWithCapacityLimiter(t, ext, &ItemsSizer[tracesRequest]{}, capacity) } func createTestPersistentQueueWithCapacityLimiter(t testing.TB, ext storage.Extension, sizer Sizer[tracesRequest], - capacity int) *persistentQueue[tracesRequest] { + capacity int64) *persistentQueue[tracesRequest] { pq := NewPersistentQueue[tracesRequest](PersistentQueueSettings[tracesRequest]{ Sizer: sizer, Capacity: capacity, @@ -117,7 +117,7 @@ func TestPersistentQueue_FullCapacity(t *testing.T) { tests := []struct { name string sizer Sizer[tracesRequest] - capacity int + capacity int64 sizeMultiplier int }{ { @@ -518,8 +518,6 @@ func TestPersistentQueueStartWithNonDispatched(t *testing.T) { 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)) @@ -847,34 +845,132 @@ func TestPersistentQueue_ItemsCapacityUsageIsNotPreserved(t *testing.T) { 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()) + // The queue items size cannot be restored, fall back to request-based size + assert.Equal(t, 2, newPQ.Size()) assert.NoError(t, newPQ.Offer(context.Background(), newTracesRequest(2, 5))) - // Only new items are reflected - assert.Equal(t, 10, newPQ.Size()) + // Only new items are correctly reflected + assert.Equal(t, 12, newPQ.Size()) - // Consuming old items should does not affect the size. + // Consuming a restored request should reduce the restored size by 20 but it should not go to below zero 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.Equal(t, 0, newPQ.Size()) + // Consuming another restored request should not affect the restored size since it's already dropped to 0. 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.Equal(t, 0, newPQ.Size()) + + // Adding another batch should update the size accordingly + assert.NoError(t, newPQ.Offer(context.Background(), newTracesRequest(5, 5))) + assert.Equal(t, 25, 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, 15, newPQ.Size()) + + assert.NoError(t, newPQ.Shutdown(context.Background())) +} + +// This test covers the case when the queue is restarted with the less capacity than needed to restore the queued items. +// In that case, the queue has to be restored anyway even if it exceeds the capacity limit. +func TestPersistentQueue_RequestCapacityLessAfterRestart(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.NoError(t, pq.Offer(context.Background(), newTracesRequest(1, 5))) + + // Read the first request just to populate the read index in the storage. + // Otherwise, the write index won't be restored either. + assert.True(t, pq.Consume(func(_ context.Context, traces tracesRequest) error { + assert.Equal(t, 40, traces.traces.SpanCount()) + return nil + })) + assert.Equal(t, 3, pq.Size()) + + assert.NoError(t, pq.Shutdown(context.Background())) + + // The queue is restarted with the less capacity than needed to restore the queued items, but with the same + // underlying storage. No need to drop requests that are over capacity since they are already in the storage. + newPQ := createTestPersistentQueueWithRequestsCapacity(t, ext, 2) + + // The queue items size cannot be restored, fall back to request-based size + assert.Equal(t, 3, newPQ.Size()) + + // Queue is full + assert.Error(t, newPQ.Offer(context.Background(), newTracesRequest(2, 5))) + + assert.True(t, newPQ.Consume(func(_ context.Context, traces tracesRequest) error { + assert.Equal(t, 20, traces.traces.SpanCount()) + return nil + })) + assert.Equal(t, 2, newPQ.Size()) + + // Still full + assert.Error(t, newPQ.Offer(context.Background(), newTracesRequest(2, 5))) + + assert.True(t, newPQ.Consume(func(_ context.Context, traces tracesRequest) error { + assert.Equal(t, 25, traces.traces.SpanCount()) + return nil + })) + assert.Equal(t, 1, newPQ.Size()) + + // Now it can accept new items + assert.NoError(t, newPQ.Offer(context.Background(), newTracesRequest(2, 5))) + + assert.NoError(t, newPQ.Shutdown(context.Background())) +} + +// This test covers the case when the persistent storage is recovered from a snapshot which has +// bigger value for the used size than the size of the actual items in the storage. +func TestPersistentQueue_RestoredUsedSizeIsCorrectedOnDrain(t *testing.T) { + ext := NewMockStorageExtension(nil) + pq := createTestPersistentQueueWithItemsCapacity(t, ext, 1000) + + assert.Equal(t, 0, pq.Size()) + + for i := 0; i < 6; i++ { + assert.NoError(t, pq.Offer(context.Background(), newTracesRequest(2, 5))) + } + assert.Equal(t, 60, pq.Size()) + + // Consume 30 items + for i := 0; i < 3; i++ { + assert.True(t, pq.Consume(func(context.Context, tracesRequest) error { return nil })) + } + // The used size is now 30, but the snapshot should have 50, because it's taken every 5 read/writes. + assert.Equal(t, 30, pq.Size()) + + // Create a new queue pointed to the same storage + newPQ := createTestPersistentQueueWithItemsCapacity(t, ext, 1000) + + // This is an incorrect size restored from the snapshot. + // In reality the size should be 30. Once the queue is drained, it will be updated to the correct size. + assert.Equal(t, 50, newPQ.Size()) + + assert.True(t, newPQ.Consume(func(context.Context, tracesRequest) error { return nil })) + assert.True(t, newPQ.Consume(func(context.Context, tracesRequest) error { return nil })) + assert.Equal(t, 30, newPQ.Size()) + + // Now the size must be correctly reflected + assert.True(t, newPQ.Consume(func(context.Context, tracesRequest) error { return nil })) assert.Equal(t, 0, newPQ.Size()) assert.NoError(t, newPQ.Shutdown(context.Background())) + assert.NoError(t, pq.Shutdown(context.Background())) } func requireCurrentlyDispatchedItemsEqual(t *testing.T, pq *persistentQueue[tracesRequest], compare []uint64) { diff --git a/exporter/internal/queue/queue.go b/exporter/internal/queue/queue.go index 0ae0703b05d..35bc504579e 100644 --- a/exporter/internal/queue/queue.go +++ b/exporter/internal/queue/queue.go @@ -34,3 +34,26 @@ type Queue[T any] interface { // Capacity returns the capacity of the queue. Capacity() int } + +type itemsCounter interface { + ItemsCount() int +} + +// Sizer is an interface that returns the size of the given element. +type Sizer[T any] interface { + Sizeof(T) int64 +} + +// 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) int64 { + return int64(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) int64 { + return 1 +} diff --git a/exporter/internal/queue/queue_capacity.go b/exporter/internal/queue/queue_capacity.go deleted file mode 100644 index 1995febcd63..00000000000 --- a/exporter/internal/queue/queue_capacity.go +++ /dev/null @@ -1,74 +0,0 @@ -// 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 deleted file mode 100644 index 3dd6ad2b898..00000000000 --- a/exporter/internal/queue/queue_capacity_test.go +++ /dev/null @@ -1,58 +0,0 @@ -// 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/internal/queue/sized_channel.go b/exporter/internal/queue/sized_channel.go new file mode 100644 index 00000000000..1702a38ac2f --- /dev/null +++ b/exporter/internal/queue/sized_channel.go @@ -0,0 +1,104 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package queue // import "go.opentelemetry.io/collector/exporter/internal/queue" + +import "sync/atomic" + +// sizedChannel is a channel wrapper for sized elements with a capacity set to a total size of all the elements. +// The channel will accept elements until the total size of the elements reaches the capacity. +type sizedChannel[T any] struct { + used *atomic.Int64 + + // We need to store the capacity in a separate field because the capacity of the channel can be higher. + // It happens when we restore a persistent queue from a disk that is bigger than the pre-configured capacity. + cap int64 + ch chan T +} + +// newSizedChannel creates a sized elements channel. Each element is assigned a size by the provided sizer. +// chanCapacity is the capacity of the underlying channel which usually should be equal to the capacity of the queue to +// avoid blocking the producer. Optionally, the channel can be preloaded with the elements and their total size. +func newSizedChannel[T any](capacity int64, els []T, totalSize int64) *sizedChannel[T] { + used := &atomic.Int64{} + used.Store(totalSize) + + chCap := capacity + if chCap < int64(len(els)) { + chCap = int64(len(els)) + } + + ch := make(chan T, chCap) + for _, el := range els { + ch <- el + } + + return &sizedChannel[T]{ + used: used, + cap: capacity, + ch: ch, + } +} + +// push puts the element into the queue with the given sized if there is enough capacity. +// Returns an error if the queue is full. The callback is called before the element is committed to the queue. +// If the callback returns an error, the element is not put into the queue and the error is returned. +// The size is the size of the element MUST be positive. +func (vcq *sizedChannel[T]) push(el T, size int64, callback func() error) error { + if vcq.used.Add(size) > vcq.cap { + vcq.used.Add(-size) + return ErrQueueIsFull + } + if callback != nil { + if err := callback(); err != nil { + vcq.used.Add(-size) + return err + } + } + vcq.ch <- el + return nil +} + +// pop removes the element from the queue and returns it. +// 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. +// The callback is called before the element is removed from the queue. It must return the size of the element. +func (vcq *sizedChannel[T]) pop(callback func(T) (size int64)) (T, bool) { + el, ok := <-vcq.ch + if !ok { + return el, false + } + + size := callback(el) + + // The used size and the channel size might be not in sync with the queue in case it's restored from the disk + // because we don't flush the current queue size on the disk on every read/write. + // In that case we need to make sure it doesn't go below 0. + if vcq.used.Add(-size) < 0 { + vcq.used.Store(0) + } + return el, true +} + +// syncSize updates the used size to 0 if the queue is empty. +// The caller must ensure that this call is not called concurrently with push. +// It's used by the persistent queue to ensure the used value correctly reflects the reality which may not be always +// the case in case if the queue size is restored from the disk after a crash. +func (vcq *sizedChannel[T]) syncSize() { + if len(vcq.ch) == 0 { + vcq.used.Store(0) + } +} + +// shutdown closes the queue channel to initiate draining of the queue. +func (vcq *sizedChannel[T]) shutdown() { + close(vcq.ch) +} + +func (vcq *sizedChannel[T]) Size() int { + return int(vcq.used.Load()) +} + +func (vcq *sizedChannel[T]) Capacity() int { + return int(vcq.cap) +} diff --git a/exporter/internal/queue/sized_channel_test.go b/exporter/internal/queue/sized_channel_test.go new file mode 100644 index 00000000000..02cd4bf8e68 --- /dev/null +++ b/exporter/internal/queue/sized_channel_test.go @@ -0,0 +1,44 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package queue + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSizedCapacityChannel(t *testing.T) { + q := newSizedChannel[int](7, nil, 0) + assert.NoError(t, q.push(1, 1, nil)) + assert.Equal(t, 1, q.Size()) + assert.Equal(t, 7, q.Capacity()) + + // failed callback should not allow the element to be added + assert.Error(t, q.push(2, 2, func() error { return errors.New("failed") })) + assert.Equal(t, 1, q.Size()) + + assert.NoError(t, q.push(3, 3, nil)) + assert.Equal(t, 4, q.Size()) + + // should not be able to send to the full queue + assert.Error(t, q.push(4, 4, nil)) + assert.Equal(t, 4, q.Size()) + + el, ok := q.pop(func(el int) int64 { return int64(el) }) + assert.Equal(t, 1, el) + assert.True(t, ok) + assert.Equal(t, 3, q.Size()) + + el, ok = q.pop(func(el int) int64 { return int64(el) }) + assert.Equal(t, 3, el) + assert.True(t, ok) + assert.Equal(t, 0, q.Size()) + + q.shutdown() + el, ok = q.pop(func(el int) int64 { return int64(el) }) + assert.False(t, ok) + assert.Equal(t, 0, el) +} diff --git a/exporter/loggingexporter/generated_component_test.go b/exporter/loggingexporter/generated_component_test.go new file mode 100644 index 00000000000..e5902b96208 --- /dev/null +++ b/exporter/loggingexporter/generated_component_test.go @@ -0,0 +1,151 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package loggingexporter + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "logging", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +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) + }{ + + { + name: "logs", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsExporter(ctx, set, cfg) + }, + }, + + { + name: "metrics", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsExporter(ctx, set, cfg) + }, + }, + + { + name: "traces", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesExporter(ctx, set, cfg) + }, + }, + } + + 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) { + 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 test.name { + case "logs": + e, ok := c.(exporter.Logs) + require.True(t, ok) + logs := generateLifecycleTestLogs() + if !e.Capabilities().MutatesData { + logs.MarkReadOnly() + } + err = e.ConsumeLogs(context.Background(), logs) + case "metrics": + e, ok := c.(exporter.Metrics) + require.True(t, ok) + metrics := generateLifecycleTestMetrics() + if !e.Capabilities().MutatesData { + metrics.MarkReadOnly() + } + err = e.ConsumeMetrics(context.Background(), metrics) + case "traces": + e, ok := c.(exporter.Traces) + require.True(t, ok) + traces := generateLifecycleTestTraces() + 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) + }) + } +} + +func generateLifecycleTestLogs() plog.Logs { + logs := plog.NewLogs() + rl := logs.ResourceLogs().AppendEmpty() + rl.Resource().Attributes().PutStr("resource", "R1") + l := rl.ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() + l.Body().SetStr("test log message") + l.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return logs +} + +func generateLifecycleTestMetrics() pmetric.Metrics { + metrics := pmetric.NewMetrics() + rm := metrics.ResourceMetrics().AppendEmpty() + rm.Resource().Attributes().PutStr("resource", "R1") + m := rm.ScopeMetrics().AppendEmpty().Metrics().AppendEmpty() + m.SetName("test_metric") + dp := m.SetEmptyGauge().DataPoints().AppendEmpty() + dp.Attributes().PutStr("test_attr", "value_1") + dp.SetIntValue(123) + dp.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return metrics +} + +func generateLifecycleTestTraces() ptrace.Traces { + traces := ptrace.NewTraces() + rs := traces.ResourceSpans().AppendEmpty() + rs.Resource().Attributes().PutStr("resource", "R1") + span := rs.ScopeSpans().AppendEmpty().Spans().AppendEmpty() + span.Attributes().PutStr("test_attr", "value_1") + span.SetName("test_span") + span.SetStartTimestamp(pcommon.NewTimestampFromTime(time.Now().Add(-1 * time.Second))) + span.SetEndTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return traces +} diff --git a/exporter/loggingexporter/package_test.go b/exporter/loggingexporter/generated_package_test.go similarity index 62% rename from exporter/loggingexporter/package_test.go rename to exporter/loggingexporter/generated_package_test.go index 0c1b40739cc..14eb697fde5 100644 --- a/exporter/loggingexporter/package_test.go +++ b/exporter/loggingexporter/generated_package_test.go @@ -1,5 +1,4 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 +// Code generated by mdatagen. DO NOT EDIT. package loggingexporter diff --git a/exporter/loggingexporter/go.mod b/exporter/loggingexporter/go.mod index 97dac63f6aa..d817b35d6a6 100644 --- a/exporter/loggingexporter/go.mod +++ b/exporter/loggingexporter/go.mod @@ -4,57 +4,57 @@ module go.opentelemetry.io/collector/exporter/loggingexporter go 1.21 require ( - github.com/stretchr/testify v1.8.4 - 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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/exporter v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.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/cenkalti/backoff/v4 v4.3.0 // 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/google/uuid 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.1 // 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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.opentelemetry.io/collector v0.100.0 // indirect + go.opentelemetry.io/collector/config/configretry v0.100.0 // indirect + go.opentelemetry.io/collector/consumer v0.100.0 // indirect + go.opentelemetry.io/collector/extension v0.100.0 // indirect + go.opentelemetry.io/collector/receiver v0.100.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.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/net v0.24.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -74,6 +74,8 @@ replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata + replace go.opentelemetry.io/collector/receiver => ../../receiver retract ( diff --git a/exporter/loggingexporter/go.sum b/exporter/loggingexporter/go.sum index dbdb92fd3bb..7bbf6704ff6 100644 --- a/exporter/loggingexporter/go.sum +++ b/exporter/loggingexporter/go.sum @@ -1,7 +1,7 @@ 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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -16,13 +16,11 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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/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= @@ -31,8 +29,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -50,32 +48,32 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.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.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -91,16 +89,16 @@ 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -113,14 +111,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/exporter/loggingexporter/internal/metadata/generated_status.go b/exporter/loggingexporter/internal/metadata/generated_status.go index 64c84dcae1f..ce3f313e8e0 100644 --- a/exporter/loggingexporter/internal/metadata/generated_status.go +++ b/exporter/loggingexporter/internal/metadata/generated_status.go @@ -3,15 +3,11 @@ 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" + Type = component.MustNewType("logging") ) const ( @@ -19,11 +15,3 @@ const ( 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/internal/metadata/generated_telemetry.go b/exporter/loggingexporter/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..121a4370066 --- /dev/null +++ b/exporter/loggingexporter/internal/metadata/generated_telemetry.go @@ -0,0 +1,18 @@ +// 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" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/exporter/loggingexporter") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/exporter/loggingexporter") +} diff --git a/exporter/loggingexporter/internal/metadata/generated_telemetry_test.go b/exporter/loggingexporter/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..deab99a089e --- /dev/null +++ b/exporter/loggingexporter/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/exporter/loggingexporter", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/exporter/loggingexporter", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/exporter/nopexporter/Makefile b/exporter/nopexporter/Makefile new file mode 100644 index 00000000000..ded7a36092d --- /dev/null +++ b/exporter/nopexporter/Makefile @@ -0,0 +1 @@ +include ../../Makefile.Common diff --git a/exporter/nopexporter/README.md b/exporter/nopexporter/README.md new file mode 100644 index 00000000000..99b54523fb0 --- /dev/null +++ b/exporter/nopexporter/README.md @@ -0,0 +1,27 @@ +# No-op Exporter + + +| 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%3Aexporter%2Fnop%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aexporter%2Fnop) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aexporter%2Fnop%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aexporter%2Fnop) | + +[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 + + +Serves as a placeholder exporter in a pipeline. This can be useful if you want +to e.g. start a Collector with only extensions enabled, or for testing Collector +pipeline throughput without worrying about an exporter. + +## Getting Started + +All that is required to enable the No-op exporter is to include it in the +exporter definitions. It takes no configuration. + +```yaml +exporters: + nop: +``` diff --git a/exporter/nopexporter/doc.go b/exporter/nopexporter/doc.go new file mode 100644 index 00000000000..00261565191 --- /dev/null +++ b/exporter/nopexporter/doc.go @@ -0,0 +1,7 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +//go:generate mdatagen metadata.yaml + +// Package nopexporter serves as a placeholder exporter. +package nopexporter // import "go.opentelemetry.io/collector/exporter/nopexporter" diff --git a/exporter/nopexporter/generated_component_test.go b/exporter/nopexporter/generated_component_test.go new file mode 100644 index 00000000000..675dee1a0ee --- /dev/null +++ b/exporter/nopexporter/generated_component_test.go @@ -0,0 +1,151 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package nopexporter + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "nop", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +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) + }{ + + { + name: "logs", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsExporter(ctx, set, cfg) + }, + }, + + { + name: "metrics", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsExporter(ctx, set, cfg) + }, + }, + + { + name: "traces", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesExporter(ctx, set, cfg) + }, + }, + } + + 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) { + 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 test.name { + case "logs": + e, ok := c.(exporter.Logs) + require.True(t, ok) + logs := generateLifecycleTestLogs() + if !e.Capabilities().MutatesData { + logs.MarkReadOnly() + } + err = e.ConsumeLogs(context.Background(), logs) + case "metrics": + e, ok := c.(exporter.Metrics) + require.True(t, ok) + metrics := generateLifecycleTestMetrics() + if !e.Capabilities().MutatesData { + metrics.MarkReadOnly() + } + err = e.ConsumeMetrics(context.Background(), metrics) + case "traces": + e, ok := c.(exporter.Traces) + require.True(t, ok) + traces := generateLifecycleTestTraces() + 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) + }) + } +} + +func generateLifecycleTestLogs() plog.Logs { + logs := plog.NewLogs() + rl := logs.ResourceLogs().AppendEmpty() + rl.Resource().Attributes().PutStr("resource", "R1") + l := rl.ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() + l.Body().SetStr("test log message") + l.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return logs +} + +func generateLifecycleTestMetrics() pmetric.Metrics { + metrics := pmetric.NewMetrics() + rm := metrics.ResourceMetrics().AppendEmpty() + rm.Resource().Attributes().PutStr("resource", "R1") + m := rm.ScopeMetrics().AppendEmpty().Metrics().AppendEmpty() + m.SetName("test_metric") + dp := m.SetEmptyGauge().DataPoints().AppendEmpty() + dp.Attributes().PutStr("test_attr", "value_1") + dp.SetIntValue(123) + dp.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return metrics +} + +func generateLifecycleTestTraces() ptrace.Traces { + traces := ptrace.NewTraces() + rs := traces.ResourceSpans().AppendEmpty() + rs.Resource().Attributes().PutStr("resource", "R1") + span := rs.ScopeSpans().AppendEmpty().Spans().AppendEmpty() + span.Attributes().PutStr("test_attr", "value_1") + span.SetName("test_span") + span.SetStartTimestamp(pcommon.NewTimestampFromTime(time.Now().Add(-1 * time.Second))) + span.SetEndTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return traces +} diff --git a/extension/extensiontest/package_test.go b/exporter/nopexporter/generated_package_test.go similarity index 51% rename from extension/extensiontest/package_test.go rename to exporter/nopexporter/generated_package_test.go index 22f7af4bd14..1bcb87f7640 100644 --- a/extension/extensiontest/package_test.go +++ b/exporter/nopexporter/generated_package_test.go @@ -1,7 +1,6 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 +// Code generated by mdatagen. DO NOT EDIT. -package extensiontest +package nopexporter import ( "testing" diff --git a/exporter/nopexporter/go.mod b/exporter/nopexporter/go.mod new file mode 100644 index 00000000000..5d3489ccf93 --- /dev/null +++ b/exporter/nopexporter/go.mod @@ -0,0 +1,80 @@ +module go.opentelemetry.io/collector/exporter/nopexporter + +go 1.21 + +toolchain go1.21.6 + +require ( + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/exporter v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.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/google/uuid 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.1.1 // 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.1 // indirect + github.com/prometheus/common v0.53.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/receiver v0.100.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace go.opentelemetry.io/collector/component => ../../component + +replace go.opentelemetry.io/collector/consumer => ../../consumer + +replace go.opentelemetry.io/collector/exporter => ../ + +replace go.opentelemetry.io/collector/pdata => ../../pdata + +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata + +replace go.opentelemetry.io/collector/config/configretry => ../../config/configretry + +replace go.opentelemetry.io/collector/receiver => ../../receiver + +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 => ../../config/configtelemetry + +replace go.opentelemetry.io/collector/extension => ../../extension diff --git a/exporter/nopexporter/go.sum b/exporter/nopexporter/go.sum new file mode 100644 index 00000000000..7bbf6704ff6 --- /dev/null +++ b/exporter/nopexporter/go.sum @@ -0,0 +1,124 @@ +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.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/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.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/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.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/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= +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.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= +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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +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.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +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.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/exporter/nopexporter/internal/metadata/generated_status.go b/exporter/nopexporter/internal/metadata/generated_status.go new file mode 100644 index 00000000000..1901cab9ee6 --- /dev/null +++ b/exporter/nopexporter/internal/metadata/generated_status.go @@ -0,0 +1,17 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("nop") +) + +const ( + TracesStability = component.StabilityLevelBeta + MetricsStability = component.StabilityLevelBeta + LogsStability = component.StabilityLevelBeta +) diff --git a/exporter/nopexporter/internal/metadata/generated_telemetry.go b/exporter/nopexporter/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..db41096278d --- /dev/null +++ b/exporter/nopexporter/internal/metadata/generated_telemetry.go @@ -0,0 +1,18 @@ +// 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" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/exporter/nopexporter") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/exporter/nopexporter") +} diff --git a/exporter/nopexporter/internal/metadata/generated_telemetry_test.go b/exporter/nopexporter/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..13312b17e0d --- /dev/null +++ b/exporter/nopexporter/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/exporter/nopexporter", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/exporter/nopexporter", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/exporter/nopexporter/metadata.yaml b/exporter/nopexporter/metadata.yaml new file mode 100644 index 00000000000..3c61e2e6433 --- /dev/null +++ b/exporter/nopexporter/metadata.yaml @@ -0,0 +1,7 @@ +type: nop + +status: + class: exporter + stability: + beta: [traces, metrics, logs] + distributions: [core, contrib] diff --git a/exporter/nopexporter/nop_exporter.go b/exporter/nopexporter/nop_exporter.go new file mode 100644 index 00000000000..16adf430cea --- /dev/null +++ b/exporter/nopexporter/nop_exporter.go @@ -0,0 +1,46 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package nopexporter // import "go.opentelemetry.io/collector/exporter/nopexporter" + +import ( + "context" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/nopexporter/internal/metadata" +) + +// NewFactory returns an exporter.Factory that constructs nop exporters. +func NewFactory() exporter.Factory { + return exporter.NewFactory( + metadata.Type, + func() component.Config { return &struct{}{} }, + exporter.WithTraces(createTracesExporter, metadata.TracesStability), + exporter.WithMetrics(createMetricsExporter, metadata.MetricsStability), + exporter.WithLogs(createLogsExporter, metadata.LogsStability), + ) +} + +func createTracesExporter(context.Context, exporter.CreateSettings, component.Config) (exporter.Traces, error) { + return nopInstance, nil +} + +func createMetricsExporter(context.Context, exporter.CreateSettings, component.Config) (exporter.Metrics, error) { + return nopInstance, nil +} + +func createLogsExporter(context.Context, exporter.CreateSettings, component.Config) (exporter.Logs, error) { + return nopInstance, nil +} + +var nopInstance = &nopExporter{ + Consumer: consumertest.NewNop(), +} + +type nopExporter struct { + component.StartFunc + component.ShutdownFunc + consumertest.Consumer +} diff --git a/exporter/nopexporter/nop_exporter_test.go b/exporter/nopexporter/nop_exporter_test.go new file mode 100644 index 00000000000..80baefc9631 --- /dev/null +++ b/exporter/nopexporter/nop_exporter_test.go @@ -0,0 +1,45 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package nopexporter + +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/exporter/exportertest" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" +) + +func TestNewNopFactory(t *testing.T) { + factory := NewFactory() + require.NotNil(t, factory) + assert.Equal(t, component.MustNewType("nop"), factory.Type()) + cfg := factory.CreateDefaultConfig() + assert.Equal(t, &struct{}{}, cfg) + + traces, err := factory.CreateTracesExporter(context.Background(), exportertest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + 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.CreateMetricsExporter(context.Background(), exportertest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + 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.CreateLogsExporter(context.Background(), exportertest.NewNopCreateSettings(), cfg) + require.NoError(t, err) + 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/exporter/otlpexporter/config.go b/exporter/otlpexporter/config.go index 61440c3a9e3..62956f293ed 100644 --- a/exporter/otlpexporter/config.go +++ b/exporter/otlpexporter/config.go @@ -5,6 +5,10 @@ package otlpexporter // import "go.opentelemetry.io/collector/exporter/otlpexpor import ( "errors" + "fmt" + "net" + "strconv" + "strings" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configgrpc" @@ -22,10 +26,34 @@ type Config struct { } func (c *Config) Validate() error { - if c.SanitizedEndpoint() == "" { + endpoint := c.sanitizedEndpoint() + if endpoint == "" { return errors.New(`requires a non-empty "endpoint"`) } + + // Validate that the port is in the address + _, port, err := net.SplitHostPort(endpoint) + if err != nil { + return err + } + if _, err := strconv.Atoi(port); err != nil { + return fmt.Errorf(`invalid port "%s"`, port) + } + return nil } +func (c *Config) sanitizedEndpoint() string { + switch { + case strings.HasPrefix(c.Endpoint, "http://"): + return strings.TrimPrefix(c.Endpoint, "http://") + case strings.HasPrefix(c.Endpoint, "https://"): + return strings.TrimPrefix(c.Endpoint, "https://") + case strings.HasPrefix(c.Endpoint, "dns:///"): + return strings.TrimPrefix(c.Endpoint, "dns:///") + default: + return c.Endpoint + } +} + var _ component.Config = (*Config)(nil) diff --git a/exporter/otlpexporter/config_test.go b/exporter/otlpexporter/config_test.go index c024eb0af88..7a644b7ef0e 100644 --- a/exporter/otlpexporter/config_test.go +++ b/exporter/otlpexporter/config_test.go @@ -62,7 +62,7 @@ func TestUnmarshalConfig(t *testing.T) { Endpoint: "1.2.3.4:1234", Compression: "gzip", TLSSetting: configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: "/var/lib/mycert.pem", }, Insecure: false, @@ -91,6 +91,10 @@ func TestUnmarshalInvalidConfig(t *testing.T) { name: "no_endpoint", errorMsg: `requires a non-empty "endpoint"`, }, + { + name: "https_endpoint", + errorMsg: `requires a non-empty "endpoint"`, + }, { name: "http_endpoint", errorMsg: `requires a non-empty "endpoint"`, @@ -103,6 +107,18 @@ func TestUnmarshalInvalidConfig(t *testing.T) { name: "invalid_retry", errorMsg: `'randomization_factor' must be within [0, 1]`, }, + { + name: "invalid_tls", + errorMsg: `invalid TLS min_version: unsupported TLS version: "asd"`, + }, + { + name: "missing_port", + errorMsg: `missing port in address`, + }, + { + name: "invalid_port", + errorMsg: `invalid port "port"`, + }, } { t.Run(test.name, func(t *testing.T) { cfg := factory.CreateDefaultConfig() @@ -114,3 +130,10 @@ func TestUnmarshalInvalidConfig(t *testing.T) { } } + +func TestValidDNSEndpoint(t *testing.T) { + factory := NewFactory() + cfg := factory.CreateDefaultConfig().(*Config) + cfg.Endpoint = "dns:///backend.example.com:4317" + assert.NoError(t, cfg.Validate()) +} diff --git a/exporter/otlpexporter/factory_test.go b/exporter/otlpexporter/factory_test.go index 45db95986b4..d89c8fe2ead 100644 --- a/exporter/otlpexporter/factory_test.go +++ b/exporter/otlpexporter/factory_test.go @@ -140,7 +140,7 @@ func TestCreateTracesExporter(t *testing.T) { ClientConfig: configgrpc.ClientConfig{ Endpoint: endpoint, TLSSetting: configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "test_cert.pem"), }, }, @@ -153,7 +153,7 @@ func TestCreateTracesExporter(t *testing.T) { ClientConfig: configgrpc.ClientConfig{ Endpoint: endpoint, TLSSetting: configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: "nosuchfile", }, }, diff --git a/exporter/otlpexporter/generated_component_test.go b/exporter/otlpexporter/generated_component_test.go new file mode 100644 index 00000000000..27a3b7da3d0 --- /dev/null +++ b/exporter/otlpexporter/generated_component_test.go @@ -0,0 +1,151 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package otlpexporter + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "otlp", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +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) + }{ + + { + name: "logs", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsExporter(ctx, set, cfg) + }, + }, + + { + name: "metrics", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsExporter(ctx, set, cfg) + }, + }, + + { + name: "traces", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesExporter(ctx, set, cfg) + }, + }, + } + + 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) { + 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 test.name { + case "logs": + e, ok := c.(exporter.Logs) + require.True(t, ok) + logs := generateLifecycleTestLogs() + if !e.Capabilities().MutatesData { + logs.MarkReadOnly() + } + err = e.ConsumeLogs(context.Background(), logs) + case "metrics": + e, ok := c.(exporter.Metrics) + require.True(t, ok) + metrics := generateLifecycleTestMetrics() + if !e.Capabilities().MutatesData { + metrics.MarkReadOnly() + } + err = e.ConsumeMetrics(context.Background(), metrics) + case "traces": + e, ok := c.(exporter.Traces) + require.True(t, ok) + traces := generateLifecycleTestTraces() + 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) + }) + } +} + +func generateLifecycleTestLogs() plog.Logs { + logs := plog.NewLogs() + rl := logs.ResourceLogs().AppendEmpty() + rl.Resource().Attributes().PutStr("resource", "R1") + l := rl.ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() + l.Body().SetStr("test log message") + l.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return logs +} + +func generateLifecycleTestMetrics() pmetric.Metrics { + metrics := pmetric.NewMetrics() + rm := metrics.ResourceMetrics().AppendEmpty() + rm.Resource().Attributes().PutStr("resource", "R1") + m := rm.ScopeMetrics().AppendEmpty().Metrics().AppendEmpty() + m.SetName("test_metric") + dp := m.SetEmptyGauge().DataPoints().AppendEmpty() + dp.Attributes().PutStr("test_attr", "value_1") + dp.SetIntValue(123) + dp.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return metrics +} + +func generateLifecycleTestTraces() ptrace.Traces { + traces := ptrace.NewTraces() + rs := traces.ResourceSpans().AppendEmpty() + rs.Resource().Attributes().PutStr("resource", "R1") + span := rs.ScopeSpans().AppendEmpty().Spans().AppendEmpty() + span.Attributes().PutStr("test_attr", "value_1") + span.SetName("test_span") + span.SetStartTimestamp(pcommon.NewTimestampFromTime(time.Now().Add(-1 * time.Second))) + span.SetEndTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return traces +} diff --git a/exporter/otlpexporter/generated_package_test.go b/exporter/otlpexporter/generated_package_test.go new file mode 100644 index 00000000000..9612d731def --- /dev/null +++ b/exporter/otlpexporter/generated_package_test.go @@ -0,0 +1,13 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package otlpexporter + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/exporter/otlpexporter/go.mod b/exporter/otlpexporter/go.mod index 8762e4cc0f9..6ba890c33a8 100644 --- a/exporter/otlpexporter/go.mod +++ b/exporter/otlpexporter/go.mod @@ -3,31 +3,32 @@ module go.opentelemetry.io/collector/exporter/otlpexporter 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/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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/config/configauth v0.100.0 + go.opentelemetry.io/collector/config/configcompression v1.7.0 + go.opentelemetry.io/collector/config/configgrpc v0.100.0 + go.opentelemetry.io/collector/config/configopaque v1.7.0 + go.opentelemetry.io/collector/config/configretry v0.100.0 + go.opentelemetry.io/collector/config/configtls v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/exporter v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/collector/pdata/testdata v0.100.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda + google.golang.org/grpc v1.63.2 + google.golang.org/protobuf v1.34.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -35,15 +36,15 @@ require ( 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/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // 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.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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.1 // 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 @@ -51,32 +52,35 @@ require ( 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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.opentelemetry.io/collector/config/confignet v0.100.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/config/internal v0.100.0 // indirect + go.opentelemetry.io/collector/extension v0.100.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.100.0 // indirect + go.opentelemetry.io/collector/featuregate v1.7.0 // indirect + go.opentelemetry.io/collector/receiver v0.100.0 // indirect + go.opentelemetry.io/contrib/config v0.6.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.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/net v0.24.0 // indirect + golang.org/x/sys v0.19.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/api v0.0.0-20240227224415-6ceb2ff114de // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -110,6 +114,8 @@ replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata + replace go.opentelemetry.io/collector/receiver => ../../receiver replace go.opentelemetry.io/collector/consumer => ../../consumer diff --git a/exporter/otlpexporter/go.sum b/exporter/otlpexporter/go.sum index d617159313d..0180159064d 100644 --- a/exporter/otlpexporter/go.sum +++ b/exporter/otlpexporter/go.sum @@ -1,20 +1,12 @@ -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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/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/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= @@ -26,17 +18,15 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= 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= @@ -49,8 +39,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -70,46 +60,52 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/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.opentelemetry.io/contrib/config v0.6.0 h1:M1SRD1Z15XHPGk61tMLI1up77XT5FdrqQSRrlH0fYuk= +go.opentelemetry.io/contrib/config v0.6.0/go.mod h1:t+/kzmRWLN7J+4F/dD4fFvlYCmCO63WYwy/B00IC++c= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 h1:A3SayB3rNyt+1S6qpI9mHPkeHTZbD7XILEqWnYZb2l0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0/go.mod h1:27iA5uvhuRNmalO+iEUdVn5ZMj2qy10Mm+XRIpRmyuU= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 h1:+hm+I+KigBy3M24/h1p/NHkUx/evbLH0PNcjpMyCHc4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0/go.mod h1:NjC8142mLvvNT6biDpaMjyz78kyEHIwAJlSX0N9P5KI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 h1:HGZWGmCVRCVyAs2GQaiHQPbDHo+ObFWeUEOd+zDnp64= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0/go.mod h1:SaH+v38LSCHddyk7RGlU9uZyQoRrKao6IBnJw6Kbn+c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 h1:1u/AyyOqAWzy+SkPxDpahCNZParHV8Vid1RnI2clyDE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0/go.mod h1:z46paqbJ9l7c9fIPCXTqTGwhQZ5XoTIsfeFYWboizjs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 h1:Waw9Wfpo/IXzOI8bCB7DIk+0JZcqqsyn1JFnAc+iam8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0/go.mod h1:wnJIG4fOqyynOnnQF/eQb4/16VlX2EJAHhHgqIqWfAo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 h1:1wp/gyxsuYtuE/JFxsQRtcCDtMrO2qMvlfXALU5wkzI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0/go.mod h1:gbTHmghkGgqxMomVQQMur1Nba4M0MQ8AYThXDUjsJ38= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 h1:5fnmgteaar1VcAA69huatudPduNFz7guRtCmfZCooZI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0/go.mod h1:lsPccfZiz1cb1AhBPmicWM2E4F1VynFXEvD8SEBS4TM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 h1:0W5o9SzoR15ocYHEQfvfipzcNog1lBxOLfnex91Hk6s= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0/go.mod h1:zVZ8nz+VSggWmnh6tTsJqXQ7rU4xLwRtna1M4x5jq58= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= 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= @@ -125,18 +121,16 @@ 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.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/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -149,20 +143,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.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= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/exporter/otlpexporter/internal/metadata/generated_status.go b/exporter/otlpexporter/internal/metadata/generated_status.go index 4b0d0f0ecd5..c9cff844fa2 100644 --- a/exporter/otlpexporter/internal/metadata/generated_status.go +++ b/exporter/otlpexporter/internal/metadata/generated_status.go @@ -3,15 +3,11 @@ 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" + Type = component.MustNewType("otlp") ) const ( @@ -19,11 +15,3 @@ const ( 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/internal/metadata/generated_telemetry.go b/exporter/otlpexporter/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..ee872915b19 --- /dev/null +++ b/exporter/otlpexporter/internal/metadata/generated_telemetry.go @@ -0,0 +1,18 @@ +// 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" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/exporter/otlpexporter") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/exporter/otlpexporter") +} diff --git a/exporter/otlpexporter/internal/metadata/generated_telemetry_test.go b/exporter/otlpexporter/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..8ad8ad95063 --- /dev/null +++ b/exporter/otlpexporter/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/exporter/otlpexporter", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/exporter/otlpexporter", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/exporter/otlpexporter/metadata.yaml b/exporter/otlpexporter/metadata.yaml index 820930b1dc5..f24e40e1f91 100644 --- a/exporter/otlpexporter/metadata.yaml +++ b/exporter/otlpexporter/metadata.yaml @@ -6,3 +6,7 @@ status: stable: [traces, metrics] beta: [logs] distributions: [core, contrib] + +tests: + config: + endpoint: otelcol:4317 \ No newline at end of file diff --git a/exporter/otlpexporter/otlp_test.go b/exporter/otlpexporter/otlp_test.go index d1c4f622bc0..345c9cbf645 100644 --- a/exporter/otlpexporter/otlp_test.go +++ b/exporter/otlpexporter/otlp_test.go @@ -31,13 +31,13 @@ import ( "go.opentelemetry.io/collector/config/configtls" "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exportertest" - "go.opentelemetry.io/collector/internal/testdata" "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/pdata/testdata" ) type mockReceiver struct { diff --git a/exporter/otlpexporter/testdata/invalid_configs.yaml b/exporter/otlpexporter/testdata/invalid_configs.yaml index 73c24e3f13e..69fd873be3f 100644 --- a/exporter/otlpexporter/testdata/invalid_configs.yaml +++ b/exporter/otlpexporter/testdata/invalid_configs.yaml @@ -11,6 +11,8 @@ no_endpoint: multiplier: 1.3 max_interval: 60s max_elapsed_time: 10m +https_endpoint: + endpoint: https:// http_endpoint: endpoint: http:// timeout: 10s @@ -53,3 +55,49 @@ invalid_retry: multiplier: 1.3 max_interval: 60s max_elapsed_time: 10m +invalid_tls: + tls: + min_version: asd + endpoint: example.com:443 + 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 +missing_port: + endpoint: example.com + 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_port: + endpoint: example.com:port + 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 + + diff --git a/exporter/otlphttpexporter/config_test.go b/exporter/otlphttpexporter/config_test.go index 04bb1041036..e158891dd75 100644 --- a/exporter/otlphttpexporter/config_test.go +++ b/exporter/otlphttpexporter/config_test.go @@ -60,7 +60,7 @@ func TestUnmarshalConfig(t *testing.T) { }, Endpoint: "https://1.2.3.4:1234", TLSSetting: configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: "/var/lib/mycert.pem", CertFile: "certfile", KeyFile: "keyfile", diff --git a/exporter/otlphttpexporter/factory_test.go b/exporter/otlphttpexporter/factory_test.go index a36a9548d95..d81b0c7bd55 100644 --- a/exporter/otlphttpexporter/factory_test.go +++ b/exporter/otlphttpexporter/factory_test.go @@ -97,7 +97,7 @@ func TestCreateTracesExporter(t *testing.T) { ClientConfig: confighttp.ClientConfig{ Endpoint: endpoint, TLSSetting: configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: filepath.Join("testdata", "test_cert.pem"), }, }, @@ -110,7 +110,7 @@ func TestCreateTracesExporter(t *testing.T) { ClientConfig: confighttp.ClientConfig{ Endpoint: endpoint, TLSSetting: configtls.ClientConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CAFile: "nosuchfile", }, }, diff --git a/exporter/otlphttpexporter/generated_component_test.go b/exporter/otlphttpexporter/generated_component_test.go new file mode 100644 index 00000000000..443b94841b4 --- /dev/null +++ b/exporter/otlphttpexporter/generated_component_test.go @@ -0,0 +1,151 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package otlphttpexporter + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exportertest" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/ptrace" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "otlphttp", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +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) + }{ + + { + name: "logs", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsExporter(ctx, set, cfg) + }, + }, + + { + name: "metrics", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsExporter(ctx, set, cfg) + }, + }, + + { + name: "traces", + createFn: func(ctx context.Context, set exporter.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesExporter(ctx, set, cfg) + }, + }, + } + + 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) { + 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 test.name { + case "logs": + e, ok := c.(exporter.Logs) + require.True(t, ok) + logs := generateLifecycleTestLogs() + if !e.Capabilities().MutatesData { + logs.MarkReadOnly() + } + err = e.ConsumeLogs(context.Background(), logs) + case "metrics": + e, ok := c.(exporter.Metrics) + require.True(t, ok) + metrics := generateLifecycleTestMetrics() + if !e.Capabilities().MutatesData { + metrics.MarkReadOnly() + } + err = e.ConsumeMetrics(context.Background(), metrics) + case "traces": + e, ok := c.(exporter.Traces) + require.True(t, ok) + traces := generateLifecycleTestTraces() + 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) + }) + } +} + +func generateLifecycleTestLogs() plog.Logs { + logs := plog.NewLogs() + rl := logs.ResourceLogs().AppendEmpty() + rl.Resource().Attributes().PutStr("resource", "R1") + l := rl.ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() + l.Body().SetStr("test log message") + l.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return logs +} + +func generateLifecycleTestMetrics() pmetric.Metrics { + metrics := pmetric.NewMetrics() + rm := metrics.ResourceMetrics().AppendEmpty() + rm.Resource().Attributes().PutStr("resource", "R1") + m := rm.ScopeMetrics().AppendEmpty().Metrics().AppendEmpty() + m.SetName("test_metric") + dp := m.SetEmptyGauge().DataPoints().AppendEmpty() + dp.Attributes().PutStr("test_attr", "value_1") + dp.SetIntValue(123) + dp.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return metrics +} + +func generateLifecycleTestTraces() ptrace.Traces { + traces := ptrace.NewTraces() + rs := traces.ResourceSpans().AppendEmpty() + rs.Resource().Attributes().PutStr("resource", "R1") + span := rs.ScopeSpans().AppendEmpty().Spans().AppendEmpty() + span.Attributes().PutStr("test_attr", "value_1") + span.SetName("test_span") + span.SetStartTimestamp(pcommon.NewTimestampFromTime(time.Now().Add(-1 * time.Second))) + span.SetEndTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return traces +} diff --git a/exporter/otlphttpexporter/package_test.go b/exporter/otlphttpexporter/generated_package_test.go similarity index 62% rename from exporter/otlphttpexporter/package_test.go rename to exporter/otlphttpexporter/generated_package_test.go index 07858386cc4..625e0cd9304 100644 --- a/exporter/otlphttpexporter/package_test.go +++ b/exporter/otlphttpexporter/generated_package_test.go @@ -1,5 +1,4 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 +// Code generated by mdatagen. DO NOT EDIT. package otlphttpexporter diff --git a/exporter/otlphttpexporter/go.mod b/exporter/otlphttpexporter/go.mod index 20043caf0b6..2c9f641f43b 100644 --- a/exporter/otlphttpexporter/go.mod +++ b/exporter/otlphttpexporter/go.mod @@ -3,30 +3,30 @@ module go.opentelemetry.io/collector/exporter/otlphttpexporter 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/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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/config/configcompression v1.7.0 + go.opentelemetry.io/collector/config/confighttp v0.100.0 + go.opentelemetry.io/collector/config/configopaque v1.7.0 + go.opentelemetry.io/collector/config/configretry v0.100.0 + go.opentelemetry.io/collector/config/configtls v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/exporter v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda + google.golang.org/grpc v1.63.2 + google.golang.org/protobuf v1.34.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // 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 @@ -35,48 +35,51 @@ require ( 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/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // 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/klauspost/compress v1.17.8 // 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/knadh/koanf/v2 v2.1.1 // 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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.opentelemetry.io/collector/config/configauth v0.100.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/config/internal v0.100.0 // indirect + go.opentelemetry.io/collector/extension v0.100.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.100.0 // indirect + go.opentelemetry.io/collector/featuregate v1.7.0 // indirect + go.opentelemetry.io/collector/receiver v0.100.0 // indirect + go.opentelemetry.io/contrib/config v0.6.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.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/net v0.24.0 // indirect + golang.org/x/sys v0.19.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/api v0.0.0-20240227224415-6ceb2ff114de // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -110,6 +113,8 @@ replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata + replace go.opentelemetry.io/collector/receiver => ../../receiver replace go.opentelemetry.io/collector/consumer => ../../consumer diff --git a/exporter/otlphttpexporter/go.sum b/exporter/otlphttpexporter/go.sum index 9d2b7f63d76..b8a1052e14f 100644 --- a/exporter/otlphttpexporter/go.sum +++ b/exporter/otlphttpexporter/go.sum @@ -1,7 +1,7 @@ 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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -20,31 +20,29 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= 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/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/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/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -62,48 +60,54 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/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/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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/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.opentelemetry.io/contrib/config v0.6.0 h1:M1SRD1Z15XHPGk61tMLI1up77XT5FdrqQSRrlH0fYuk= +go.opentelemetry.io/contrib/config v0.6.0/go.mod h1:t+/kzmRWLN7J+4F/dD4fFvlYCmCO63WYwy/B00IC++c= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 h1:Xs2Ncz0gNihqu9iosIZ5SkBbWo5T8JhhLJFMQL1qmLI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0/go.mod h1:vy+2G/6NvVMpwGX/NyLqcC41fxepnuKHk16E6IZUcJc= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 h1:+hm+I+KigBy3M24/h1p/NHkUx/evbLH0PNcjpMyCHc4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0/go.mod h1:NjC8142mLvvNT6biDpaMjyz78kyEHIwAJlSX0N9P5KI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 h1:HGZWGmCVRCVyAs2GQaiHQPbDHo+ObFWeUEOd+zDnp64= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0/go.mod h1:SaH+v38LSCHddyk7RGlU9uZyQoRrKao6IBnJw6Kbn+c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 h1:1u/AyyOqAWzy+SkPxDpahCNZParHV8Vid1RnI2clyDE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0/go.mod h1:z46paqbJ9l7c9fIPCXTqTGwhQZ5XoTIsfeFYWboizjs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 h1:Waw9Wfpo/IXzOI8bCB7DIk+0JZcqqsyn1JFnAc+iam8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0/go.mod h1:wnJIG4fOqyynOnnQF/eQb4/16VlX2EJAHhHgqIqWfAo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 h1:1wp/gyxsuYtuE/JFxsQRtcCDtMrO2qMvlfXALU5wkzI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0/go.mod h1:gbTHmghkGgqxMomVQQMur1Nba4M0MQ8AYThXDUjsJ38= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 h1:5fnmgteaar1VcAA69huatudPduNFz7guRtCmfZCooZI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0/go.mod h1:lsPccfZiz1cb1AhBPmicWM2E4F1VynFXEvD8SEBS4TM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 h1:0W5o9SzoR15ocYHEQfvfipzcNog1lBxOLfnex91Hk6s= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0/go.mod h1:zVZ8nz+VSggWmnh6tTsJqXQ7rU4xLwRtna1M4x5jq58= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= 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= @@ -119,16 +123,16 @@ 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -141,18 +145,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 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= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/exporter/otlphttpexporter/internal/metadata/generated_status.go b/exporter/otlphttpexporter/internal/metadata/generated_status.go index d9f62544a6f..8af2905a456 100644 --- a/exporter/otlphttpexporter/internal/metadata/generated_status.go +++ b/exporter/otlphttpexporter/internal/metadata/generated_status.go @@ -3,15 +3,11 @@ 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" + Type = component.MustNewType("otlphttp") ) const ( @@ -19,11 +15,3 @@ const ( 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/internal/metadata/generated_telemetry.go b/exporter/otlphttpexporter/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..8b014c784fb --- /dev/null +++ b/exporter/otlphttpexporter/internal/metadata/generated_telemetry.go @@ -0,0 +1,18 @@ +// 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" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/exporter/otlphttpexporter") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/exporter/otlphttpexporter") +} diff --git a/exporter/otlphttpexporter/internal/metadata/generated_telemetry_test.go b/exporter/otlphttpexporter/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..bc1d66d9cfb --- /dev/null +++ b/exporter/otlphttpexporter/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/exporter/otlphttpexporter", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/exporter/otlphttpexporter", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/exporter/otlphttpexporter/metadata.yaml b/exporter/otlphttpexporter/metadata.yaml index 14cae78d175..5e1c41d3243 100644 --- a/exporter/otlphttpexporter/metadata.yaml +++ b/exporter/otlphttpexporter/metadata.yaml @@ -6,3 +6,8 @@ status: stable: [traces, metrics] beta: [logs] distributions: [core, contrib] + +tests: + config: + endpoint: "https://1.2.3.4:1234" + diff --git a/exporter/otlphttpexporter/otlp.go b/exporter/otlphttpexporter/otlp.go index 6ebc50e2cc0..ea02be512f4 100644 --- a/exporter/otlphttpexporter/otlp.go +++ b/exporter/otlphttpexporter/otlp.go @@ -23,6 +23,7 @@ import ( "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exporterhelper" + "go.opentelemetry.io/collector/internal/httphelper" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/plog/plogotlp" "go.opentelemetry.io/collector/pdata/pmetric" @@ -77,8 +78,8 @@ 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.ClientConfig.ToClient(host, e.settings) +func (e *baseExporter) start(ctx context.Context, host component.Host) error { + client, err := e.config.ClientConfig.ToClient(ctx, host, e.settings) if err != nil { return err } @@ -184,16 +185,18 @@ func (e *baseExporter) export(ctx context.Context, url string, request []byte, p respStatus := readResponseStatus(resp) // Format the error message. Use the status if it is present in the response. + var errString string var formattedErr error if respStatus != nil { - formattedErr = fmt.Errorf( + errString = fmt.Sprintf( "error exporting items, request to %s responded with HTTP Status Code %d, Message=%s, Details=%v", url, resp.StatusCode, respStatus.Message, respStatus.Details) } else { - formattedErr = fmt.Errorf( + errString = fmt.Sprintf( "error exporting items, request to %s responded with HTTP Status Code %d", url, resp.StatusCode) } + formattedErr = httphelper.NewStatusFromMsgAndHTTPCode(errString, resp.StatusCode).Err() if isRetryableStatusCode(resp.StatusCode) { // A retry duration of 0 seconds will trigger the default backoff policy @@ -301,6 +304,9 @@ func handlePartialSuccessResponse(resp *http.Response, partialSuccessHandler par type partialSuccessHandler func(bytes []byte, contentType string) error func (e *baseExporter) tracesPartialSuccessHandler(protoBytes []byte, contentType string) error { + if protoBytes == nil { + return nil + } exportResponse := ptraceotlp.NewExportResponse() switch contentType { case protobufContentType: @@ -328,6 +334,9 @@ func (e *baseExporter) tracesPartialSuccessHandler(protoBytes []byte, contentTyp } func (e *baseExporter) metricsPartialSuccessHandler(protoBytes []byte, contentType string) error { + if protoBytes == nil { + return nil + } exportResponse := pmetricotlp.NewExportResponse() switch contentType { case protobufContentType: @@ -355,6 +364,9 @@ func (e *baseExporter) metricsPartialSuccessHandler(protoBytes []byte, contentTy } func (e *baseExporter) logsPartialSuccessHandler(protoBytes []byte, contentType string) error { + if protoBytes == nil { + return nil + } exportResponse := plogotlp.NewExportResponse() switch contentType { case protobufContentType: diff --git a/exporter/otlphttpexporter/otlp_test.go b/exporter/otlphttpexporter/otlp_test.go index 0116803d816..e886e655482 100644 --- a/exporter/otlphttpexporter/otlp_test.go +++ b/exporter/otlphttpexporter/otlp_test.go @@ -37,6 +37,41 @@ import ( "go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp" ) +const tracesTelemetryType = "traces" +const metricsTelemetryType = "metrics" +const logsTelemetryType = "logs" + +type responseSerializer interface { + MarshalJSON() ([]byte, error) + MarshalProto() ([]byte, error) +} + +type responseSerializerProvider = func() responseSerializer + +func provideTracesResponseSerializer() responseSerializer { + response := ptraceotlp.NewExportResponse() + partial := response.PartialSuccess() + partial.SetErrorMessage("hello") + partial.SetRejectedSpans(1) + return response +} + +func provideMetricsResponseSerializer() responseSerializer { + response := pmetricotlp.NewExportResponse() + partial := response.PartialSuccess() + partial.SetErrorMessage("hello") + partial.SetRejectedDataPoints(1) + return response +} + +func provideLogsResponseSerializer() responseSerializer { + response := plogotlp.NewExportResponse() + partial := response.PartialSuccess() + partial.SetErrorMessage("hello") + partial.SetRejectedLogRecords(1) + return response +} + 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) @@ -93,12 +128,12 @@ func TestErrorResponses(t *testing.T) { isPermErr: true, }, { - name: "419", + name: "429", responseStatus: http.StatusTooManyRequests, - responseBody: status.New(codes.InvalidArgument, "Quota exceeded"), + responseBody: status.New(codes.ResourceExhausted, "Quota exceeded"), err: func(srv *httptest.Server) error { return exporterhelper.NewThrottleRetry( - errors.New(errMsgPrefix(srv)+"429, Message=Quota exceeded, Details=[]"), + status.New(codes.ResourceExhausted, errMsgPrefix(srv)+"429, Message=Quota exceeded, Details=[]").Err(), time.Duration(0)*time.Second) }, }, @@ -114,7 +149,7 @@ func TestErrorResponses(t *testing.T) { responseBody: status.New(codes.InvalidArgument, "Bad gateway"), err: func(srv *httptest.Server) error { return exporterhelper.NewThrottleRetry( - errors.New(errMsgPrefix(srv)+"502, Message=Bad gateway, Details=[]"), + status.New(codes.Unavailable, errMsgPrefix(srv)+"502, Message=Bad gateway, Details=[]").Err(), time.Duration(0)*time.Second) }, }, @@ -124,7 +159,7 @@ func TestErrorResponses(t *testing.T) { responseBody: status.New(codes.InvalidArgument, "Server overloaded"), err: func(srv *httptest.Server) error { return exporterhelper.NewThrottleRetry( - errors.New(errMsgPrefix(srv)+"503, Message=Server overloaded, Details=[]"), + status.New(codes.Unavailable, errMsgPrefix(srv)+"503, Message=Server overloaded, Details=[]").Err(), time.Duration(0)*time.Second) }, }, @@ -135,7 +170,7 @@ func TestErrorResponses(t *testing.T) { headers: map[string]string{"Retry-After": "30"}, err: func(srv *httptest.Server) error { return exporterhelper.NewThrottleRetry( - errors.New(errMsgPrefix(srv)+"503, Message=Server overloaded, Details=[]"), + status.New(codes.Unavailable, errMsgPrefix(srv)+"503, Message=Server overloaded, Details=[]").Err(), time.Duration(30)*time.Second) }, }, @@ -145,7 +180,7 @@ func TestErrorResponses(t *testing.T) { responseBody: status.New(codes.InvalidArgument, "Gateway timeout"), err: func(srv *httptest.Server) error { return exporterhelper.NewThrottleRetry( - errors.New(errMsgPrefix(srv)+"504, Message=Gateway timeout, Details=[]"), + status.New(codes.Unavailable, errMsgPrefix(srv)+"504, Message=Gateway timeout, Details=[]").Err(), time.Duration(0)*time.Second) }, }, @@ -155,7 +190,7 @@ func TestErrorResponses(t *testing.T) { responseBody: status.New(codes.InvalidArgument, strings.Repeat("a", maxHTTPResponseReadBytes+1)), err: func(srv *httptest.Server) error { return exporterhelper.NewThrottleRetry( - errors.New(errMsgPrefix(srv)+"503"), + status.New(codes.Unavailable, errMsgPrefix(srv)+"503").Err(), time.Duration(0)*time.Second) }, }, @@ -467,22 +502,66 @@ func TestPartialResponse_missingHeaderButHasBody(t *testing.T) { exp, err := newExporter(cfg, set) require.NoError(t, err) - response := ptraceotlp.NewExportResponse() - partial := response.PartialSuccess() - partial.SetErrorMessage("hello") - partial.SetRejectedSpans(1) - data, err := response.MarshalProto() - 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(bytes.NewReader(data)), - Header: map[string][]string{ - "Content-Type": {"application/x-protobuf"}, + contentTypes := []struct { + contentType string + }{ + {contentType: protobufContentType}, + {contentType: jsonContentType}, + } + + telemetryTypes := []struct { + telemetryType string + handler partialSuccessHandler + serializer responseSerializerProvider + }{ + { + telemetryType: tracesTelemetryType, + handler: exp.tracesPartialSuccessHandler, + serializer: provideTracesResponseSerializer, + }, + { + telemetryType: metricsTelemetryType, + handler: exp.metricsPartialSuccessHandler, + serializer: provideMetricsResponseSerializer, + }, + { + telemetryType: logsTelemetryType, + handler: exp.logsPartialSuccessHandler, + serializer: provideLogsResponseSerializer, }, } - err = handlePartialSuccessResponse(resp, exp.tracesPartialSuccessHandler) - assert.NoError(t, err) + + for _, ct := range contentTypes { + for _, tt := range telemetryTypes { + t.Run(tt.telemetryType+" "+ct.contentType, func(t *testing.T) { + serializer := tt.serializer() + + var data []byte + var err error + + switch ct.contentType { + case jsonContentType: + data, err = serializer.MarshalJSON() + case protobufContentType: + data, err = serializer.MarshalProto() + default: + require.Fail(t, "unsupported content type: %s", ct.contentType) + } + 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(bytes.NewReader(data)), + Header: map[string][]string{ + "Content-Type": {ct.contentType}, + }, + } + err = handlePartialSuccessResponse(resp, tt.handler) + assert.NoError(t, err) + }) + } + } } func TestPartialResponse_missingHeaderAndBody(t *testing.T) { @@ -491,16 +570,47 @@ func TestPartialResponse_missingHeaderAndBody(t *testing.T) { 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(bytes.NewReader([]byte{})), - Header: map[string][]string{ - "Content-Type": {"application/x-protobuf"}, + contentTypes := []struct { + contentType string + }{ + {contentType: protobufContentType}, + {contentType: jsonContentType}, + } + + telemetryTypes := []struct { + telemetryType string + handler partialSuccessHandler + }{ + { + telemetryType: tracesTelemetryType, + handler: exp.tracesPartialSuccessHandler, + }, + { + telemetryType: metricsTelemetryType, + handler: exp.metricsPartialSuccessHandler, + }, + { + telemetryType: logsTelemetryType, + handler: exp.logsPartialSuccessHandler, }, } - err = handlePartialSuccessResponse(resp, exp.tracesPartialSuccessHandler) - assert.Nil(t, err) + + for _, ct := range contentTypes { + for _, tt := range telemetryTypes { + t.Run(tt.telemetryType+" "+ct.contentType, func(t *testing.T) { + resp := &http.Response{ + // `-1` indicates a missing Content-Length header in the Go http standard library + ContentLength: -1, + Body: io.NopCloser(bytes.NewReader([]byte{})), + Header: map[string][]string{ + "Content-Type": {ct.contentType}, + }, + } + err = handlePartialSuccessResponse(resp, tt.handler) + assert.Nil(t, err) + }) + } + } } func TestPartialResponse_nonErrUnexpectedEOFError(t *testing.T) { @@ -524,53 +634,147 @@ func TestPartialSuccess_shortContentLengthHeader(t *testing.T) { exp, err := newExporter(cfg, set) require.NoError(t, err) - response := ptraceotlp.NewExportResponse() - partial := response.PartialSuccess() - partial.SetErrorMessage("hello") - partial.SetRejectedSpans(1) - data, err := response.MarshalProto() - require.NoError(t, err) - resp := &http.Response{ - ContentLength: 3, - Body: io.NopCloser(bytes.NewReader(data)), - Header: map[string][]string{ - "Content-Type": {"application/x-protobuf"}, + contentTypes := []struct { + contentType string + }{ + {contentType: protobufContentType}, + {contentType: jsonContentType}, + } + + telemetryTypes := []struct { + telemetryType string + handler partialSuccessHandler + serializer responseSerializerProvider + }{ + { + telemetryType: tracesTelemetryType, + handler: exp.tracesPartialSuccessHandler, + serializer: provideTracesResponseSerializer, + }, + { + telemetryType: metricsTelemetryType, + handler: exp.metricsPartialSuccessHandler, + serializer: provideMetricsResponseSerializer, + }, + { + telemetryType: logsTelemetryType, + handler: exp.logsPartialSuccessHandler, + serializer: provideLogsResponseSerializer, }, } - // For short content-length, a real error happens. - err = handlePartialSuccessResponse(resp, exp.tracesPartialSuccessHandler) - assert.Error(t, err) + + for _, ct := range contentTypes { + for _, tt := range telemetryTypes { + t.Run(tt.telemetryType+" "+ct.contentType, func(t *testing.T) { + serializer := tt.serializer() + + var data []byte + var err error + + switch ct.contentType { + case jsonContentType: + data, err = serializer.MarshalJSON() + case protobufContentType: + data, err = serializer.MarshalProto() + default: + require.Fail(t, "unsupported content type: %s", ct.contentType) + } + require.NoError(t, err) + + resp := &http.Response{ + ContentLength: 3, + Body: io.NopCloser(bytes.NewReader(data)), + Header: map[string][]string{ + "Content-Type": {ct.contentType}, + }, + } + // For short content-length, a real error happens. + err = handlePartialSuccessResponse(resp, tt.handler) + assert.Error(t, err) + }) + } + } } func TestPartialSuccess_longContentLengthHeader(t *testing.T) { - cfg := createDefaultConfig() - set := exportertest.NewNopCreateSettings() + contentTypes := []struct { + contentType string + }{ + {contentType: protobufContentType}, + {contentType: jsonContentType}, + } - logger, observed := observer.New(zap.DebugLevel) - set.TelemetrySettings.Logger = zap.New(logger) + telemetryTypes := []struct { + telemetryType string + serializer responseSerializerProvider + }{ + { + telemetryType: tracesTelemetryType, + serializer: provideTracesResponseSerializer, + }, + { + telemetryType: metricsTelemetryType, + serializer: provideMetricsResponseSerializer, + }, + { + telemetryType: logsTelemetryType, + serializer: provideLogsResponseSerializer, + }, + } - exp, err := newExporter(cfg, set) - require.NoError(t, err) + for _, ct := range contentTypes { + for _, tt := range telemetryTypes { + t.Run(tt.telemetryType+" "+ct.contentType, func(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") - partial.SetRejectedSpans(1) - data, err := response.MarshalProto() - require.NoError(t, err) - resp := &http.Response{ - ContentLength: 4096, - Body: io.NopCloser(bytes.NewReader(data)), - Header: map[string][]string{ - "Content-Type": {"application/x-protobuf"}, - }, + serializer := tt.serializer() + + var handler partialSuccessHandler + + switch tt.telemetryType { + case tracesTelemetryType: + handler = exp.tracesPartialSuccessHandler + case metricsTelemetryType: + handler = exp.metricsPartialSuccessHandler + case logsTelemetryType: + handler = exp.logsPartialSuccessHandler + default: + require.Fail(t, "unsupported telemetry type: %s", ct.contentType) + } + + var data []byte + + switch ct.contentType { + case jsonContentType: + data, err = serializer.MarshalJSON() + case protobufContentType: + data, err = serializer.MarshalProto() + default: + require.Fail(t, "unsupported content type: %s", ct.contentType) + } + require.NoError(t, err) + + resp := &http.Response{ + ContentLength: 4096, + Body: io.NopCloser(bytes.NewReader(data)), + Header: map[string][]string{ + "Content-Type": {ct.contentType}, + }, + } + // No real error happens for long content length, so the partial + // success is handled as success with a warning. + err = handlePartialSuccessResponse(resp, handler) + 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") + }) + } } - // 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) { diff --git a/extension/auth/go.mod b/extension/auth/go.mod index 8b1b0ba6a45..661499d5720 100644 --- a/extension/auth/go.mod +++ b/extension/auth/go.mod @@ -3,11 +3,11 @@ module go.opentelemetry.io/collector/extension/auth go 1.21 require ( - github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.96.0 - go.opentelemetry.io/collector/extension v0.96.0 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/extension v0.100.0 go.uber.org/goleak v1.3.0 - google.golang.org/grpc v1.62.0 + google.golang.org/grpc v1.63.2 ) require ( @@ -18,33 +18,32 @@ require ( 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.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/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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/confmap v0.100.0 // indirect + go.opentelemetry.io/collector/pdata v1.7.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/metric v1.26.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.opentelemetry.io/otel/trace v1.26.0 // indirect go.uber.org/multierr v1.11.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/net v0.23.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/extension/auth/go.sum b/extension/auth/go.sum index 2f664245ecd..5467b123e44 100644 --- a/extension/auth/go.sum +++ b/extension/auth/go.sum @@ -13,10 +13,6 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -25,8 +21,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -39,30 +35,30 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.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.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -78,16 +74,16 @@ 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.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -100,14 +96,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/extension/ballastextension/generated_component_test.go b/extension/ballastextension/generated_component_test.go new file mode 100644 index 00000000000..779e5631778 --- /dev/null +++ b/extension/ballastextension/generated_component_test.go @@ -0,0 +1,51 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package ballastextension + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/extension/extensiontest" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "memory_ballast", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +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) { + 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())) + }) +} diff --git a/extension/ballastextension/package_test.go b/extension/ballastextension/generated_package_test.go similarity index 62% rename from extension/ballastextension/package_test.go rename to extension/ballastextension/generated_package_test.go index 9035e22edbc..3f80a3e2754 100644 --- a/extension/ballastextension/package_test.go +++ b/extension/ballastextension/generated_package_test.go @@ -1,5 +1,4 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 +// Code generated by mdatagen. DO NOT EDIT. package ballastextension diff --git a/extension/ballastextension/go.mod b/extension/ballastextension/go.mod index a6035aa3fca..8d895a863d1 100644 --- a/extension/ballastextension/go.mod +++ b/extension/ballastextension/go.mod @@ -4,13 +4,13 @@ module go.opentelemetry.io/collector/extension/ballastextension 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/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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/extension v0.100.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.0 go.uber.org/goleak v1.3.0 go.uber.org/zap v1.27.0 ) @@ -24,36 +24,36 @@ require ( 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/google/uuid 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.1 // 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/shirou/gopsutil/v3 v3.24.1 // indirect + github.com/shirou/gopsutil/v3 v3.24.3 // 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/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 + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/pdata v1.7.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.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/net v0.24.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -77,3 +77,5 @@ retract ( ) replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry + +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata diff --git a/extension/ballastextension/go.sum b/extension/ballastextension/go.sum index 9394f812d28..6d9bf441a16 100644 --- a/extension/ballastextension/go.sum +++ b/extension/ballastextension/go.sum @@ -16,22 +16,20 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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/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/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -48,45 +46,47 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF 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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE= +github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg= 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/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 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= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -102,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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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= @@ -114,9 +114,9 @@ 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.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/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -129,14 +129,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/extension/ballastextension/internal/metadata/generated_status.go b/extension/ballastextension/internal/metadata/generated_status.go index c6407064c52..54e3d38805d 100644 --- a/extension/ballastextension/internal/metadata/generated_status.go +++ b/extension/ballastextension/internal/metadata/generated_status.go @@ -3,25 +3,13 @@ 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" + Type = component.MustNewType("memory_ballast") ) 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/internal/metadata/generated_telemetry.go b/extension/ballastextension/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..ddd7d808462 --- /dev/null +++ b/extension/ballastextension/internal/metadata/generated_telemetry.go @@ -0,0 +1,18 @@ +// 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" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/extension/ballastextension") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/extension/ballastextension") +} diff --git a/extension/ballastextension/internal/metadata/generated_telemetry_test.go b/extension/ballastextension/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..6eeac05298b --- /dev/null +++ b/extension/ballastextension/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/extension/ballastextension", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/extension/ballastextension", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/extension/extensiontest/nop_extension.go b/extension/extensiontest/nop_extension.go index f92ff388d94..134eee042a7 100644 --- a/extension/extensiontest/nop_extension.go +++ b/extension/extensiontest/nop_extension.go @@ -6,6 +6,8 @@ package extensiontest // import "go.opentelemetry.io/collector/extension/extensi import ( "context" + "github.com/google/uuid" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/extension" @@ -16,7 +18,7 @@ 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), + ID: component.NewIDWithName(nopType, uuid.NewString()), TelemetrySettings: componenttest.NewNopTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo(), } diff --git a/extension/go.mod b/extension/go.mod index 61adfe39b85..c6f3813997e 100644 --- a/extension/go.mod +++ b/extension/go.mod @@ -3,9 +3,10 @@ module go.opentelemetry.io/collector/extension go 1.21 require ( - github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/collector/component v0.96.0 - go.opentelemetry.io/collector/confmap v0.96.0 + github.com/google/uuid v1.6.0 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 go.uber.org/goleak v1.3.0 ) @@ -17,33 +18,32 @@ require ( 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.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/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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/pdata v1.7.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/metric v1.26.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.opentelemetry.io/otel/trace v1.26.0 // indirect go.uber.org/multierr v1.11.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/net v0.23.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/extension/go.sum b/extension/go.sum index 2f664245ecd..a0f02ecceb9 100644 --- a/extension/go.sum +++ b/extension/go.sum @@ -13,20 +13,18 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -39,30 +37,30 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.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.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -78,16 +76,16 @@ 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.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -100,14 +98,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/extension/memorylimiterextension/generated_component_test.go b/extension/memorylimiterextension/generated_component_test.go new file mode 100644 index 00000000000..7580d8a30c9 --- /dev/null +++ b/extension/memorylimiterextension/generated_component_test.go @@ -0,0 +1,45 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package memorylimiterextension + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/extension/extensiontest" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "memory_limiter", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +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("lifecycle", func(t *testing.T) { + 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())) + }) +} diff --git a/extension/memorylimiterextension/generated_package_test.go b/extension/memorylimiterextension/generated_package_test.go new file mode 100644 index 00000000000..92a130658b4 --- /dev/null +++ b/extension/memorylimiterextension/generated_package_test.go @@ -0,0 +1,13 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package memorylimiterextension + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/extension/memorylimiterextension/go.mod b/extension/memorylimiterextension/go.mod index b44b779bdc9..3a10b662bd5 100644 --- a/extension/memorylimiterextension/go.mod +++ b/extension/memorylimiterextension/go.mod @@ -3,12 +3,14 @@ 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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/extension v0.100.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.0 + go.uber.org/goleak v1.3.0 go.uber.org/zap v1.27.0 ) @@ -21,37 +23,36 @@ require ( 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/google/uuid 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.1 // 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/shirou/gopsutil/v3 v3.24.1 // indirect + github.com/shirou/gopsutil/v3 v3.24.3 // 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 + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/pdata v1.7.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.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/net v0.24.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -70,3 +71,5 @@ replace go.opentelemetry.io/collector/pdata => ../../pdata replace go.opentelemetry.io/collector/consumer => ../../consumer replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry + +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata diff --git a/extension/memorylimiterextension/go.sum b/extension/memorylimiterextension/go.sum index 9394f812d28..6d9bf441a16 100644 --- a/extension/memorylimiterextension/go.sum +++ b/extension/memorylimiterextension/go.sum @@ -16,22 +16,20 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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/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/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -48,45 +46,47 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF 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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE= +github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg= 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/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 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= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -102,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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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= @@ -114,9 +114,9 @@ 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.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/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -129,14 +129,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/extension/memorylimiterextension/internal/metadata/generated_status.go b/extension/memorylimiterextension/internal/metadata/generated_status.go index 5f0f98ec044..21472c5d5aa 100644 --- a/extension/memorylimiterextension/internal/metadata/generated_status.go +++ b/extension/memorylimiterextension/internal/metadata/generated_status.go @@ -3,25 +3,13 @@ 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" + Type = component.MustNewType("memory_limiter") ) 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/internal/metadata/generated_telemetry.go b/extension/memorylimiterextension/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..c90ad7e67da --- /dev/null +++ b/extension/memorylimiterextension/internal/metadata/generated_telemetry.go @@ -0,0 +1,18 @@ +// 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" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/extension/memorylimiterextension") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/extension/memorylimiterextension") +} diff --git a/extension/memorylimiterextension/internal/metadata/generated_telemetry_test.go b/extension/memorylimiterextension/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..b2c1e454273 --- /dev/null +++ b/extension/memorylimiterextension/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/extension/memorylimiterextension", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/extension/memorylimiterextension", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/extension/memorylimiterextension/metadata.yaml b/extension/memorylimiterextension/metadata.yaml index 75f16b8f750..26cafc9b5ad 100644 --- a/extension/memorylimiterextension/metadata.yaml +++ b/extension/memorylimiterextension/metadata.yaml @@ -5,3 +5,11 @@ status: stability: development: [extension] distributions: [] + +tests: + config: + check_interval: 5s + limit_mib: 400 + spike_limit_mib: 50 + # TODO: https://github.com/open-telemetry/opentelemetry-collector/issues/9686 + skip_shutdown: true diff --git a/extension/zpagesextension/generated_component_test.go b/extension/zpagesextension/generated_component_test.go new file mode 100644 index 00000000000..df6ede48a05 --- /dev/null +++ b/extension/zpagesextension/generated_component_test.go @@ -0,0 +1,51 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package zpagesextension + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/extension/extensiontest" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "zpages", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +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) { + 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())) + }) +} diff --git a/extension/zpagesextension/package_test.go b/extension/zpagesextension/generated_package_test.go similarity index 62% rename from extension/zpagesextension/package_test.go rename to extension/zpagesextension/generated_package_test.go index 40ce0f11cc4..a34cf6a2031 100644 --- a/extension/zpagesextension/package_test.go +++ b/extension/zpagesextension/generated_package_test.go @@ -1,5 +1,4 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 +// Code generated by mdatagen. DO NOT EDIT. package zpagesextension diff --git a/extension/zpagesextension/go.mod b/extension/zpagesextension/go.mod index 4e795a8d6ac..1af25bfbed5 100644 --- a/extension/zpagesextension/go.mod +++ b/extension/zpagesextension/go.mod @@ -3,60 +3,63 @@ module go.opentelemetry.io/collector/extension/zpagesextension 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/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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/config/confignet v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/extension v0.100.0 + go.opentelemetry.io/contrib/zpages v0.51.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/sdk v1.26.0 + go.opentelemetry.io/otel/trace v1.26.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/cenkalti/backoff/v4 v4.3.0 // 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/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.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/knadh/koanf/v2 v2.1.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/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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/pdata v1.7.0 // indirect + go.opentelemetry.io/contrib/config v0.6.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.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/net v0.24.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -82,3 +85,5 @@ retract ( ) replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry + +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata diff --git a/extension/zpagesextension/go.sum b/extension/zpagesextension/go.sum index 1210952ad72..fe7454c4610 100644 --- a/extension/zpagesextension/go.sum +++ b/extension/zpagesextension/go.sum @@ -1,7 +1,7 @@ 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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/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= @@ -15,22 +15,20 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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/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.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= 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/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -43,44 +41,50 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/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.opentelemetry.io/contrib/config v0.6.0 h1:M1SRD1Z15XHPGk61tMLI1up77XT5FdrqQSRrlH0fYuk= +go.opentelemetry.io/contrib/config v0.6.0/go.mod h1:t+/kzmRWLN7J+4F/dD4fFvlYCmCO63WYwy/B00IC++c= +go.opentelemetry.io/contrib/zpages v0.51.0 h1:psVr4JTWd0qtISPj9EA6AODGJ09bvsOxWiuKqiGdSCA= +go.opentelemetry.io/contrib/zpages v0.51.0/go.mod h1:PKtp+NEp1gTTLmFHpynYgYCSkKtisPntOb9S1mQjFKg= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 h1:+hm+I+KigBy3M24/h1p/NHkUx/evbLH0PNcjpMyCHc4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0/go.mod h1:NjC8142mLvvNT6biDpaMjyz78kyEHIwAJlSX0N9P5KI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 h1:HGZWGmCVRCVyAs2GQaiHQPbDHo+ObFWeUEOd+zDnp64= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0/go.mod h1:SaH+v38LSCHddyk7RGlU9uZyQoRrKao6IBnJw6Kbn+c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 h1:1u/AyyOqAWzy+SkPxDpahCNZParHV8Vid1RnI2clyDE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0/go.mod h1:z46paqbJ9l7c9fIPCXTqTGwhQZ5XoTIsfeFYWboizjs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 h1:Waw9Wfpo/IXzOI8bCB7DIk+0JZcqqsyn1JFnAc+iam8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0/go.mod h1:wnJIG4fOqyynOnnQF/eQb4/16VlX2EJAHhHgqIqWfAo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 h1:1wp/gyxsuYtuE/JFxsQRtcCDtMrO2qMvlfXALU5wkzI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0/go.mod h1:gbTHmghkGgqxMomVQQMur1Nba4M0MQ8AYThXDUjsJ38= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 h1:5fnmgteaar1VcAA69huatudPduNFz7guRtCmfZCooZI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0/go.mod h1:lsPccfZiz1cb1AhBPmicWM2E4F1VynFXEvD8SEBS4TM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 h1:0W5o9SzoR15ocYHEQfvfipzcNog1lBxOLfnex91Hk6s= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0/go.mod h1:zVZ8nz+VSggWmnh6tTsJqXQ7rU4xLwRtna1M4x5jq58= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= 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= @@ -96,16 +100,16 @@ 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -118,18 +122,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 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= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/extension/zpagesextension/internal/metadata/generated_status.go b/extension/zpagesextension/internal/metadata/generated_status.go index 21ba9b8e88e..ee7c714b77a 100644 --- a/extension/zpagesextension/internal/metadata/generated_status.go +++ b/extension/zpagesextension/internal/metadata/generated_status.go @@ -3,25 +3,13 @@ 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" + Type = component.MustNewType("zpages") ) 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/internal/metadata/generated_telemetry.go b/extension/zpagesextension/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..d545bbbe394 --- /dev/null +++ b/extension/zpagesextension/internal/metadata/generated_telemetry.go @@ -0,0 +1,18 @@ +// 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" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/extension/zpagesextension") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/extension/zpagesextension") +} diff --git a/extension/zpagesextension/internal/metadata/generated_telemetry_test.go b/extension/zpagesextension/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..53ce3364bc1 --- /dev/null +++ b/extension/zpagesextension/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/extension/zpagesextension", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/extension/zpagesextension", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/featuregate/go.mod b/featuregate/go.mod index 4382445ec39..8f955c5df51 100644 --- a/featuregate/go.mod +++ b/featuregate/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/hashicorp/go-version v1.6.0 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 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 f198f93ff2e..f57a6bb525d 100644 --- a/featuregate/go.sum +++ b/featuregate/go.sum @@ -16,8 +16,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN 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= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= diff --git a/filter/Makefile b/filter/Makefile new file mode 100644 index 00000000000..39734bfaebb --- /dev/null +++ b/filter/Makefile @@ -0,0 +1 @@ +include ../Makefile.Common diff --git a/filter/config.go b/filter/config.go new file mode 100644 index 00000000000..e5b12c4f014 --- /dev/null +++ b/filter/config.go @@ -0,0 +1,72 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package filter // import "go.opentelemetry.io/collector/filter" + +import ( + "errors" + "regexp" +) + +// Config configures the matching behavior of a FilterSet. +type Config struct { + Strict string `mapstructure:"strict"` + Regex string `mapstructure:"regexp"` +} + +func (c Config) Validate() error { + if c.Strict == "" && c.Regex == "" { + return errors.New("must specify either strict or regex") + } + if c.Strict != "" && c.Regex != "" { + return errors.New("strict and regex cannot be used together") + } + + if c.Regex != "" { + _, err := regexp.Compile(c.Regex) + if err != nil { + return err + } + } + + return nil +} + +type CombinedFilter struct { + stricts map[any]struct{} + regexes []*regexp.Regexp +} + +// CreateFilter creates a Filter from yaml config. +func CreateFilter(configs []Config) Filter { + cf := &CombinedFilter{ + stricts: make(map[any]struct{}), + } + for _, config := range configs { + if config.Strict != "" { + cf.stricts[config.Strict] = struct{}{} + } + + if config.Regex != "" { + // Validate() call above ensures that the regex is valid. + re := regexp.MustCompile(config.Regex) + cf.regexes = append(cf.regexes, re) + } + } + return cf +} + +func (cf *CombinedFilter) Matches(toMatch any) bool { + _, ok := cf.stricts[toMatch] + if ok { + return ok + } + if str, ok := toMatch.(string); ok { + for _, re := range cf.regexes { + if re.MatchString(str) { + return true + } + } + } + return false +} diff --git a/filter/config_test.go b/filter/config_test.go new file mode 100644 index 00000000000..c321580ed40 --- /dev/null +++ b/filter/config_test.go @@ -0,0 +1,113 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package filter + +import ( + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/confmap" + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func readTestdataConfigYamls(t *testing.T, filename string) map[string][]Config { + testFile := filepath.Join("testdata", filename) + v, err := confmaptest.LoadConf(testFile) + require.NoError(t, err) + + cfgs := map[string][]Config{} + require.NoErrorf(t, v.Unmarshal(&cfgs, confmap.WithIgnoreUnused()), "unable to unmarshal yaml from file %v", testFile) + return cfgs +} + +func TestConfig(t *testing.T) { + actualConfigs := readTestdataConfigYamls(t, "config.yaml") + expectedConfigs := map[string][]Config{ + "regexp/default": { + { + Regex: "one|two", + }, + }, + "strict/default": { + { + Strict: "strict", + }, + }, + } + + for testName, actualCfg := range actualConfigs { + t.Run(testName, func(t *testing.T) { + expCfg, ok := expectedConfigs[testName] + assert.True(t, ok) + assert.Equal(t, expCfg, actualCfg) + + for _, cfg := range actualCfg { + assert.NoError(t, cfg.Validate()) + } + fs := CreateFilter(actualCfg) + assert.NotNil(t, fs) + }) + } +} + +func TestMatches(t *testing.T) { + cfg := []Config{ + { + Strict: "a", + }, + { + Strict: "b", + }, + { + Regex: "a|b|c", + }, + } + + for _, c := range cfg { + assert.NoError(t, c.Validate()) + } + fs := CreateFilter(cfg) + + assert.True(t, fs.Matches("a")) + assert.True(t, fs.Matches("b")) + assert.True(t, fs.Matches("c")) +} + +func TestConfigInvalid(t *testing.T) { + actualConfigs := readTestdataConfigYamls(t, "config_invalid.yaml") + expectedConfigs := map[string][]Config{ + "invalid/regexp": { + { + Regex: "(.*[", + }, + }, + "invalid/config_empty": { + { + Regex: "", + Strict: "", + }, + }, + "invalid/config_both_set": { + { + Regex: "1", + Strict: "1", + }, + }, + } + + for testName, actualCfg := range actualConfigs { + t.Run(testName, func(t *testing.T) { + expCfg, ok := expectedConfigs[testName] + assert.True(t, ok) + assert.Equal(t, expCfg, actualCfg) + + for _, cfg := range actualCfg { + assert.Error(t, cfg.Validate()) + } + }) + } +} diff --git a/filter/doc.go b/filter/doc.go new file mode 100644 index 00000000000..3750c1ccd76 --- /dev/null +++ b/filter/doc.go @@ -0,0 +1,5 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package filter provides an interface for matching strings against a set of string filters. +package filter // import "go.opentelemetry.io/collector/filter" diff --git a/filter/filter.go b/filter/filter.go new file mode 100644 index 00000000000..4bee571fdde --- /dev/null +++ b/filter/filter.go @@ -0,0 +1,11 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package filter // import "go.opentelemetry.io/collector/filter" + +// Filter is an interface for matching values against a set of filters. +type Filter interface { + // Matches returns true if the given value matches at least one + // of the filters encapsulated by the Filter. + Matches(any) bool +} diff --git a/filter/go.mod b/filter/go.mod new file mode 100644 index 00000000000..16234c14a89 --- /dev/null +++ b/filter/go.mod @@ -0,0 +1,24 @@ +module go.opentelemetry.io/collector/filter + +go 1.21 + +require ( + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/confmap v0.100.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.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 + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace go.opentelemetry.io/collector/confmap => ../confmap diff --git a/filter/go.sum b/filter/go.sum new file mode 100644 index 00000000000..4fac02f5c47 --- /dev/null +++ b/filter/go.sum @@ -0,0 +1,28 @@ +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.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +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= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/filter/testdata/config.yaml b/filter/testdata/config.yaml new file mode 100644 index 00000000000..82778b24f34 --- /dev/null +++ b/filter/testdata/config.yaml @@ -0,0 +1,8 @@ +# Yaml form of the configuration for Filters +# This configuration can be embedded into other component's yamls +# The top level here are just test names and do not represent part of the actual configuration. + +regexp/default: + - regexp: "one|two" +strict/default: + - strict: "strict" diff --git a/filter/testdata/config_invalid.yaml b/filter/testdata/config_invalid.yaml new file mode 100644 index 00000000000..4e7bc85e6f4 --- /dev/null +++ b/filter/testdata/config_invalid.yaml @@ -0,0 +1,12 @@ +# Yaml form of the configuration for Filters +# This configuration can be embedded into other component's yamls +# The top level here are just test names and do not represent part of the actual configuration. + +invalid/regexp: + - regexp: "(.*[" +invalid/config_empty: + - regexp: "" + strict: "" +invalid/config_both_set: + - regexp: "1" + strict: "1" diff --git a/go.mod b/go.mod index 79c836ef8ef..0b0e01d1d21 100644 --- a/go.mod +++ b/go.mod @@ -3,22 +3,24 @@ module go.opentelemetry.io/collector go 1.21 require ( - github.com/shirou/gopsutil/v3 v3.24.1 - 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/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 + github.com/shirou/gopsutil/v3 v3.24.3 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/featuregate v1.7.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/collector/pdata/testdata v0.100.0 + go.opentelemetry.io/contrib/config v0.6.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 + google.golang.org/grpc v1.63.2 ) require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // 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 @@ -26,13 +28,12 @@ require ( 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/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.1 // 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 @@ -41,31 +42,33 @@ require ( 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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/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 + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 // indirect + go.opentelemetry.io/otel/metric v1.26.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.opentelemetry.io/otel/trace v1.26.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -81,6 +84,8 @@ replace go.opentelemetry.io/collector/featuregate => ./featuregate replace go.opentelemetry.io/collector/pdata => ./pdata +replace go.opentelemetry.io/collector/pdata/testdata => ./pdata/testdata + 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 f060cc531e2..3ce50f26a17 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ 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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -18,17 +18,13 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= 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= @@ -39,8 +35,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -62,58 +58,66 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF 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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/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.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE= +github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg= 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/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 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/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= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/contrib/config v0.6.0 h1:M1SRD1Z15XHPGk61tMLI1up77XT5FdrqQSRrlH0fYuk= +go.opentelemetry.io/contrib/config v0.6.0/go.mod h1:t+/kzmRWLN7J+4F/dD4fFvlYCmCO63WYwy/B00IC++c= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 h1:+hm+I+KigBy3M24/h1p/NHkUx/evbLH0PNcjpMyCHc4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0/go.mod h1:NjC8142mLvvNT6biDpaMjyz78kyEHIwAJlSX0N9P5KI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 h1:HGZWGmCVRCVyAs2GQaiHQPbDHo+ObFWeUEOd+zDnp64= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0/go.mod h1:SaH+v38LSCHddyk7RGlU9uZyQoRrKao6IBnJw6Kbn+c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 h1:1u/AyyOqAWzy+SkPxDpahCNZParHV8Vid1RnI2clyDE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0/go.mod h1:z46paqbJ9l7c9fIPCXTqTGwhQZ5XoTIsfeFYWboizjs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 h1:Waw9Wfpo/IXzOI8bCB7DIk+0JZcqqsyn1JFnAc+iam8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0/go.mod h1:wnJIG4fOqyynOnnQF/eQb4/16VlX2EJAHhHgqIqWfAo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 h1:1wp/gyxsuYtuE/JFxsQRtcCDtMrO2qMvlfXALU5wkzI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0/go.mod h1:gbTHmghkGgqxMomVQQMur1Nba4M0MQ8AYThXDUjsJ38= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 h1:5fnmgteaar1VcAA69huatudPduNFz7guRtCmfZCooZI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0/go.mod h1:lsPccfZiz1cb1AhBPmicWM2E4F1VynFXEvD8SEBS4TM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 h1:0W5o9SzoR15ocYHEQfvfipzcNog1lBxOLfnex91Hk6s= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0/go.mod h1:zVZ8nz+VSggWmnh6tTsJqXQ7rU4xLwRtna1M4x5jq58= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= 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= @@ -129,8 +133,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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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= @@ -141,9 +145,9 @@ 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.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/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -156,18 +160,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 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= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/internal/e2e/go.mod b/internal/e2e/go.mod index 70e5da18f40..7ba98c47f7d 100644 --- a/internal/e2e/go.mod +++ b/internal/e2e/go.mod @@ -3,26 +3,27 @@ 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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/config/configgrpc v0.100.0 + go.opentelemetry.io/collector/config/confighttp v0.100.0 + go.opentelemetry.io/collector/config/configretry v0.100.0 + go.opentelemetry.io/collector/config/configtls v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/exporter v0.100.0 + go.opentelemetry.io/collector/exporter/otlpexporter v0.99.0 + go.opentelemetry.io/collector/exporter/otlphttpexporter v0.99.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/collector/pdata/testdata v0.100.0 + go.opentelemetry.io/collector/receiver v0.100.0 + go.opentelemetry.io/collector/receiver/otlpreceiver v0.99.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/cenkalti/backoff/v4 v4.3.0 // 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 @@ -31,15 +32,15 @@ require ( 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/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // 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/klauspost/compress v1.17.8 // 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/knadh/koanf/v2 v2.1.1 // 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 @@ -47,43 +48,46 @@ require ( 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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.opentelemetry.io/collector/config/configauth v0.100.0 // indirect + go.opentelemetry.io/collector/config/configcompression v1.7.0 // indirect + go.opentelemetry.io/collector/config/confignet v0.100.0 // indirect + go.opentelemetry.io/collector/config/configopaque v1.7.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/config/internal v0.100.0 // indirect + go.opentelemetry.io/collector/confmap v0.100.0 // indirect + go.opentelemetry.io/collector/extension v0.100.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.100.0 // indirect + go.opentelemetry.io/collector/featuregate v1.7.0 // indirect + go.opentelemetry.io/contrib/config v0.6.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 // indirect + go.opentelemetry.io/otel/metric v1.26.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.opentelemetry.io/otel/trace v1.26.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.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/net v0.24.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -115,6 +119,8 @@ replace go.opentelemetry.io/collector/exporter/otlphttpexporter => ../../exporte replace go.opentelemetry.io/collector/pdata => ../../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata + replace go.opentelemetry.io/collector/consumer => ../../consumer replace go.opentelemetry.io/collector/receiver/otlpreceiver => ../../receiver/otlpreceiver diff --git a/internal/e2e/go.sum b/internal/e2e/go.sum index 6dc69bb0e99..ee0cdcbf90e 100644 --- a/internal/e2e/go.sum +++ b/internal/e2e/go.sum @@ -1,20 +1,12 @@ -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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/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= @@ -28,31 +20,29 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= 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/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/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/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -72,50 +62,56 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/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/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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/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.opentelemetry.io/contrib/config v0.6.0 h1:M1SRD1Z15XHPGk61tMLI1up77XT5FdrqQSRrlH0fYuk= +go.opentelemetry.io/contrib/config v0.6.0/go.mod h1:t+/kzmRWLN7J+4F/dD4fFvlYCmCO63WYwy/B00IC++c= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 h1:A3SayB3rNyt+1S6qpI9mHPkeHTZbD7XILEqWnYZb2l0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0/go.mod h1:27iA5uvhuRNmalO+iEUdVn5ZMj2qy10Mm+XRIpRmyuU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 h1:Xs2Ncz0gNihqu9iosIZ5SkBbWo5T8JhhLJFMQL1qmLI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0/go.mod h1:vy+2G/6NvVMpwGX/NyLqcC41fxepnuKHk16E6IZUcJc= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 h1:+hm+I+KigBy3M24/h1p/NHkUx/evbLH0PNcjpMyCHc4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0/go.mod h1:NjC8142mLvvNT6biDpaMjyz78kyEHIwAJlSX0N9P5KI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 h1:HGZWGmCVRCVyAs2GQaiHQPbDHo+ObFWeUEOd+zDnp64= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0/go.mod h1:SaH+v38LSCHddyk7RGlU9uZyQoRrKao6IBnJw6Kbn+c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 h1:1u/AyyOqAWzy+SkPxDpahCNZParHV8Vid1RnI2clyDE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0/go.mod h1:z46paqbJ9l7c9fIPCXTqTGwhQZ5XoTIsfeFYWboizjs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 h1:Waw9Wfpo/IXzOI8bCB7DIk+0JZcqqsyn1JFnAc+iam8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0/go.mod h1:wnJIG4fOqyynOnnQF/eQb4/16VlX2EJAHhHgqIqWfAo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 h1:1wp/gyxsuYtuE/JFxsQRtcCDtMrO2qMvlfXALU5wkzI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0/go.mod h1:gbTHmghkGgqxMomVQQMur1Nba4M0MQ8AYThXDUjsJ38= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 h1:5fnmgteaar1VcAA69huatudPduNFz7guRtCmfZCooZI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0/go.mod h1:lsPccfZiz1cb1AhBPmicWM2E4F1VynFXEvD8SEBS4TM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 h1:0W5o9SzoR15ocYHEQfvfipzcNog1lBxOLfnex91Hk6s= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0/go.mod h1:zVZ8nz+VSggWmnh6tTsJqXQ7rU4xLwRtna1M4x5jq58= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= 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= @@ -131,18 +127,16 @@ 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.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/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -155,20 +149,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.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= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/internal/e2e/otlphttp_test.go b/internal/e2e/otlphttp_test.go index 59627ab4b17..b173dcf59d7 100644 --- a/internal/e2e/otlphttp_test.go +++ b/internal/e2e/otlphttp_test.go @@ -28,10 +28,10 @@ import ( "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/pdata/testdata" "go.opentelemetry.io/collector/receiver/otlpreceiver" "go.opentelemetry.io/collector/receiver/receivertest" ) diff --git a/internal/fanoutconsumer/logs_test.go b/internal/fanoutconsumer/logs_test.go index 8c247cb1232..c1b91a7a4e8 100644 --- a/internal/fanoutconsumer/logs_test.go +++ b/internal/fanoutconsumer/logs_test.go @@ -12,7 +12,7 @@ import ( "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" - "go.opentelemetry.io/collector/internal/testdata" + "go.opentelemetry.io/collector/pdata/testdata" ) func TestLogsNotMultiplexing(t *testing.T) { diff --git a/internal/fanoutconsumer/metrics_test.go b/internal/fanoutconsumer/metrics_test.go index efb39ec552a..51e00791a76 100644 --- a/internal/fanoutconsumer/metrics_test.go +++ b/internal/fanoutconsumer/metrics_test.go @@ -12,7 +12,7 @@ import ( "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" - "go.opentelemetry.io/collector/internal/testdata" + "go.opentelemetry.io/collector/pdata/testdata" ) func TestMetricsNotMultiplexing(t *testing.T) { diff --git a/internal/fanoutconsumer/traces_test.go b/internal/fanoutconsumer/traces_test.go index 120c6524715..829e4cd9069 100644 --- a/internal/fanoutconsumer/traces_test.go +++ b/internal/fanoutconsumer/traces_test.go @@ -12,7 +12,7 @@ import ( "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" - "go.opentelemetry.io/collector/internal/testdata" + "go.opentelemetry.io/collector/pdata/testdata" ) func TestTracesNotMultiplexing(t *testing.T) { diff --git a/internal/httphelper/helper.go b/internal/httphelper/helper.go new file mode 100644 index 00000000000..be7d4a3a986 --- /dev/null +++ b/internal/httphelper/helper.go @@ -0,0 +1,36 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package httphelper // import "go.opentelemetry.io/collector/internal/httphelper" + +import ( + "net/http" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// NewStatusFromMsgAndHTTPCode returns a gRPC status based on an error message string and a http status code. +// This function is shared between the http receiver and http exporter for error propagation. +func NewStatusFromMsgAndHTTPCode(errMsg string, statusCode int) *status.Status { + var c codes.Code + // Mapping based on https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md + // 429 mapping to ResourceExhausted and 400 mapping to StatusBadRequest are exceptions. + switch statusCode { + case http.StatusBadRequest: + c = codes.InvalidArgument + case http.StatusUnauthorized: + c = codes.Unauthenticated + case http.StatusForbidden: + c = codes.PermissionDenied + case http.StatusNotFound: + c = codes.Unimplemented + case http.StatusTooManyRequests: + c = codes.ResourceExhausted + case http.StatusBadGateway, http.StatusServiceUnavailable, http.StatusGatewayTimeout: + c = codes.Unavailable + default: + c = codes.Unknown + } + return status.New(c, errMsg) +} diff --git a/internal/httphelper/helper_test.go b/internal/httphelper/helper_test.go new file mode 100644 index 00000000000..a2c96ed0e09 --- /dev/null +++ b/internal/httphelper/helper_test.go @@ -0,0 +1,83 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package httphelper + +import ( + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func Test_ErrorMsgAndHTTPCodeToStatus(t *testing.T) { + tests := []struct { + name string + errMsg string + statusCode int + expected *status.Status + }{ + { + name: "Bad Request", + errMsg: "test", + statusCode: http.StatusBadRequest, + expected: status.New(codes.InvalidArgument, "test"), + }, + { + name: "Unauthorized", + errMsg: "test", + statusCode: http.StatusUnauthorized, + expected: status.New(codes.Unauthenticated, "test"), + }, + { + name: "Forbidden", + errMsg: "test", + statusCode: http.StatusForbidden, + expected: status.New(codes.PermissionDenied, "test"), + }, + { + name: "Not Found", + errMsg: "test", + statusCode: http.StatusNotFound, + expected: status.New(codes.Unimplemented, "test"), + }, + { + name: "Too Many Requests", + errMsg: "test", + statusCode: http.StatusTooManyRequests, + expected: status.New(codes.ResourceExhausted, "test"), + }, + { + name: "Bad Gateway", + errMsg: "test", + statusCode: http.StatusBadGateway, + expected: status.New(codes.Unavailable, "test"), + }, + { + name: "Service Unavailable", + errMsg: "test", + statusCode: http.StatusServiceUnavailable, + expected: status.New(codes.Unavailable, "test"), + }, + { + name: "Gateway Timeout", + errMsg: "test", + statusCode: http.StatusGatewayTimeout, + expected: status.New(codes.Unavailable, "test"), + }, + { + name: "Unsupported Media Type", + errMsg: "test", + statusCode: http.StatusUnsupportedMediaType, + expected: status.New(codes.Unknown, "test"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := NewStatusFromMsgAndHTTPCode(tt.errMsg, tt.statusCode) + assert.Equal(t, tt.expected, result) + }) + } +} diff --git a/internal/localhostgate/featuregate.go b/internal/localhostgate/featuregate.go index e1b02fca044..78c19622967 100644 --- a/internal/localhostgate/featuregate.go +++ b/internal/localhostgate/featuregate.go @@ -18,9 +18,9 @@ import ( const UseLocalHostAsDefaultHostID = "component.UseLocalHostAsDefaultHost" -// useLocalHostAsDefaultHostfeatureGate is the feature gate that controls whether +// 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( +var UseLocalHostAsDefaultHostfeatureGate = mustRegisterOrLoad( featuregate.GlobalRegistry(), UseLocalHostAsDefaultHostID, featuregate.StageAlpha, @@ -51,7 +51,7 @@ func mustRegisterOrLoad(reg *featuregate.Registry, id string, stage featuregate. // 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() { + if !UseLocalHostAsDefaultHostfeatureGate.IsEnabled() { host = "0.0.0.0" } return fmt.Sprintf("%s:%d", host, port) @@ -59,7 +59,7 @@ func EndpointForPort(port int) string { // 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() { + 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 index ef09519ac9c..bde051c4f15 100644 --- a/internal/localhostgate/featuregate_test.go +++ b/internal/localhostgate/featuregate_test.go @@ -50,7 +50,7 @@ func TestEndpointForPort(t *testing.T) { for _, tt := range tests { t.Run(tt.endpoint, func(t *testing.T) { - defer setFeatureGateForTest(t, useLocalHostAsDefaultHostfeatureGate, tt.enabled)() + defer setFeatureGateForTest(t, UseLocalHostAsDefaultHostfeatureGate, tt.enabled)() assert.Equal(t, EndpointForPort(tt.port), tt.endpoint) }) } diff --git a/internal/memorylimiter/config_test.go b/internal/memorylimiter/config_test.go index ca7a243f861..29db1dc6def 100644 --- a/internal/memorylimiter/config_test.go +++ b/internal/memorylimiter/config_test.go @@ -93,3 +93,13 @@ func TestConfigValidate(t *testing.T) { }) } } + +func TestUnmarshalInvalidConfig(t *testing.T) { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "negative_unsigned_limits_config.yaml")) + require.NoError(t, err) + cfg := &Config{} + err = component.UnmarshalConfig(cm, cfg) + require.Error(t, err) + require.Contains(t, err.Error(), "error decoding 'limit_mib': cannot convert negative value -2000 to an unsigned integer") + require.Contains(t, err.Error(), "error decoding 'spike_limit_mib': cannot convert negative value -2300 to an unsigned integer") +} diff --git a/internal/memorylimiter/testdata/negative_unsigned_limits_config.yaml b/internal/memorylimiter/testdata/negative_unsigned_limits_config.yaml new file mode 100644 index 00000000000..3a2ef3a5b99 --- /dev/null +++ b/internal/memorylimiter/testdata/negative_unsigned_limits_config.yaml @@ -0,0 +1,13 @@ +# 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: -2000 + +# The maximum, in MiB, spike expected between the measurements of memory usage. +spike_limit_mib: -2300 diff --git a/internal/obsreportconfig/obsmetrics/obs_exporter.go b/internal/obsreportconfig/obsmetrics/obs_exporter.go index 50a2724070c..b87270f5e5a 100644 --- a/internal/obsreportconfig/obsmetrics/obs_exporter.go +++ b/internal/obsreportconfig/obsmetrics/obs_exporter.go @@ -30,8 +30,9 @@ const ( ) var ( - ExporterPrefix = ExporterKey + NameSep - ExportTraceDataOperationSuffix = NameSep + "traces" - ExportMetricsOperationSuffix = NameSep + "metrics" - ExportLogsOperationSuffix = NameSep + "logs" + ExporterPrefix = ExporterKey + SpanNameSep + ExporterMetricPrefix = ExporterKey + MetricNameSep + ExportTraceDataOperationSuffix = SpanNameSep + "traces" + ExportMetricsOperationSuffix = SpanNameSep + "metrics" + ExportLogsOperationSuffix = SpanNameSep + "logs" ) diff --git a/internal/obsreportconfig/obsmetrics/obs_processor.go b/internal/obsreportconfig/obsmetrics/obs_processor.go index 75084014ec5..3cbd8fc4a83 100644 --- a/internal/obsreportconfig/obsmetrics/obs_processor.go +++ b/internal/obsreportconfig/obsmetrics/obs_processor.go @@ -18,5 +18,5 @@ const ( ) var ( - ProcessorPrefix = ProcessorKey + NameSep + ProcessorMetricPrefix = ProcessorKey + MetricNameSep ) diff --git a/internal/obsreportconfig/obsmetrics/obs_receiver.go b/internal/obsreportconfig/obsmetrics/obs_receiver.go index d70148c1ff9..bcb6306f81b 100644 --- a/internal/obsreportconfig/obsmetrics/obs_receiver.go +++ b/internal/obsreportconfig/obsmetrics/obs_receiver.go @@ -30,8 +30,9 @@ const ( ) var ( - ReceiverPrefix = ReceiverKey + NameSep - ReceiveTraceDataOperationSuffix = NameSep + "TraceDataReceived" - ReceiverMetricsOperationSuffix = NameSep + "MetricsReceived" - ReceiverLogsOperationSuffix = NameSep + "LogsReceived" + ReceiverPrefix = ReceiverKey + SpanNameSep + ReceiverMetricPrefix = ReceiverKey + MetricNameSep + ReceiveTraceDataOperationSuffix = SpanNameSep + "TraceDataReceived" + ReceiverMetricsOperationSuffix = SpanNameSep + "MetricsReceived" + ReceiverLogsOperationSuffix = SpanNameSep + "LogsReceived" ) diff --git a/internal/obsreportconfig/obsmetrics/obs_scraper.go b/internal/obsreportconfig/obsmetrics/obs_scraper.go index 7e2b73d127f..4254891f33a 100644 --- a/internal/obsreportconfig/obsmetrics/obs_scraper.go +++ b/internal/obsreportconfig/obsmetrics/obs_scraper.go @@ -16,6 +16,7 @@ const ( ) const ( - ScraperPrefix = ScraperKey + NameSep - ScraperMetricsOperationSuffix = NameSep + "MetricsScraped" + ScraperPrefix = ScraperKey + SpanNameSep + ScraperMetricPrefix = ScraperKey + MetricNameSep + ScraperMetricsOperationSuffix = SpanNameSep + "MetricsScraped" ) diff --git a/internal/obsreportconfig/obsmetrics/obsmetrics.go b/internal/obsreportconfig/obsmetrics/obsmetrics.go index 84baf6d9c34..02ce450d3a9 100644 --- a/internal/obsreportconfig/obsmetrics/obsmetrics.go +++ b/internal/obsreportconfig/obsmetrics/obsmetrics.go @@ -7,6 +7,7 @@ package obsmetrics // import "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" const ( - NameSep = "/" - Scope = "go.opentelemetry.io/collector/obsreport" + SpanNameSep = "/" + MetricNameSep = "_" + Scope = "go.opentelemetry.io/collector/obsreport" ) diff --git a/internal/obsreportconfig/obsreportconfig.go b/internal/obsreportconfig/obsreportconfig.go index aed6813460c..dc5d4915569 100644 --- a/internal/obsreportconfig/obsreportconfig.go +++ b/internal/obsreportconfig/obsreportconfig.go @@ -7,14 +7,6 @@ import ( "go.opentelemetry.io/collector/featuregate" ) -// UseOtelForInternalMetricsfeatureGate is the feature gate that controls whether the collector uses open -// telemetrySettings for internal metrics. -var UseOtelForInternalMetricsfeatureGate = featuregate.GlobalRegistry().MustRegister( - "telemetry.useOtelForInternalMetrics", - 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. var DisableHighCardinalityMetricsfeatureGate = featuregate.GlobalRegistry().MustRegister( diff --git a/internal/tools/go.mod b/internal/tools/go.mod index c5dda5ebbdc..b1049839b5a 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -5,18 +5,18 @@ go 1.21 require ( github.com/a8m/envsubst v1.4.2 github.com/client9/misspell v0.3.4 - github.com/golangci/golangci-lint v1.56.2 + github.com/golangci/golangci-lint v1.57.2 github.com/google/addlicense v1.1.1 github.com/jcchavezs/porto v0.6.0 github.com/pavius/impi v0.0.3 - 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 + go.opentelemetry.io/build-tools/checkfile v0.13.0 + go.opentelemetry.io/build-tools/chloggen v0.13.0 + go.opentelemetry.io/build-tools/crosslink v0.13.0 + go.opentelemetry.io/build-tools/multimod v0.13.0 + go.opentelemetry.io/build-tools/semconvgen v0.13.0 golang.org/x/exp v0.0.0-20240119083558-1b970713d09a - golang.org/x/tools v0.18.0 - golang.org/x/vuln v1.0.4 + golang.org/x/tools v0.20.0 + golang.org/x/vuln v1.1.0 ) require ( @@ -24,10 +24,10 @@ require ( 4d63.com/gochecknoglobals v0.2.1 // indirect dario.cat/mergo v1.0.0 // indirect github.com/4meepo/tagalign v1.3.3 // indirect - github.com/Abirdcfly/dupword v0.0.13 // indirect + github.com/Abirdcfly/dupword v0.0.14 // 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/Antonboom/testifylint v1.2.0 // 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.2.0 // indirect @@ -37,7 +37,7 @@ require ( 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/nakedret/v2 v2.0.4 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect github.com/ashanbrown/forbidigo v1.6.0 // indirect @@ -51,27 +51,27 @@ require ( 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/catenacyber/perfsprint v0.6.0 // indirect + github.com/catenacyber/perfsprint v0.7.1 // 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.1.0 // indirect + github.com/ckaznocha/intrange v0.1.1 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/curioswitch/go-reassign v0.2.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/daixiang0/gci v0.12.3 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/denis-tingaikin/go-header v0.5.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/esimonov/ifshort v1.0.4 // 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.7.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/ghostiam/protogetter v0.3.4 // indirect - github.com/go-critic/go-critic v0.11.1 // indirect + github.com/ghostiam/protogetter v0.3.5 // indirect + github.com/go-critic/go-critic v0.11.2 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.5.0 // indirect github.com/go-git/go-git/v5 v5.11.0 // indirect @@ -87,15 +87,12 @@ require ( github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // 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-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/plugin-module-register v0.1.1 // indirect github.com/golangci/revgrep v0.5.2 // indirect - github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect + github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // 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 @@ -107,19 +104,20 @@ require ( 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.7.0 // indirect + github.com/jgautheron/goconst v1.7.1 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // 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/jjti/go-spancheck v0.5.3 // indirect github.com/julz/importas v0.1.0 // indirect + github.com/karamaru-alpha/copyloopvar v1.0.10 // indirect github.com/kevinburke/ssh_config v1.2.0 // 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/kkHAIKE/contextcheck v1.1.5 // indirect github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.9 // indirect + github.com/kunwardeep/paralleltest v1.0.10 // indirect github.com/kyoh86/exportloopref v0.1.11 // indirect - github.com/ldez/gomoddirectives v0.2.3 // indirect + github.com/ldez/gomoddirectives v0.2.4 // 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 @@ -131,8 +129,6 @@ require ( github.com/mattn/go-colorable v0.1.13 // 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/v2 v2.0.0 // indirect - github.com/mbilski/exhaustivestruct v1.2.0 // indirect github.com/mgechev/revive v1.3.7 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect @@ -140,23 +136,26 @@ require ( github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.15.2 // indirect + github.com/nunnatsa/ginkgolinter v0.16.2 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.0 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/polyfloyd/go-errorlint v1.4.8 // indirect - github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_golang v1.19.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/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/quasilyte/go-ruleguard v0.4.2 // 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/ryancurrah/gomodguard v1.3.1 // indirect github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect + github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect github.com/sashamelentyev/usestdlibvars v1.25.0 // indirect github.com/securego/gosec/v2 v2.19.0 // indirect @@ -164,28 +163,27 @@ require ( 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.1 // indirect github.com/sonatard/noctx v0.0.2 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect github.com/spf13/afero v1.11.0 // indirect - github.com/spf13/cast v1.5.1 // indirect + github.com/spf13/cast v1.6.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 + github.com/spf13/viper v1.18.2 // indirect github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect - github.com/stretchr/objx v0.5.0 // indirect - github.com/stretchr/testify v1.8.4 // indirect - github.com/subosito/gotenv v1.4.2 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/stretchr/testify v1.9.0 // indirect + github.com/subosito/gotenv v1.6.0 // 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.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/tomarrell/wrapcheck/v2 v2.8.3 // 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.1.0 // indirect @@ -196,27 +194,26 @@ require ( github.com/yeya24/promlinter v0.2.0 // 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-simpler.org/musttag v0.9.0 // indirect + go-simpler.org/sloglint v0.5.0 // indirect + go.opentelemetry.io/build-tools v0.13.0 // indirect + go.uber.org/automaxprocs v1.5.3 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // 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 + go.uber.org/zap v1.27.0 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/ini.v1 v1.67.0 // 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.6 // indirect + honnef.co/go/tools v0.4.7 // 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-20240104100049-c549a3470d14 // indirect ) diff --git a/internal/tools/go.sum b/internal/tools/go.sum index b0c915fbf3d..f2935d93a15 100644 --- a/internal/tools/go.sum +++ b/internal/tools/go.sum @@ -39,14 +39,14 @@ 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.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/Abirdcfly/dupword v0.0.14 h1:3U4ulkc8EUo+CaT105/GJ1BQwtgyj6+VaBVbAX11Ba8= +github.com/Abirdcfly/dupword v0.0.14/go.mod h1:VKDAbxdY8YbKUByLGg8EETzYSuC4crm9WwI6Y3S0cLI= 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/Antonboom/testifylint v1.2.0 h1:015bxD8zc5iY8QwTp4+RG9I4kIbqwvGX9TrBbb7jGdM= +github.com/Antonboom/testifylint v1.2.0/go.mod h1:rkmEqjqVnHDRNsinyN6fPSLnoajzFwsCcguJgwADBkw= 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= @@ -77,8 +77,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy 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/alexkohler/nakedret/v2 v2.0.2 h1:qnXuZNvv3/AxkAb22q/sEsEpcA99YxLFACDtEw9TPxE= -github.com/alexkohler/nakedret/v2 v2.0.2/go.mod h1:2b8Gkk0GsOrqQv/gPWjNLDSKwG8I5moSXG1K4VIBcTQ= +github.com/alexkohler/nakedret/v2 v2.0.4 h1:yZuKmjqGi0pSmjGpOC016LtPJysIL0WEUiaXW5SUnNg= +github.com/alexkohler/nakedret/v2 v2.0.4/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU= github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= @@ -112,8 +112,8 @@ github.com/butuzov/ireturn v0.3.0/go.mod h1:A09nIiwiqzN/IoVo9ogpa0Hzi9fex1kd9PSD 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/catenacyber/perfsprint v0.6.0 h1:VSv95RRkk5+BxrU/YTPcnxuMEWar1iMK5Vyh3fWcBfs= -github.com/catenacyber/perfsprint v0.6.0/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= +github.com/catenacyber/perfsprint v0.7.1 h1:PGW5G/Kxn+YrN04cRAZKC+ZuvlVwolYMrIyyTJ/rMmc= +github.com/catenacyber/perfsprint v0.7.1/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= @@ -128,6 +128,8 @@ github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+U 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/ckaznocha/intrange v0.1.1 h1:gHe4LfqCspWkh8KpJFs20fJz3XRHFBFUV9yI7Itu83Q= +github.com/ckaznocha/intrange v0.1.1/go.mod h1:RWffCw/vKBwHeOEwWdCikAtY0q4gGt8VhJZEEA5n+RE= 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/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= @@ -139,13 +141,14 @@ github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDU github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= 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/daixiang0/gci v0.12.3 h1:yOZI7VAxAGPQmkb1eqt5g/11SUlwoat1fSblGLmdiQc= +github.com/daixiang0/gci v0.12.3/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/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8= +github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= 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= @@ -154,8 +157,6 @@ 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/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.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= @@ -170,12 +171,12 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos 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/ghostiam/protogetter v0.3.5 h1:+f7UiF8XNd4w3a//4DnusQ2SZjPkUjxkMEfjbxOK4Ug= +github.com/ghostiam/protogetter v0.3.5/go.mod h1:7lpeDnEJ1ZjL/YtyoN99ljO4z0pd3H0d18/t2dPBxHw= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= 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-critic/go-critic v0.11.2 h1:81xH/2muBphEgPtcwH1p6QD+KzXl2tMSi3hXjBSxDnM= +github.com/go-critic/go-critic v0.11.2/go.mod h1:OePaicfjsf+KPy33yq4gzv6CO7TEQ9Rom6ns1KsJnl8= 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.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= @@ -255,26 +256,20 @@ 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/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-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/golangci-lint v1.57.2 h1:NNhxfZyL5He1WWDrIvl1a4n5bvWZBcgAqBwlJAAgLTw= +github.com/golangci/golangci-lint v1.57.2/go.mod h1:ApiG3S3Ca23QyfGp5BmsorTiVxJpr5jGiNS0BkdSidg= 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/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= +github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= 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/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs= +github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ= github.com/google/addlicense v1.1.1 h1:jpVf9qPbU8rz5MxKo7d+RMcNHkqxi4YJi/laauX4aAE= github.com/google/addlicense v1.1.1/go.mod h1:Sm/DHu7Jk+T5miFHHehdIjbi4M5+dJDRS3Cq0rncIxA= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -341,14 +336,14 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= 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/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= +github.com/jgautheron/goconst v1.7.1/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/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/jjti/go-spancheck v0.5.3 h1:vfq4s2IB8T3HvbpiwDTYgVPj1Ze/ZSXrTtaZRTc7CuM= +github.com/jjti/go-spancheck v0.5.3/go.mod h1:eQdOX1k3T+nAKvZDyLC3Eby0La4dZ+I19iOl5NzSPFE= 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= @@ -360,14 +355,16 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= 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/karamaru-alpha/copyloopvar v1.0.10 h1:8HYDy6KQYqTmD7JuhZMWS1nwPru9889XI24ROd/+WXI= +github.com/karamaru-alpha/copyloopvar v1.0.10/go.mod h1:u7CIfztblY0jZLOQZgH3oYsJzpC2A7S6u/lfgSXHy0k= 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.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/kkHAIKE/contextcheck v1.1.5 h1:CdnJh63tcDe53vG+RebdpdXJTc9atMgGqdx8LXxiilg= +github.com/kkHAIKE/contextcheck v1.1.5/go.mod h1:O930cpht4xb1YQpK+1+AgoM3mFsvxr7uyFptcnWTYUA= 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= @@ -380,12 +377,12 @@ 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.9 h1:3Sr2IfFNcsMmlqPk1cjTUbJ4zofKPGyHxenwPebgTug= -github.com/kunwardeep/paralleltest v1.0.9/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= +github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs= +github.com/kunwardeep/paralleltest v1.0.10/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/gomoddirectives v0.2.4 h1:j3YjBIjEBbqZ0NKtBNzr8rtMHTOrLPeiwTkfUJZ3alg= +github.com/ldez/gomoddirectives v0.2.4/go.mod h1:oWu9i62VcQDYp9EQ0ONTfqLNh+mDLWWDO+SO0qSQw5g= 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/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= @@ -412,10 +409,6 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D 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/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.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= @@ -437,8 +430,8 @@ github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhK 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.15.2 h1:N2ORxUxPU56R9gsfLIlVVvCv/V/VVou5qVI1oBKBNHg= -github.com/nunnatsa/ginkgolinter v0.15.2/go.mod h1:oYxE7dt1vZI8cK2rZOs3RgTaBN2vggkqnENmoJ8kVvc= +github.com/nunnatsa/ginkgolinter v0.16.2 h1:8iLqHIZvN4fTLDC0Ke9tbSZVcyVHoBs0HIbnVSxfHJk= +github.com/nunnatsa/ginkgolinter v0.16.2/go.mod h1:4tWRinDN1FeJgU+iJANW/kz7xKN5nYRAOfJDQUS9dOQ= 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.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= @@ -454,25 +447,28 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9 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.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= +github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= 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/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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polyfloyd/go-errorlint v1.4.8 h1:jiEjKDH33ouFktyez7sckv6pHWif9B7SuS8cutDXFHw= github.com/polyfloyd/go-errorlint v1.4.8/go.mod h1:NNCxFcFjZcw3xNjVdCchERkEM6Oz7wta2XJVxRftwO4= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= 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.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +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-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= @@ -483,17 +479,17 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 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.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +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.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.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/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/quasilyte/go-ruleguard v0.4.2 h1:htXcXDK6/rO12kiTHKfHuqR4kr3Y4M0J0rOL6CH/BYs= +github.com/quasilyte/go-ruleguard v0.4.2/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= @@ -504,12 +500,18 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR 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/ryancurrah/gomodguard v1.3.1 h1:fH+fUg+ngsQO0ruZXXHnA/2aNllWA1whly4a6UvyzGE= +github.com/ryancurrah/gomodguard v1.3.1/go.mod h1:DGFHzEhi6iJ0oIDfMuo3TgrS+L9gZvrEfmjjuelnRU0= 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/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= 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/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= 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.25.0 h1:IK8SI2QyFzy/2OD2PYnhy84dpfNo9qADrRt6LH8vSzU= @@ -530,28 +532,26 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= -github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= -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.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/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= 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.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/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= 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= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= -github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stbenjam/no-sprintf-host-port v0.1.1 h1:tYugd/yrm1O0dV+ThCbaKZh195Dfm07ysF0U6JQXczc= @@ -559,8 +559,9 @@ github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8L 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 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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= @@ -569,10 +570,11 @@ 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.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= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c h1:+aPplBwWcHBo6q9xrfWdMrT9o4kltkmmvpemgIjep/8= github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk= github.com/tdakkota/asciicheck v0.2.0 h1:o8jvnUANo0qXtnslk2d3nMKTFNlOnJjRrNcj0j9qkHM= @@ -587,8 +589,8 @@ github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 h1:quvGphlmUVU+n 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= github.com/timonwong/loggercheck v0.9.4/go.mod h1:caz4zlPcgvpEkXgVnAJGowHAMW2NwHaNlpS8xDbVhTg= -github.com/tomarrell/wrapcheck/v2 v2.8.1 h1:HxSqDSN0sAt0yJYsrcYVoEeyM4aI9yAm3KQpIXDJRhQ= -github.com/tomarrell/wrapcheck/v2 v2.8.1/go.mod h1:/n2Q3NZ4XFT50ho6Hbxg+RV1uyo2Uow/Vdm9NQcl5SE= +github.com/tomarrell/wrapcheck/v2 v2.8.3 h1:5ov+Cbhlgi7s/a42BprYoxsr73CbdMUTzE3bRDFASUs= +github.com/tomarrell/wrapcheck/v2 v2.8.3/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= 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= @@ -618,33 +620,35 @@ 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-simpler.org/musttag v0.9.0 h1:Dzt6/tyP9ONr5g9h9P3cnYWCxeBFRkd0uJL/w+1Mxos= +go-simpler.org/musttag v0.9.0/go.mod h1:gA9nThnalvNSKpEoyp3Ko4/vCX2xTpqKoUtNqXOnVR4= +go-simpler.org/sloglint v0.5.0 h1:2YCcd+YMuYpuqthCgubcF5lBSjb6berc5VMOYUHKrpY= +go-simpler.org/sloglint v0.5.0/go.mod h1:EUknX5s8iXqf18KQxKnaBHUPVriiPnOrPjjJcsaTcSQ= 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.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.opentelemetry.io/build-tools v0.13.0 h1:0I3jJQ2zcJU8k4ZjyHNqUBX2Len1UvBIOzVP4b50g9A= +go.opentelemetry.io/build-tools v0.13.0/go.mod h1:PEtg5iWjNI9WAlKXP/xll/hgbq/Cp4Ma4T1ssKB2T0Q= +go.opentelemetry.io/build-tools/checkfile v0.13.0 h1:Nq13fOLpF9T+y4birZbfv6JurFC1Pla5UwC+t0GMbAo= +go.opentelemetry.io/build-tools/checkfile v0.13.0/go.mod h1:fRNphqnBebBiwL1A3OofgCDiJ6enb73uKGIO+n0gHPI= +go.opentelemetry.io/build-tools/chloggen v0.13.0 h1:C30r8ecNuJ30T3+vSvFJhaXUjUpx6r07nM3weDCpS7U= +go.opentelemetry.io/build-tools/chloggen v0.13.0/go.mod h1:1Ueg04+D2eU7Lm80RqS4DYTdtkHwTmulQZL0tUI4iAk= +go.opentelemetry.io/build-tools/crosslink v0.13.0 h1:R0V89bTYzoJpasiOIYiQo6txL/ZTzMdEuthJ4gLUTF8= +go.opentelemetry.io/build-tools/crosslink v0.13.0/go.mod h1:aYIwOj9b3Nmgm6nIZZk28tF/JjpicI8xenEVUeoVNp0= +go.opentelemetry.io/build-tools/multimod v0.13.0 h1:HGAP3zCM8vOTNJSQbjQ5VbKZSctIZxppPBxRTzye7ic= +go.opentelemetry.io/build-tools/multimod v0.13.0/go.mod h1:CxZp68c4PIN+bYlVOGB2FvE5zZMBuGz7cGSHv2L7pSc= +go.opentelemetry.io/build-tools/semconvgen v0.13.0 h1:gGCCXzAQa4/9osvjQr/twTSiPFloxJOz01/segikweI= +go.opentelemetry.io/build-tools/semconvgen v0.13.0/go.mod h1:Xwolx7cXWG3QYYLvDMeO4+IkZGna+4SkI6qadeLDkW4= +go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8= +go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= +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-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 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= @@ -656,8 +660,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 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.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= 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= @@ -672,8 +676,8 @@ golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRj 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-20231219180239-dc181d75b848 h1:UhRVJ0i7bF9n/Hd8YjW3eKjlPVBHzbQdxrBgjbSKl64= -golang.org/x/exp/typeparams v0.0.0-20231219180239-dc181d75b848/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f h1:phY1HzDcf18Aq9A8KkmRtY9WvOFIxN8wgfvy6Zm1DV8= +golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f/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= @@ -702,8 +706,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.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.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= @@ -744,8 +748,8 @@ 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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= @@ -765,8 +769,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.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.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= @@ -822,8 +826,8 @@ 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.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -831,8 +835,8 @@ 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.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= 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= @@ -896,7 +900,6 @@ 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-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.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= @@ -911,10 +914,10 @@ golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.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/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +golang.org/x/vuln v1.1.0 h1:ECEdI+aEtjpF90eqEcDL5Q11DWSZAw5PJQWlp0+gWqc= +golang.org/x/vuln v1.1.0/go.mod h1:HT/Ar8fE34tbxWG2s7PYjVl+iIE4Er36/940Z+K540Y= 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= @@ -994,8 +997,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj 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.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 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= @@ -1024,14 +1027,10 @@ 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.6 h1:oFEHCKeID7to/3autwsWfnuv69j3NsfcXbvJKuIcep8= -honnef.co/go/tools v0.4.6/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0= +honnef.co/go/tools v0.4.7 h1:9MDAWxMoSnB6QoSqiVr7P5mtkT9pOc1kSxchzPCnqJs= +honnef.co/go/tools v0.4.7/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-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= diff --git a/obsreport/doc.go b/obsreport/doc.go deleted file mode 100644 index ca75b9ac670..00000000000 --- a/obsreport/doc.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Package obsreport provides unified and consistent observability signals ( -// metrics, tracing, etc) for components of the OpenTelemetry collector. -// -// The function Configure is used to control which signals are going to be -// generated. It provides functions for the typical operations of receivers, -// processors, and exporters. -// -// Receivers should use the respective start and end according to the data type -// being received, ie.: -// -// - Traces receive operations should use the pair: -// StartTracesOp/EndTracesOp -// -// - Metrics receive operations should use the pair: -// StartMetricsOp/EndMetricsOp -// -// - Logs receive operations should use the pair: -// StartLogsOp/EndLogsOp -// -// Similar for exporters: -// -// - Traces export operations should use the pair: -// StartTracesOp/EndTracesOp -// -// - Metrics export operations should use the pair: -// StartMetricsOp/EndMetricsOp -// -// - Metrics export operations should use the pair: -// StartLogsOp/EndLogsOp -// -// The package is capable of generating legacy metrics by using the -// observability package allowing a controlled transition from legacy to the -// new metrics. The goal is to eventually remove the legacy metrics and use only -// the new metrics. -// -// The main differences regarding the legacy metrics are: -// -// 1. "Amount of metric data" is measured as metric points (ie.: a single value -// in time), contrast it with number of time series used legacy. Number of -// metric data points is a more general concept regarding various metric -// formats. -// -// 2. Exporters measure the number of items, ie.: number of spans or metric -// points, that were sent and the ones for which the attempt to send failed. -// For more information about this see Notes below about reporting data loss. -// -// 3. All measurements of "amount of data" used in the new metrics for receivers -// and exporters should reflect their native formats, not the internal format -// used in the Collector. This is to facilitate reconciliation between Collector, -// client and backend. For instance: certain metric formats do not provide -// direct support for histograms and have predefined conventions to represent -// those, this conversion may end with a different number of time series and -// data points than the internal Collector format. -// -// Notes: -// -// * Data loss should be recorded only when the component itself remove the data -// from the pipeline. Legacy metrics for receivers used "dropped" in their names -// but these could be non-zero under normal operations and reflected no actual -// data loss when exporters with "sending_queue" are used. New metrics were renamed -// to avoid this misunderstanding. Here are the general recommendations to report data loss: -// -// - Receivers reporting errors to clients typically result in the client -// re-sending the same data so it is more correct to report "receive errors", -// not actual data loss. -// -// - Exporters need to report individual failures to send data, but on -// typical production pipelines processors usually take care of retries, -// so these should be reported as "send errors". -// -// - Data "filtered out" should have its own metrics and not be confused -// with dropped data. -// -// # Naming Convention for New Metrics -// -// Common Metrics: -// Metrics shared by different components should follow the convention below: -// -// `/` -// -// As a label the metric should have at least `{=""}` where -// `` is the name used in the configuration for the instance of the -// component, eg.: -// -// `receiver/accepted_spans{receiver="otlp",...}` -// `exporter/sent_spans{exporter="otlp/prod",...}` -// -// Component Specific Metrics: -// These metrics are implemented by specific components, eg.: batch processor. -// The general pattern is the same as the common metrics but with the addition -// of the component type (as it appears in the configuration) before the actual -// metric: -// -// `//` -// -// Even metrics exclusive to a single type should follow the conventions above -// and also include the type (as written in the configuration) as part of the -// metric name since there could be multiple instances of the same type in -// different pipelines, eg.: -// -// `processor/batch/batch_size_trigger_send{processor="batch/dev",...}` -package obsreport // import "go.opentelemetry.io/collector/obsreport" diff --git a/obsreport/obsreporttest/deprecated.go b/obsreport/obsreporttest/deprecated.go deleted file mode 100644 index b822191ee4e..00000000000 --- a/obsreport/obsreporttest/deprecated.go +++ /dev/null @@ -1,29 +0,0 @@ -// 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/package_test.go b/obsreport/obsreporttest/package_test.go deleted file mode 100644 index 97b3f7f9210..00000000000 --- a/obsreport/obsreporttest/package_test.go +++ /dev/null @@ -1,14 +0,0 @@ -// 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 3fd5cb2ca31..bca6e9b86dc 100644 --- a/otelcol/collector.go +++ b/otelcol/collector.go @@ -99,8 +99,9 @@ type Collector struct { configProvider ConfigProvider - service *service.Service - state *atomic.Int32 + serviceConfig *service.Config + service *service.Service + state *atomic.Int32 // shutdownChan is used to terminate the collector. shutdownChan chan struct{} @@ -115,6 +116,9 @@ func NewCollector(set CollectorSettings) (*Collector, error) { var err error configProvider := set.ConfigProvider + set.ConfigProviderSettings.ResolverSettings.ProviderSettings = confmap.ProviderSettings{Logger: zap.NewNop()} + set.ConfigProviderSettings.ResolverSettings.ConverterSettings = confmap.ConverterSettings{} + if configProvider == nil { configProvider, err = NewConfigProvider(set.ConfigProviderSettings) if err != nil { @@ -182,6 +186,8 @@ func (col *Collector) setupConfigurationComponents(ctx context.Context) error { return fmt.Errorf("invalid configuration: %w", err) } + col.serviceConfig = &cfg.Service + col.service, err = service.New(ctx, service.Settings{ BuildInfo: col.set.BuildInfo, CollectorConf: conf, @@ -239,6 +245,7 @@ func (col *Collector) DryRun(ctx context.Context) error { // Run starts the collector according to the given configuration, and waits for it to complete. // Consecutive calls to Run are not allowed, Run shouldn't be called once a collector is shut down. +// Sets up the control logic for config reloading and shutdown. func (col *Collector) Run(ctx context.Context) error { if err := col.setupConfigurationComponents(ctx); err != nil { col.setCollectorState(StateClosed) @@ -254,6 +261,8 @@ func (col *Collector) Run(ctx context.Context) error { signal.Notify(col.signalsChannel, os.Interrupt, syscall.SIGTERM) } + // Control loop: selects between channels for various interrupts - when this loop is broken, the collector exits. + // If a configuration reload fails, we return without waiting for graceful shutdown. LOOP: for { select { diff --git a/otelcol/collector_test.go b/otelcol/collector_test.go index c56d56fc728..b96a6fc15db 100644 --- a/otelcol/collector_test.go +++ b/otelcol/collector_test.go @@ -421,16 +421,33 @@ func TestCollectorClosedStateOnStartUpError(t *testing.T) { } func TestCollectorDryRun(t *testing.T) { - // Load a bad config causing startup to fail - set := CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: nopFactories, - ConfigProviderSettings: newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-invalid.yaml")}), + tests := map[string]struct { + settings CollectorSettings + expectedErr string + }{ + "invalid_processor": { + settings: CollectorSettings{ + BuildInfo: component.NewDefaultBuildInfo(), + Factories: nopFactories, + ConfigProviderSettings: newDefaultConfigProviderSettings([]string{filepath.Join("testdata", "otelcol-invalid.yaml")}), + }, + expectedErr: `service::pipelines::traces: references processor "invalid" which is not configured`, + }, } - col, err := NewCollector(set) - require.NoError(t, err) - require.Error(t, col.DryRun(context.Background())) + for name, test := range tests { + t.Run(name, func(t *testing.T) { + col, err := NewCollector(test.settings) + require.NoError(t, err) + + err = col.DryRun(context.Background()) + if test.expectedErr == "" { + require.NoError(t, err) + } else { + require.EqualError(t, err, test.expectedErr) + } + }) + } } func TestPassConfmapToServiceFailure(t *testing.T) { @@ -439,8 +456,8 @@ func TestPassConfmapToServiceFailure(t *testing.T) { Factories: nopFactories, ConfigProviderSettings: ConfigProviderSettings{ ResolverSettings: confmap.ResolverSettings{ - URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")}, - Providers: makeMapProvidersMap(newFailureProvider()), + URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")}, + ProviderFactories: []confmap.ProviderFactory{confmap.NewProviderFactory(newFailureProvider)}, }, }, } @@ -463,7 +480,7 @@ func startCollector(ctx context.Context, t *testing.T, col *Collector) *sync.Wai type failureProvider struct{} -func newFailureProvider() confmap.Provider { +func newFailureProvider(_ confmap.ProviderSettings) confmap.Provider { return &failureProvider{} } diff --git a/otelcol/collector_windows.go b/otelcol/collector_windows.go index f443d930b17..cc0a3611628 100644 --- a/otelcol/collector_windows.go +++ b/otelcol/collector_windows.go @@ -18,6 +18,7 @@ import ( "golang.org/x/sys/windows/svc/eventlog" "go.opentelemetry.io/collector/featuregate" + "go.opentelemetry.io/collector/service" ) type windowsService struct { @@ -76,11 +77,6 @@ func (s *windowsService) Execute(args []string, requests <-chan svc.ChangeReques } func (s *windowsService) start(elog *eventlog.Log, colErrorChannel chan error) error { - // Append to new slice instead of the already existing s.settings.LoggingOptions slice to not change that. - s.settings.LoggingOptions = append( - []zap.Option{zap.WrapCore(withWindowsCore(elog))}, - s.settings.LoggingOptions..., - ) // Parse all the flags manually. if err := s.flags.Parse(os.Args[1:]); err != nil { return err @@ -96,6 +92,18 @@ func (s *windowsService) start(elog *eventlog.Log, colErrorChannel chan error) e return err } + // The logging options need to be in place before the collector Run method is called + // since the telemetry creates the logger at the time of the Run method call. + // However, the zap.WrapCore function needs to read the serviceConfig to determine + // if the Windows Event Log should be used, however, the serviceConfig is also + // only read at the time of the Run method call. To work around this, we pass the + // serviceConfig as a pointer to the logging options, and then read its value + // when the zap.Logger is created by the telemetry. + s.col.set.LoggingOptions = append( + s.col.set.LoggingOptions, + zap.WrapCore(withWindowsCore(elog, &s.col.serviceConfig)), + ) + // col.Run blocks until receiving a SIGTERM signal, so needs to be started // asynchronously, but it will exit early if an error occurs on startup go func() { @@ -192,8 +200,18 @@ func (w windowsEventLogCore) Sync() error { return w.core.Sync() } -func withWindowsCore(elog *eventlog.Log) func(zapcore.Core) zapcore.Core { +func withWindowsCore(elog *eventlog.Log, serviceConfig **service.Config) func(zapcore.Core) zapcore.Core { return func(core zapcore.Core) zapcore.Core { + if serviceConfig != nil { + for _, output := range (*serviceConfig).Telemetry.Logs.OutputPaths { + if output != "stdout" && output != "stderr" { + // A log file was specified in the configuration, so we should not use the Windows Event Log + return core + } + } + } + + // Use the Windows Event Log encoderConfig := zap.NewProductionEncoderConfig() encoderConfig.LineEnding = "\r\n" return windowsEventLogCore{core, elog, zapcore.NewConsoleEncoder(encoderConfig)} diff --git a/otelcol/collector_windows_service_test.go b/otelcol/collector_windows_service_test.go new file mode 100644 index 00000000000..999fa87bbbc --- /dev/null +++ b/otelcol/collector_windows_service_test.go @@ -0,0 +1,185 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +//go:build windows && win32service + +package otelcol + +import ( + "encoding/xml" + "fmt" + "os" + "os/exec" + "path/filepath" + "testing" + "time" + + "github.com/stretchr/testify/require" + "golang.org/x/sys/windows/svc" + "golang.org/x/sys/windows/svc/mgr" +) + +const ( + collectorServiceName = "otelcorecol" +) + +// Test the collector as a Windows service. +// The test assumes that the service and respective event source are already created. +// The test also must be executed with administrative privileges. +func TestCollectorAsService(t *testing.T) { + collector_executable, err := filepath.Abs(filepath.Join("..", "bin", "otelcorecol_windows_amd64")) + require.NoError(t, err) + _, err = os.Stat(collector_executable) + require.NoError(t, err) + + scm, err := mgr.Connect() + require.NoError(t, err) + defer scm.Disconnect() + + service, err := scm.OpenService(collectorServiceName) + require.NoError(t, err) + defer service.Close() + + tests := []struct { + name string + configFile string + expectStartFailure bool + customSetup func(*testing.T) + customValidation func(*testing.T) + }{ + { + name: "Default", + configFile: filepath.Join("..", "examples", "local", "otel-config.yaml"), + }, + { + name: "ConfigFileNotFound", + configFile: filepath.Join(".", "non", "existent", "otel-config.yaml"), + expectStartFailure: true, + }, + { + name: "LogToFile", + configFile: filepath.Join(".", "testdata", "otel-log-to-file.yaml"), + customSetup: func(t *testing.T) { + // Create the folder and clean the log file if it exists + programDataPath := os.Getenv("ProgramData") + logsPath := filepath.Join(programDataPath, "OpenTelemetry", "Collector", "Logs") + err := os.MkdirAll(logsPath, os.ModePerm) + require.NoError(t, err) + + logFilePath := filepath.Join(logsPath, "otelcol.log") + err = os.Remove(logFilePath) + if err != nil && !os.IsNotExist(err) { + require.NoError(t, err) + } + }, + customValidation: func(t *testing.T) { + // Check that the log file was created + programDataPath := os.Getenv("ProgramData") + logsPath := filepath.Join(programDataPath, "OpenTelemetry", "Collector", "Logs") + logFilePath := filepath.Join(logsPath, "otelcol.log") + fileinfo, err := os.Stat(logFilePath) + require.NoError(t, err) + require.NotEmpty(t, fileinfo.Size()) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + serviceConfig, err := service.Config() + require.NoError(t, err) + + // Setup the command line to launch the collector as a service + fullConfigPath, err := filepath.Abs(tt.configFile) + require.NoError(t, err) + + serviceConfig.BinaryPathName = fmt.Sprintf("\"%s\" --config \"%s\"", collector_executable, fullConfigPath) + err = service.UpdateConfig(serviceConfig) + require.NoError(t, err) + + if tt.customSetup != nil { + tt.customSetup(t) + } + + startTime := time.Now() + + err = service.Start() + require.NoError(t, err) + + expectedState := svc.Running + if tt.expectStartFailure { + expectedState = svc.Stopped + } else { + defer func() { + _, err = service.Control(svc.Stop) + require.NoError(t, err) + + require.Eventually(t, func() bool { + status, _ := service.Query() + return status.State == svc.Stopped + }, 10*time.Second, 500*time.Millisecond) + }() + } + + // Wait for the service to reach the expected state + require.Eventually(t, func() bool { + status, _ := service.Query() + return status.State == expectedState + }, 10*time.Second, 500*time.Millisecond) + + if tt.customValidation != nil { + tt.customValidation(t) + } else { + // Read the events from the otelcorecol source and check that they were emitted after the service + // command started. This is a simple validation that the messages are being logged on the + // Windows event log. + cmd := exec.Command("wevtutil.exe", "qe", "Application", "/c:1", "/rd:true", "/f:RenderedXml", "/q:*[System[Provider[@Name='otelcorecol']]]") + out, err := cmd.CombinedOutput() + require.NoError(t, err) + + var e Event + require.NoError(t, xml.Unmarshal([]byte(out), &e)) + + eventTime, err := time.Parse("2006-01-02T15:04:05.9999999Z07:00", e.System.TimeCreated.SystemTime) + require.NoError(t, err) + + require.True(t, eventTime.After(startTime.In(time.UTC))) + } + }) + } +} + +// Helper types to read the XML events from the event log using wevtutil +type Event struct { + XMLName xml.Name `xml:"Event"` + System System `xml:"System"` + Data string `xml:"EventData>Data"` +} + +type System struct { + Provider Provider `xml:"Provider"` + EventID int `xml:"EventID"` + Version int `xml:"Version"` + Level int `xml:"Level"` + Task int `xml:"Task"` + Opcode int `xml:"Opcode"` + Keywords string `xml:"Keywords"` + TimeCreated TimeCreated `xml:"TimeCreated"` + EventRecordID int `xml:"EventRecordID"` + Execution Execution `xml:"Execution"` + Channel string `xml:"Channel"` + Computer string `xml:"Computer"` +} + +type Provider struct { + Name string `xml:"Name,attr"` +} + +type TimeCreated struct { + SystemTime string `xml:"SystemTime,attr"` +} + +type Execution struct { + ProcessID string `xml:"ProcessID,attr"` + ThreadID string `xml:"ThreadID,attr"` +} diff --git a/otelcol/command.go b/otelcol/command.go index f510687c31b..9db850bcc13 100644 --- a/otelcol/command.go +++ b/otelcol/command.go @@ -41,6 +41,7 @@ func NewCommand(set CollectorSettings) *cobra.Command { return rootCmd } +// Puts command line flags from flags into the CollectorSettings, to be used during config resolution. func updateSettingsUsingFlags(set *CollectorSettings, flags *flag.FlagSet) error { if set.ConfigProvider == nil { resolverSet := &set.ConfigProviderSettings.ResolverSettings @@ -55,7 +56,7 @@ func updateSettingsUsingFlags(set *CollectorSettings, flags *flag.FlagSet) error // 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 { + if len(resolverSet.ProviderFactories) == 0 && len(resolverSet.ConverterFactories) == 0 { set.ConfigProviderSettings = newDefaultConfigProviderSettings(resolverSet.URIs) } } diff --git a/otelcol/command_components.go b/otelcol/command_components.go index 83dd4670375..da13d6779a7 100644 --- a/otelcol/command_components.go +++ b/otelcol/command_components.go @@ -5,11 +5,17 @@ package otelcol // import "go.opentelemetry.io/collector/otelcol" import ( "fmt" + "sort" "github.com/spf13/cobra" "gopkg.in/yaml.v3" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/connector" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/extension" + "go.opentelemetry.io/collector/processor" + "go.opentelemetry.io/collector/receiver" ) type componentWithStability struct { @@ -41,59 +47,59 @@ func newComponentsCommand(set CollectorSettings) *cobra.Command { } components := componentsOutput{} - for con := range factories.Connectors { + for _, con := range sortFactoriesByType[connector.Factory](factories.Connectors) { components.Connectors = append(components.Connectors, componentWithStability{ - Name: con, + Name: con.Type(), Stability: map[string]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(), + "logs-to-logs": con.LogsToLogsStability().String(), + "logs-to-metrics": con.LogsToMetricsStability().String(), + "logs-to-traces": con.LogsToTracesStability().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(), + "metrics-to-logs": con.MetricsToLogsStability().String(), + "metrics-to-metrics": con.MetricsToMetricsStability().String(), + "metrics-to-traces": con.MetricsToTracesStability().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(), + "traces-to-logs": con.TracesToLogsStability().String(), + "traces-to-metrics": con.TracesToMetricsStability().String(), + "traces-to-traces": con.TracesToTracesStability().String(), }, }) } - for ext := range factories.Extensions { + for _, ext := range sortFactoriesByType[extension.Factory](factories.Extensions) { components.Extensions = append(components.Extensions, componentWithStability{ - Name: ext, + Name: ext.Type(), Stability: map[string]string{ - "extension": factories.Extensions[ext].ExtensionStability().String(), + "extension": ext.ExtensionStability().String(), }, }) } - for prs := range factories.Processors { + for _, prs := range sortFactoriesByType[processor.Factory](factories.Processors) { components.Processors = append(components.Processors, componentWithStability{ - Name: prs, + Name: prs.Type(), Stability: map[string]string{ - "logs": factories.Processors[prs].LogsProcessorStability().String(), - "metrics": factories.Processors[prs].MetricsProcessorStability().String(), - "traces": factories.Processors[prs].TracesProcessorStability().String(), + "logs": prs.LogsProcessorStability().String(), + "metrics": prs.MetricsProcessorStability().String(), + "traces": prs.TracesProcessorStability().String(), }, }) } - for rcv := range factories.Receivers { + for _, rcv := range sortFactoriesByType[receiver.Factory](factories.Receivers) { components.Receivers = append(components.Receivers, componentWithStability{ - Name: rcv, + Name: rcv.Type(), Stability: map[string]string{ - "logs": factories.Receivers[rcv].LogsReceiverStability().String(), - "metrics": factories.Receivers[rcv].MetricsReceiverStability().String(), - "traces": factories.Receivers[rcv].TracesReceiverStability().String(), + "logs": rcv.LogsReceiverStability().String(), + "metrics": rcv.MetricsReceiverStability().String(), + "traces": rcv.TracesReceiverStability().String(), }, }) } - for exp := range factories.Exporters { + for _, exp := range sortFactoriesByType[exporter.Factory](factories.Exporters) { components.Exporters = append(components.Exporters, componentWithStability{ - Name: exp, + Name: exp.Type(), Stability: map[string]string{ - "logs": factories.Exporters[exp].LogsExporterStability().String(), - "metrics": factories.Exporters[exp].MetricsExporterStability().String(), - "traces": factories.Exporters[exp].TracesExporterStability().String(), + "logs": exp.LogsExporterStability().String(), + "metrics": exp.MetricsExporterStability().String(), + "traces": exp.TracesExporterStability().String(), }, }) } @@ -107,3 +113,24 @@ func newComponentsCommand(set CollectorSettings) *cobra.Command { }, } } + +func sortFactoriesByType[T component.Factory](factories map[component.Type]T) []T { + // Gather component types (factories map keys) + componentTypes := make([]component.Type, 0, len(factories)) + for componentType := range factories { + componentTypes = append(componentTypes, componentType) + } + + // Sort component types as strings + sort.Slice(componentTypes, func(i, j int) bool { + return componentTypes[i].String() < componentTypes[j].String() + }) + + // Build and return list of factories, sorted by component types + sortedFactories := make([]T, 0, len(factories)) + for _, componentType := range componentTypes { + sortedFactories = append(sortedFactories, factories[componentType]) + } + + return sortedFactories +} diff --git a/otelcol/command_components_test.go b/otelcol/command_components_test.go index 141fb586010..c4e3c7fbf29 100644 --- a/otelcol/command_components_test.go +++ b/otelcol/command_components_test.go @@ -5,19 +5,17 @@ package otelcol import ( "bytes" + "os" "path/filepath" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gopkg.in/yaml.v3" "go.opentelemetry.io/collector/component" ) -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) @@ -30,56 +28,7 @@ func TestNewBuildSubCommand(t *testing.T) { cmd := NewCommand(set) cmd.SetArgs([]string{"components"}) - ExpectedYamlStruct := componentsOutput{ - BuildInfo: component.NewDefaultBuildInfo(), - Receivers: []componentWithStability{{ - Name: nopType, - Stability: map[string]string{ - "logs": "Stable", - "metrics": "Stable", - "traces": "Stable", - }, - }}, - Processors: []componentWithStability{{ - Name: nopType, - Stability: map[string]string{ - "logs": "Stable", - "metrics": "Stable", - "traces": "Stable", - }, - }}, - Exporters: []componentWithStability{{ - Name: nopType, - Stability: map[string]string{ - "logs": "Stable", - "metrics": "Stable", - "traces": "Stable", - }, - }}, - Connectors: []componentWithStability{{ - Name: nopType, - Stability: map[string]string{ - "logs-to-logs": "Development", - "logs-to-metrics": "Development", - "logs-to-traces": "Development", - - "metrics-to-logs": "Development", - "metrics-to-metrics": "Development", - "metrics-to-traces": "Development", - - "traces-to-logs": "Development", - "traces-to-metrics": "Development", - "traces-to-traces": "Development", - }, - }}, - Extensions: []componentWithStability{{ - Name: nopType, - Stability: map[string]string{ - "extension": "Stable", - }, - }}, - } - ExpectedOutput, err := yaml.Marshal(ExpectedYamlStruct) + ExpectedOutput, err := os.ReadFile(filepath.Join("testdata", "components-output.yaml")) require.NoError(t, err) b := bytes.NewBufferString("") @@ -89,5 +38,5 @@ func TestNewBuildSubCommand(t *testing.T) { // Trim new line at the end of the two strings to make a better comparison as string() adds an extra new // line that makes the test fail. - assert.Equal(t, strings.Trim(string(ExpectedOutput), "\n"), strings.Trim(b.String(), "\n")) + assert.Equal(t, strings.ReplaceAll(strings.ReplaceAll(string(ExpectedOutput), "\n", ""), "\r", ""), strings.ReplaceAll(strings.ReplaceAll(b.String(), "\n", ""), "\r", "")) } diff --git a/otelcol/command_test.go b/otelcol/command_test.go index d599441c658..69e1a943d2b 100644 --- a/otelcol/command_test.go +++ b/otelcol/command_test.go @@ -52,9 +52,9 @@ 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.NewWithSettings(confmap.ProviderSettings{})}, - Converters: []confmap.Converter{expandconverter.New(confmap.ConverterSettings{})}, + URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")}, + ProviderFactories: []confmap.ProviderFactory{fileprovider.NewFactory()}, + ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()}, }, }, } @@ -80,16 +80,16 @@ func TestAddDefaultConfmapModules(t *testing.T) { 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) + require.Len(t, set.ConfigProviderSettings.ResolverSettings.ConverterFactories, 1) + require.Len(t, set.ConfigProviderSettings.ResolverSettings.ProviderFactories, 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"}, + ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()}, + URIs: []string{"--config=otelcol-nop.yaml"}, }, }, } @@ -101,9 +101,9 @@ func TestInvalidCollectorSettings(t *testing.T) { 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{})}, + URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")}, + ProviderFactories: []confmap.ProviderFactory{fileprovider.NewFactory()}, + ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()}, }, } diff --git a/otelcol/command_validate_test.go b/otelcol/command_validate_test.go index b215a77ffbf..30d291d4a56 100644 --- a/otelcol/command_validate_test.go +++ b/otelcol/command_validate_test.go @@ -26,9 +26,9 @@ func TestValidateSubCommandInvalidComponents(t *testing.T) { cfgProvider, err := NewConfigProvider( ConfigProviderSettings{ ResolverSettings: confmap.ResolverSettings{ - URIs: []string{filepath.Join("testdata", "otelcol-invalid-components.yaml")}, - Providers: map[string]confmap.Provider{"file": fileprovider.NewWithSettings(confmap.ProviderSettings{})}, - Converters: []confmap.Converter{expandconverter.New(confmap.ConverterSettings{})}, + URIs: []string{filepath.Join("testdata", "otelcol-invalid-components.yaml")}, + ProviderFactories: []confmap.ProviderFactory{fileprovider.NewFactory()}, + ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()}, }, }) require.NoError(t, err) diff --git a/otelcol/config.go b/otelcol/config.go index 9345405b4fd..7c27bd40201 100644 --- a/otelcol/config.go +++ b/otelcol/config.go @@ -12,8 +12,9 @@ import ( ) var ( - errMissingExporters = errors.New("no exporter configuration specified in config") - errMissingReceivers = errors.New("no receiver configuration specified in config") + errMissingExporters = errors.New("no exporter configuration specified in config") + errMissingReceivers = errors.New("no receiver configuration specified in config") + errEmptyConfigurationFile = errors.New("empty configuration file") ) // Config defines the configuration for the various elements of collector or agent. @@ -42,6 +43,11 @@ type Config struct { // invalid cases that we currently don't check for but which we may want to add in // the future (e.g. disallowing receiving and exporting on the same endpoint). func (cfg *Config) Validate() error { + // There must be at least one property set in the configuration file. + if len(cfg.Receivers) == 0 && len(cfg.Exporters) == 0 && len(cfg.Processors) == 0 && len(cfg.Connectors) == 0 && len(cfg.Extensions) == 0 { + return errEmptyConfigurationFile + } + // Currently, there is no default receiver enabled. // The configuration must specify at least one receiver to be valid. if len(cfg.Receivers) == 0 { diff --git a/otelcol/config_test.go b/otelcol/config_test.go index e482e6c8ae8..c1677c07220 100644 --- a/otelcol/config_test.go +++ b/otelcol/config_test.go @@ -54,6 +54,19 @@ func TestConfigValidate(t *testing.T) { }, expected: nil, }, + { + name: "empty configuration file", + cfgFn: func() *Config { + cfg := generateConfig() + cfg.Receivers = nil + cfg.Connectors = nil + cfg.Processors = nil + cfg.Exporters = nil + cfg.Extensions = nil + return cfg + }, + expected: errEmptyConfigurationFile, + }, { name: "missing-exporters", cfgFn: func() *Config { diff --git a/otelcol/configprovider.go b/otelcol/configprovider.go index fa43aa64ae6..477541fd4bd 100644 --- a/otelcol/configprovider.go +++ b/otelcol/configprovider.go @@ -132,27 +132,17 @@ 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.NewWithSettings(providerSet), - envprovider.NewWithSettings(providerSet), - yamlprovider.NewWithSettings(providerSet), - httpprovider.NewWithSettings(providerSet), - httpsprovider.NewWithSettings(providerSet), - ), - Converters: []confmap.Converter{expandconverter.New(converterSet)}, + ProviderFactories: []confmap.ProviderFactory{ + fileprovider.NewFactory(), + envprovider.NewFactory(), + yamlprovider.NewFactory(), + httpprovider.NewFactory(), + httpsprovider.NewFactory(), + }, + ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()}, }, } } - -func makeMapProvidersMap(providers ...confmap.Provider) map[string]confmap.Provider { - ret := make(map[string]confmap.Provider, len(providers)) - for _, provider := range providers { - ret[provider.Scheme()] = provider - } - return ret -} diff --git a/otelcol/configprovider_test.go b/otelcol/configprovider_test.go index a1c5be3eb49..b9ad46cb70d 100644 --- a/otelcol/configprovider_test.go +++ b/otelcol/configprovider_test.go @@ -48,11 +48,10 @@ func TestConfigProviderYaml(t *testing.T) { require.NoError(t, err) uriLocation := "yaml:" + string(yamlBytes) - provider := yamlprovider.New() set := ConfigProviderSettings{ ResolverSettings: confmap.ResolverSettings{ - URIs: []string{uriLocation}, - Providers: map[string]confmap.Provider{provider.Scheme(): provider}, + URIs: []string{uriLocation}, + ProviderFactories: []confmap.ProviderFactory{yamlprovider.NewFactory()}, }, } @@ -73,11 +72,10 @@ func TestConfigProviderYaml(t *testing.T) { func TestConfigProviderFile(t *testing.T) { uriLocation := "file:" + filepath.Join("testdata", "otelcol-nop.yaml") - provider := fileprovider.New() set := ConfigProviderSettings{ ResolverSettings: confmap.ResolverSettings{ - URIs: []string{uriLocation}, - Providers: map[string]confmap.Provider{provider.Scheme(): provider}, + URIs: []string{uriLocation}, + ProviderFactories: []confmap.ProviderFactory{fileprovider.NewFactory()}, }, } @@ -101,11 +99,10 @@ func TestConfigProviderFile(t *testing.T) { func TestGetConfmap(t *testing.T) { uriLocation := "file:" + filepath.Join("testdata", "otelcol-nop.yaml") - provider := fileprovider.New() set := ConfigProviderSettings{ ResolverSettings: confmap.ResolverSettings{ - URIs: []string{uriLocation}, - Providers: map[string]confmap.Provider{provider.Scheme(): provider}, + URIs: []string{uriLocation}, + ProviderFactories: []confmap.ProviderFactory{fileprovider.NewFactory()}, }, } diff --git a/otelcol/factories_test.go b/otelcol/factories_test.go index 645d59c7db2..965ea91844b 100644 --- a/otelcol/factories_test.go +++ b/otelcol/factories_test.go @@ -4,6 +4,7 @@ package otelcol import ( + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/connector" "go.opentelemetry.io/collector/connector/connectortest" "go.opentelemetry.io/collector/exporter" @@ -28,7 +29,7 @@ func nopFactories() (Factories, error) { return Factories{}, err } - if factories.Receivers, err = receiver.MakeFactoryMap(receivertest.NewNopFactory()); err != nil { + if factories.Receivers, err = receiver.MakeFactoryMap(receivertest.NewNopFactory(), receivertest.NewNopFactoryForType(component.DataTypeLogs)); err != nil { return Factories{}, err } diff --git a/otelcol/go.mod b/otelcol/go.mod index 78caf027f15..a24906b5d07 100644 --- a/otelcol/go.mod +++ b/otelcol/go.mod @@ -4,34 +4,35 @@ go 1.21 require ( github.com/spf13/cobra v1.8.0 - github.com/stretchr/testify v1.8.4 - 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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/confmap/converter/expandconverter v0.100.0 + go.opentelemetry.io/collector/confmap/provider/envprovider v0.100.0 + go.opentelemetry.io/collector/confmap/provider/fileprovider v0.100.0 + go.opentelemetry.io/collector/confmap/provider/httpprovider v0.100.0 + go.opentelemetry.io/collector/confmap/provider/httpsprovider v0.100.0 + go.opentelemetry.io/collector/confmap/provider/yamlprovider v0.100.0 + go.opentelemetry.io/collector/connector v0.100.0 + go.opentelemetry.io/collector/exporter v0.100.0 + go.opentelemetry.io/collector/extension v0.100.0 + go.opentelemetry.io/collector/featuregate v1.7.0 + go.opentelemetry.io/collector/processor v0.100.0 + go.opentelemetry.io/collector/receiver v0.100.0 + go.opentelemetry.io/collector/service v0.100.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 - golang.org/x/sys v0.17.0 - google.golang.org/grpc v1.62.0 + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa + golang.org/x/sys v0.19.0 + google.golang.org/grpc v1.63.2 gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // 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 @@ -40,15 +41,14 @@ require ( 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.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.1 // 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 @@ -57,43 +57,44 @@ require ( 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/shirou/gopsutil/v3 v3.24.1 // indirect + github.com/shirou/gopsutil/v3 v3.24.3 // 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 + github.com/yusufpapurcu/wmi v1.2.4 // indirect go.opencensus.io v0.24.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 + go.opentelemetry.io/collector v0.100.0 // indirect + go.opentelemetry.io/collector/consumer v0.100.0 // indirect + go.opentelemetry.io/collector/pdata v1.7.0 // indirect + go.opentelemetry.io/collector/pdata/testdata v0.100.0 // indirect + go.opentelemetry.io/collector/semconv v0.100.0 // indirect + go.opentelemetry.io/contrib/config v0.6.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.26.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/bridge/opencensus v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 // indirect + go.opentelemetry.io/otel/metric v1.26.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.opentelemetry.io/otel/trace v1.26.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.0 // indirect + golang.org/x/net v0.24.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-20240123012728-ef4313101c80 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/protobuf v1.32.0 // indirect + gonum.org/v1/gonum v0.15.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/protobuf v1.34.0 // indirect ) replace go.opentelemetry.io/collector => ../ @@ -106,6 +107,8 @@ replace go.opentelemetry.io/collector/component => ../component replace go.opentelemetry.io/collector/pdata => ../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../pdata/testdata + replace go.opentelemetry.io/collector/extension/zpagesextension => ../extension/zpagesextension replace go.opentelemetry.io/collector/extension => ../extension diff --git a/otelcol/go.sum b/otelcol/go.sum index c0bb0cbd6fd..ccfb176713a 100644 --- a/otelcol/go.sum +++ b/otelcol/go.sum @@ -2,8 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT 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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/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/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -42,16 +42,12 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W 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/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -60,8 +56,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= 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= @@ -74,8 +70,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -98,17 +94,17 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:Om 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.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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= -github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= +github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE= +github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg= 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= @@ -120,58 +116,60 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An 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/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 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= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/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/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.opentelemetry.io/contrib/config v0.6.0 h1:M1SRD1Z15XHPGk61tMLI1up77XT5FdrqQSRrlH0fYuk= +go.opentelemetry.io/contrib/config v0.6.0/go.mod h1:t+/kzmRWLN7J+4F/dD4fFvlYCmCO63WYwy/B00IC++c= +go.opentelemetry.io/contrib/propagators/b3 v1.26.0 h1:wgFbVA+bK2k+fGVfDOCOG4cfDAoppyr5sI2dVlh8MWM= +go.opentelemetry.io/contrib/propagators/b3 v1.26.0/go.mod h1:DDktFXxA+fyItAAM0Sbl5OBH7KOsCTjvbBdPKtoIf/k= +go.opentelemetry.io/contrib/zpages v0.51.0 h1:psVr4JTWd0qtISPj9EA6AODGJ09bvsOxWiuKqiGdSCA= +go.opentelemetry.io/contrib/zpages v0.51.0/go.mod h1:PKtp+NEp1gTTLmFHpynYgYCSkKtisPntOb9S1mQjFKg= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/bridge/opencensus v1.26.0 h1:DZzxj9QjznMVoehskOJnFP2gsTCWtDTFBDvFhPAY7nc= +go.opentelemetry.io/otel/bridge/opencensus v1.26.0/go.mod h1:rJiX0KrF5m8Tm1XE8jLczpAv5zUaDcvhKecFG0ZoFG4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 h1:+hm+I+KigBy3M24/h1p/NHkUx/evbLH0PNcjpMyCHc4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0/go.mod h1:NjC8142mLvvNT6biDpaMjyz78kyEHIwAJlSX0N9P5KI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 h1:HGZWGmCVRCVyAs2GQaiHQPbDHo+ObFWeUEOd+zDnp64= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0/go.mod h1:SaH+v38LSCHddyk7RGlU9uZyQoRrKao6IBnJw6Kbn+c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 h1:1u/AyyOqAWzy+SkPxDpahCNZParHV8Vid1RnI2clyDE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0/go.mod h1:z46paqbJ9l7c9fIPCXTqTGwhQZ5XoTIsfeFYWboizjs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 h1:Waw9Wfpo/IXzOI8bCB7DIk+0JZcqqsyn1JFnAc+iam8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0/go.mod h1:wnJIG4fOqyynOnnQF/eQb4/16VlX2EJAHhHgqIqWfAo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 h1:1wp/gyxsuYtuE/JFxsQRtcCDtMrO2qMvlfXALU5wkzI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0/go.mod h1:gbTHmghkGgqxMomVQQMur1Nba4M0MQ8AYThXDUjsJ38= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 h1:5fnmgteaar1VcAA69huatudPduNFz7guRtCmfZCooZI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0/go.mod h1:lsPccfZiz1cb1AhBPmicWM2E4F1VynFXEvD8SEBS4TM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 h1:0W5o9SzoR15ocYHEQfvfipzcNog1lBxOLfnex91Hk6s= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0/go.mod h1:zVZ8nz+VSggWmnh6tTsJqXQ7rU4xLwRtna1M4x5jq58= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= 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= @@ -182,8 +180,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk 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-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= 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= @@ -198,8 +196,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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= @@ -214,9 +212,9 @@ 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.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/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -233,26 +231,26 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= -gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= +gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= +gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= 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 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/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 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.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= -google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 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= @@ -262,10 +260,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 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/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= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/otelcol/internal/configunmarshaler/configs.go b/otelcol/internal/configunmarshaler/configs.go index ab226d3b670..05cc8b11296 100644 --- a/otelcol/internal/configunmarshaler/configs.go +++ b/otelcol/internal/configunmarshaler/configs.go @@ -5,7 +5,8 @@ package configunmarshaler // import "go.opentelemetry.io/collector/otelcol/inter import ( "fmt" - "reflect" + + "golang.org/x/exp/maps" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/confmap" @@ -34,7 +35,7 @@ func (c *Configs[F]) Unmarshal(conf *confmap.Conf) error { // Find factory based on component kind and type that we read from config source. factory, ok := c.factories[id.Type()] if !ok { - return errorUnknownType(id, reflect.ValueOf(c.factories).MapKeys()) + return errorUnknownType(id, maps.Keys(c.factories)) } // Create the default config for this component. @@ -56,7 +57,7 @@ func (c *Configs[F]) Configs() map[component.ID]component.Config { return c.cfgs } -func errorUnknownType(id component.ID, factories []reflect.Value) error { +func errorUnknownType(id component.ID, factories []component.Type) error { return fmt.Errorf("unknown type: %q for id: %q (valid values: %v)", id.Type(), id, factories) } diff --git a/otelcol/internal/configunmarshaler/configs_test.go b/otelcol/internal/configunmarshaler/configs_test.go index f6cd2865281..56c48e773f5 100644 --- a/otelcol/internal/configunmarshaler/configs_test.go +++ b/otelcol/internal/configunmarshaler/configs_test.go @@ -104,7 +104,7 @@ func TestUnmarshalError(t *testing.T) { conf: confmap.NewFromStringMap(map[string]any{ "nosuch" + tk.kind: nil, }), - expectedError: "unknown type: \"nosuch" + tk.kind + "\"", + expectedError: "unknown type: \"nosuch" + tk.kind + "\" for id: \"nosuch" + tk.kind + "\" (valid values: [nop])", }, { name: "duplicate", diff --git a/otelcol/otelcoltest/config.go b/otelcol/otelcoltest/config.go index fc2957d893a..6191eb9dbec 100644 --- a/otelcol/otelcoltest/config.go +++ b/otelcol/otelcoltest/config.go @@ -21,13 +21,13 @@ func LoadConfig(fileName string, factories otelcol.Factories) (*otelcol.Config, provider, err := otelcol.NewConfigProvider(otelcol.ConfigProviderSettings{ ResolverSettings: confmap.ResolverSettings{ 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{})}, + ProviderFactories: []confmap.ProviderFactory{ + fileprovider.NewFactory(), + envprovider.NewFactory(), + yamlprovider.NewFactory(), + httpprovider.NewFactory(), + }, + ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()}, }, }) if err != nil { @@ -44,11 +44,3 @@ func LoadConfigAndValidate(fileName string, factories otelcol.Factories) (*otelc } return cfg, cfg.Validate() } - -func makeMapProvidersMap(providers ...confmap.Provider) map[string]confmap.Provider { - ret := make(map[string]confmap.Provider, len(providers)) - for _, provider := range providers { - ret[provider.Scheme()] = provider - } - return ret -} diff --git a/otelcol/testdata/components-output.yaml b/otelcol/testdata/components-output.yaml new file mode 100644 index 00000000000..929ae01945b --- /dev/null +++ b/otelcol/testdata/components-output.yaml @@ -0,0 +1,43 @@ +buildinfo: + command: otelcol + description: OpenTelemetry Collector + version: latest +receivers: + - name: nop + stability: + logs: Stable + metrics: Stable + traces: Stable + - name: nop_logs + stability: + logs: Stable + metrics: Undefined + traces: Undefined +processors: + - name: nop + stability: + logs: Stable + metrics: Stable + traces: Stable +exporters: + - name: nop + stability: + logs: Stable + metrics: Stable + traces: Stable +connectors: + - name: nop + stability: + logs-to-logs: Development + logs-to-metrics: Development + logs-to-traces: Development + metrics-to-logs: Development + metrics-to-metrics: Development + metrics-to-traces: Development + traces-to-logs: Development + traces-to-metrics: Development + traces-to-traces: Development +extensions: + - name: nop + stability: + extension: Stable diff --git a/otelcol/testdata/otel-log-to-file.yaml b/otelcol/testdata/otel-log-to-file.yaml new file mode 100644 index 00000000000..e618aca22fc --- /dev/null +++ b/otelcol/testdata/otel-log-to-file.yaml @@ -0,0 +1,30 @@ +extensions: + zpages: + +receivers: + otlp: + protocols: + grpc: + http: + +exporters: + debug: + verbosity: detailed + +service: + telemetry: + logs: + level: warn + output_paths: + # The folder need to be created prior to starting the collector + - ${ProgramData}\OpenTelemetry\Collector\Logs\otelcol.log + + pipelines: + traces: + receivers: [otlp] + exporters: [debug] + metrics: + receivers: [otlp] + exporters: [debug] + + extensions: [zpages] diff --git a/otelcol/testdata/otelcol-invalid-receiver-type.yaml b/otelcol/testdata/otelcol-invalid-receiver-type.yaml new file mode 100644 index 00000000000..5837810fcca --- /dev/null +++ b/otelcol/testdata/otelcol-invalid-receiver-type.yaml @@ -0,0 +1,18 @@ +receivers: + nop_logs: + +processors: + nop: + +exporters: + nop: + +service: + telemetry: + metrics: + address: localhost:8888 + pipelines: + traces: + receivers: [nop_logs] + processors: [nop] + exporters: [nop] diff --git a/otelcol/unmarshaler.go b/otelcol/unmarshaler.go index 643e396db42..a522d9fa60d 100644 --- a/otelcol/unmarshaler.go +++ b/otelcol/unmarshaler.go @@ -59,7 +59,7 @@ func unmarshal(v *confmap.Conf, factories Factories) (*configSettings, error) { InitialFields: map[string]any(nil), }, Metrics: telemetry.MetricsConfig{ - Level: configtelemetry.LevelBasic, + Level: configtelemetry.LevelNormal, Address: ":8888", }, }, diff --git a/pdata/go.mod b/pdata/go.mod index 5adab7efc2d..81fa331f77c 100644 --- a/pdata/go.mod +++ b/pdata/go.mod @@ -5,25 +5,24 @@ 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 + github.com/stretchr/testify v1.9.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 - google.golang.org/grpc v1.62.0 - google.golang.org/protobuf v1.32.0 + google.golang.org/grpc v1.63.2 + google.golang.org/protobuf v1.34.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/kr/pretty v0.3.1 // 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/rogpeppe/go-internal v1.10.0 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/sys v0.16.0 // indirect + golang.org/x/net v0.23.0 // indirect + golang.org/x/sys v0.18.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/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // 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 989737ec2ef..93e99b1aad8 100644 --- a/pdata/go.sum +++ b/pdata/go.sum @@ -4,10 +4,6 @@ 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/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= @@ -35,8 +31,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/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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -52,16 +48,16 @@ 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.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 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.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.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= @@ -74,14 +70,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/pmetric_package.go b/pdata/internal/cmd/pdatagen/internal/pmetric_package.go index 95487c00f8f..68aee5219f9 100644 --- a/pdata/internal/cmd/pdatagen/internal/pmetric_package.go +++ b/pdata/internal/cmd/pdatagen/internal/pmetric_package.go @@ -115,6 +115,10 @@ var metric = &messageValueStruct{ defaultVal: `""`, testVal: `"1"`, }, + &sliceField{ + fieldName: "Metadata", + returnSlice: mapStruct, + }, &oneOfField{ typeName: "MetricType", originFieldName: "Data", diff --git a/pdata/internal/data/protogen/metrics/v1/metrics.pb.go b/pdata/internal/data/protogen/metrics/v1/metrics.pb.go index 4ef4f4d5f63..3649bd83f81 100644 --- a/pdata/internal/data/protogen/metrics/v1/metrics.pb.go +++ b/pdata/internal/data/protogen/metrics/v1/metrics.pb.go @@ -467,6 +467,14 @@ type Metric struct { // *Metric_ExponentialHistogram // *Metric_Summary Data isMetric_Data `protobuf_oneof:"data"` + // Additional metadata attributes that describe the metric. [Optional]. + // Attributes are non-identifying. + // Consumers SHOULD NOT need to be aware of these attributes. + // These attributes MAY be used to encode information allowing + // for lossless roundtrip translation to / from another data model. + // Attribute keys MUST be unique (it is not allowed to have more than one + // attribute with the same key). + Metadata []v11.KeyValue `protobuf:"bytes,12,rep,name=metadata,proto3" json:"metadata"` } func (m *Metric) Reset() { *m = Metric{} } @@ -593,6 +601,13 @@ func (m *Metric) GetSummary() *Summary { return nil } +func (m *Metric) GetMetadata() []v11.KeyValue { + if m != nil { + return m.Metadata + } + return nil +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*Metric) XXX_OneofWrappers() []interface{} { return []interface{}{ @@ -1963,105 +1978,105 @@ func init() { } var fileDescriptor_3c3112f9fa006917 = []byte{ - // 1553 bytes of a gzipped FileDescriptorProto + // 1568 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xcd, 0x4f, 0x1b, 0x49, 0x16, 0x77, 0xfb, 0xdb, 0xcf, 0x06, 0x9c, 0x5a, 0x96, 0xb4, 0x58, 0xe1, 0x38, 0xce, 0x26, 0xb0, 0xd9, 0xc8, 0x5e, 0xc8, 0x6a, 0x3f, 0x0e, 0x91, 0x62, 0x63, 0x03, 0x26, 0x80, 0x49, 0xd9, 0x20, 0x25, 0x8a, 0xd2, 0x2a, 0xec, 0xc2, 0xb4, 0xd2, 0xdd, 0xe5, 0xed, 0xae, 0x46, 0xb0, 0xff, 0xc1, - 0x4a, 0x7b, 0xc8, 0xdf, 0xb1, 0xda, 0xdb, 0x9c, 0xe6, 0x36, 0xc7, 0x1c, 0x33, 0xb7, 0xd1, 0x68, - 0x14, 0xcd, 0x90, 0xc3, 0x8c, 0x34, 0xff, 0xc4, 0xa8, 0xaa, 0xbb, 0xf1, 0x07, 0x26, 0x26, 0x1f, - 0x87, 0xe4, 0xd4, 0x55, 0xaf, 0xde, 0xfb, 0xd5, 0xfb, 0xf8, 0x55, 0xbd, 0x52, 0xc3, 0x3d, 0xd6, - 0xa3, 0x16, 0xa7, 0x06, 0x35, 0x29, 0xb7, 0x4f, 0x4b, 0x3d, 0x9b, 0x71, 0x56, 0x12, 0x63, 0xbd, - 0xed, 0x94, 0x8e, 0x97, 0x83, 0x61, 0x51, 0x2e, 0xa0, 0xdc, 0x90, 0xb6, 0x27, 0x2c, 0x06, 0x2a, - 0xc7, 0xcb, 0xf3, 0xb3, 0x5d, 0xd6, 0x65, 0x1e, 0x86, 0x18, 0x79, 0x0a, 0xf3, 0x77, 0xc7, 0xed, - 0xd1, 0x66, 0xa6, 0xc9, 0x2c, 0xb1, 0x85, 0x37, 0xf2, 0x75, 0x8b, 0xe3, 0x74, 0x6d, 0xea, 0x30, - 0xd7, 0x6e, 0x53, 0xa1, 0x1d, 0x8c, 0x3d, 0xfd, 0x82, 0x0e, 0xe9, 0x6d, 0x6f, 0xff, 0x2a, 0xe1, - 0x04, 0x3d, 0x85, 0x6c, 0xa0, 0xa0, 0xf9, 0x7e, 0xa9, 0x4a, 0x3e, 0xb2, 0x94, 0x5e, 0x29, 0x15, - 0xdf, 0xed, 0x7b, 0x11, 0xfb, 0x76, 0x3e, 0x1c, 0x9e, 0xb1, 0x87, 0x05, 0x85, 0xaf, 0xc3, 0x30, - 0x33, 0xa2, 0x84, 0xba, 0xa0, 0x76, 0x68, 0xcf, 0xa6, 0x6d, 0xc2, 0x69, 0x47, 0x73, 0xda, 0xac, - 0xd7, 0xdf, 0xf7, 0x97, 0x84, 0xdc, 0xf8, 0xde, 0xa4, 0x8d, 0x9b, 0xc2, 0x2a, 0xd8, 0x75, 0xae, - 0x0f, 0x37, 0x28, 0x47, 0x8f, 0x20, 0x19, 0xf8, 0xa3, 0x2a, 0x79, 0x65, 0x29, 0xbd, 0xf2, 0xa7, - 0xb1, 0xb8, 0xe7, 0xe9, 0x19, 0x88, 0xa8, 0x12, 0x7d, 0xf5, 0xe6, 0x46, 0x08, 0x9f, 0x03, 0xa0, - 0xc7, 0x30, 0x35, 0xec, 0x6a, 0xf8, 0x03, 0x3c, 0xcd, 0x38, 0x83, 0xfe, 0x2d, 0x00, 0x38, 0xed, - 0x23, 0x6a, 0x12, 0xcd, 0xb5, 0x0d, 0x35, 0x92, 0x57, 0x96, 0x52, 0x38, 0xe5, 0x49, 0xf6, 0x6c, - 0xa3, 0xf0, 0x8d, 0x02, 0x99, 0xa1, 0x78, 0x1a, 0x10, 0x93, 0xf6, 0x7e, 0x30, 0xf7, 0xc7, 0x6e, - 0xed, 0x33, 0xe3, 0x78, 0xb9, 0x58, 0xb7, 0x1c, 0x6e, 0xbb, 0x26, 0xb5, 0x38, 0xe1, 0x3a, 0xb3, - 0x24, 0x94, 0x1f, 0x96, 0x87, 0x83, 0x1e, 0x42, 0x62, 0x38, 0x9a, 0x3b, 0x93, 0xa2, 0xf1, 0x5c, - 0xc1, 0x81, 0xd9, 0xa4, 0x10, 0x7e, 0x8a, 0x40, 0xdc, 0x33, 0x41, 0x08, 0xa2, 0x16, 0x31, 0x3d, - 0xdf, 0x53, 0x58, 0x8e, 0x51, 0x1e, 0xd2, 0x1d, 0xea, 0xb4, 0x6d, 0xbd, 0x27, 0x1c, 0x54, 0xc3, - 0x72, 0x69, 0x50, 0x24, 0xac, 0x5c, 0x4b, 0xe7, 0x3e, 0xb2, 0x1c, 0xa3, 0x07, 0x10, 0xeb, 0x12, - 0xb7, 0x4b, 0xd5, 0x98, 0x4c, 0xc3, 0xed, 0x49, 0x3e, 0xaf, 0x0b, 0xe5, 0x8d, 0x10, 0xf6, 0xac, - 0xd0, 0xdf, 0x21, 0xe2, 0xb8, 0xa6, 0x9a, 0x90, 0xc6, 0xb7, 0x26, 0x96, 0xcf, 0x35, 0x37, 0x42, - 0x58, 0x58, 0xa0, 0x3a, 0xa4, 0x8e, 0x74, 0x87, 0xb3, 0xae, 0x4d, 0x4c, 0x35, 0xf5, 0x0e, 0x3e, - 0x0d, 0x98, 0x6f, 0x04, 0x06, 0x1b, 0x21, 0xdc, 0xb7, 0x46, 0x2f, 0xe0, 0xf7, 0xf4, 0xa4, 0xc7, - 0x2c, 0x6a, 0x71, 0x9d, 0x18, 0x5a, 0x1f, 0x16, 0x24, 0xec, 0x5f, 0x27, 0xc1, 0xd6, 0xfa, 0xc6, - 0x83, 0x3b, 0xcc, 0xd2, 0x31, 0x72, 0xb4, 0x0a, 0x09, 0xc7, 0x35, 0x4d, 0x62, 0x9f, 0xaa, 0x69, - 0x09, 0xbf, 0x78, 0x85, 0xa0, 0x85, 0xfa, 0x46, 0x08, 0x07, 0x96, 0x95, 0x38, 0x44, 0x3b, 0x84, - 0x93, 0xcd, 0x68, 0x32, 0x9a, 0x8d, 0x6d, 0x46, 0x93, 0xf1, 0x6c, 0x62, 0x33, 0x9a, 0x4c, 0x66, - 0x53, 0x85, 0x27, 0x10, 0x93, 0x19, 0x46, 0xbb, 0x90, 0x16, 0x2a, 0x5a, 0x8f, 0xe9, 0x16, 0xbf, - 0xf2, 0x15, 0xb2, 0xe3, 0x9a, 0x07, 0xd4, 0x16, 0x17, 0xd1, 0xae, 0xb0, 0xc3, 0xd0, 0x09, 0x86, - 0x4e, 0xe1, 0x57, 0x05, 0x22, 0x4d, 0xd7, 0xfc, 0xf4, 0xc8, 0x88, 0xc1, 0x75, 0xd2, 0xed, 0xda, - 0xb4, 0x2b, 0x8f, 0x86, 0xc6, 0xa9, 0xd9, 0x63, 0x36, 0x31, 0x74, 0x7e, 0x2a, 0x59, 0x38, 0xbd, - 0xf2, 0xb7, 0x49, 0xe8, 0xe5, 0xbe, 0x79, 0xab, 0x6f, 0x8d, 0xe7, 0xc8, 0x58, 0x39, 0xba, 0x09, - 0x19, 0xdd, 0xd1, 0x4c, 0x66, 0x31, 0xce, 0x2c, 0xbd, 0x2d, 0x09, 0x9d, 0xc4, 0x69, 0xdd, 0xd9, - 0x0e, 0x44, 0x85, 0x6f, 0x15, 0x48, 0xf5, 0xab, 0xd6, 0x1c, 0x17, 0xf3, 0xca, 0x95, 0xf9, 0xf6, - 0x79, 0x84, 0x5d, 0xf8, 0x59, 0x81, 0xd9, 0x71, 0x64, 0x45, 0xcf, 0xc7, 0x85, 0xf7, 0xe0, 0x43, - 0x78, 0xff, 0x99, 0x44, 0xfa, 0x0c, 0x12, 0xfe, 0xb1, 0x41, 0x8f, 0xc7, 0xc5, 0xf6, 0x97, 0x2b, - 0x1e, 0xba, 0xf1, 0x27, 0xe1, 0x2c, 0x0c, 0x33, 0x23, 0x7c, 0x46, 0xdb, 0x00, 0x84, 0x73, 0x5b, - 0x3f, 0x70, 0x39, 0x75, 0x54, 0xaf, 0x71, 0x2e, 0x4e, 0xe8, 0x09, 0x8f, 0xe8, 0xe9, 0x3e, 0x31, - 0xdc, 0xa0, 0x0f, 0x0c, 0x00, 0xa0, 0x12, 0xcc, 0x3a, 0x9c, 0xd8, 0x5c, 0xe3, 0xba, 0x49, 0x35, - 0xd7, 0xd2, 0x4f, 0x34, 0x8b, 0x58, 0x4c, 0xa6, 0x2b, 0x8e, 0xaf, 0xc9, 0xb5, 0x96, 0x6e, 0xd2, - 0x3d, 0x4b, 0x3f, 0xd9, 0x21, 0x16, 0x43, 0x7f, 0x84, 0xe9, 0x11, 0xd5, 0x88, 0x54, 0xcd, 0xf0, - 0x41, 0xad, 0x05, 0x48, 0x11, 0x47, 0xeb, 0x30, 0xf7, 0xc0, 0xa0, 0x6a, 0x34, 0xaf, 0x2c, 0x29, - 0x1b, 0x21, 0x9c, 0x24, 0x4e, 0x55, 0x4a, 0xd0, 0x75, 0x88, 0x13, 0x47, 0xd3, 0x2d, 0xae, 0xc6, - 0xf3, 0xca, 0x52, 0x56, 0x5c, 0xd3, 0xc4, 0xa9, 0x5b, 0x1c, 0x6d, 0x41, 0x8a, 0x9e, 0x50, 0xb3, - 0x67, 0x10, 0xdb, 0x51, 0x63, 0x32, 0xb8, 0xa5, 0xc9, 0xf4, 0xf0, 0x0c, 0xfc, 0xe8, 0xfa, 0x00, - 0x68, 0x16, 0x62, 0x87, 0x06, 0xe9, 0x3a, 0x6a, 0x32, 0xaf, 0x2c, 0x4d, 0x61, 0x6f, 0x52, 0x49, - 0x40, 0xec, 0x58, 0x64, 0x63, 0x33, 0x9a, 0x54, 0xb2, 0xe1, 0xc2, 0x0f, 0x11, 0x40, 0x17, 0x69, - 0x35, 0x92, 0xe7, 0xd4, 0x67, 0x9a, 0xe7, 0x59, 0x88, 0xb5, 0x99, 0x6b, 0x71, 0x99, 0xe3, 0x38, - 0xf6, 0x26, 0x08, 0x79, 0xcd, 0x2e, 0xe6, 0xe7, 0x5d, 0xf6, 0xb1, 0x5b, 0x30, 0x75, 0xe0, 0xb6, - 0x5f, 0x50, 0xae, 0x49, 0x1d, 0x47, 0x8d, 0xe7, 0x23, 0x02, 0xce, 0x13, 0xae, 0x4a, 0x19, 0x5a, - 0x84, 0x19, 0x7a, 0xd2, 0x33, 0xf4, 0xb6, 0xce, 0xb5, 0x03, 0xe6, 0x5a, 0x1d, 0x8f, 0x61, 0x0a, - 0x9e, 0x0e, 0xc4, 0x15, 0x29, 0x1d, 0xae, 0x53, 0xf2, 0x93, 0xd5, 0x09, 0x06, 0xea, 0x24, 0xa2, - 0x30, 0x75, 0x4b, 0x76, 0x2f, 0x65, 0x43, 0xc1, 0x62, 0x22, 0x65, 0xe4, 0x44, 0xcd, 0x48, 0x59, - 0x18, 0x8b, 0x89, 0x68, 0x52, 0x8e, 0x6b, 0x6a, 0xe2, 0x6b, 0xea, 0x96, 0xf7, 0x25, 0x27, 0x9a, - 0x5f, 0xde, 0xff, 0xc4, 0x61, 0xe1, 0x9d, 0x17, 0xc8, 0x48, 0xa5, 0x95, 0x2f, 0xbe, 0xd2, 0xb3, - 0xe2, 0xc1, 0x48, 0x0c, 0x2a, 0xcf, 0xd6, 0x35, 0xec, 0x4d, 0xc4, 0x9b, 0xed, 0xdf, 0xd4, 0x66, - 0x5e, 0xf5, 0xe5, 0x3b, 0x28, 0x8e, 0x53, 0x42, 0x22, 0x4b, 0x8f, 0xba, 0x90, 0xec, 0x31, 0x47, - 0xe7, 0xfa, 0x31, 0x95, 0xa7, 0x25, 0xbd, 0x52, 0xfb, 0xa8, 0x6b, 0xb9, 0x58, 0x91, 0xbc, 0x72, - 0x82, 0x17, 0x75, 0x00, 0x2e, 0x36, 0xb2, 0xe4, 0x45, 0x7a, 0x4c, 0xfd, 0xe7, 0xd4, 0xa7, 0xdd, - 0x28, 0x00, 0xbf, 0x84, 0x54, 0x43, 0xc4, 0x4d, 0x7f, 0x2c, 0x71, 0x7d, 0x8a, 0x66, 0xc6, 0x50, - 0x74, 0x6a, 0x80, 0xa2, 0xe8, 0x36, 0x4c, 0xcb, 0xe4, 0xf3, 0x23, 0x9b, 0x3a, 0x47, 0xcc, 0xe8, - 0xa8, 0xd3, 0x62, 0x19, 0x4f, 0x09, 0x69, 0x2b, 0x10, 0xce, 0xaf, 0x41, 0xc2, 0x8f, 0x06, 0xcd, - 0x41, 0x9c, 0x1d, 0x1e, 0x3a, 0x94, 0xcb, 0xa7, 0xf3, 0x35, 0xec, 0xcf, 0x2e, 0x1e, 0x63, 0xf1, - 0x84, 0x8f, 0x0e, 0x1f, 0xe3, 0xcb, 0x4e, 0x44, 0xe1, 0xff, 0x11, 0xc8, 0x8e, 0x36, 0x9c, 0x2f, - 0xa4, 0xa1, 0x8c, 0xa7, 0x7f, 0x76, 0x80, 0xfe, 0x1e, 0xf9, 0x75, 0x98, 0xf9, 0x97, 0x4b, 0x2c, - 0xae, 0x1b, 0x54, 0x93, 0xb7, 0xbc, 0x77, 0xd1, 0xa5, 0x57, 0x1e, 0xbe, 0x6f, 0x27, 0x2e, 0xca, - 0x08, 0xcb, 0xfc, 0xb1, 0x0f, 0x87, 0xa7, 0x03, 0x60, 0xb9, 0x70, 0x49, 0x77, 0x99, 0x5f, 0x85, - 0x99, 0x11, 0x43, 0x34, 0x0f, 0xc9, 0xc0, 0x54, 0x56, 0x53, 0xc1, 0xe7, 0x73, 0x01, 0x22, 0xdd, - 0x94, 0xf9, 0x51, 0xf0, 0x50, 0x67, 0x7a, 0x19, 0x81, 0x64, 0xc0, 0x3d, 0xf4, 0x1c, 0x7e, 0x77, - 0xa8, 0x1b, 0x9c, 0xda, 0xb4, 0xa3, 0x7d, 0x6c, 0xbd, 0x50, 0x80, 0x54, 0xee, 0xd7, 0xed, 0x62, - 0x19, 0xc2, 0x93, 0xfa, 0x7a, 0xe4, 0xea, 0x7d, 0xfd, 0x09, 0x24, 0x9c, 0x1e, 0xb1, 0x34, 0xbd, - 0x23, 0x0b, 0x98, 0xa9, 0x3c, 0x14, 0x8e, 0x7c, 0xff, 0xe6, 0xc6, 0x3f, 0xba, 0x6c, 0xc4, 0x77, - 0x9d, 0x95, 0xda, 0xcc, 0x30, 0x68, 0x9b, 0x33, 0xbb, 0xd4, 0x13, 0xaf, 0xa1, 0x92, 0x6e, 0x71, - 0x6a, 0x5b, 0xc4, 0x28, 0x89, 0x59, 0xb1, 0xd9, 0x23, 0x56, 0xbd, 0x8a, 0xe3, 0x02, 0xb0, 0xde, - 0x41, 0xcf, 0x20, 0xc9, 0x6d, 0xd2, 0xa6, 0x02, 0x3b, 0x26, 0xb1, 0xcb, 0x3e, 0xf6, 0x3f, 0xdf, - 0x1f, 0xbb, 0x25, 0x90, 0xea, 0x55, 0x9c, 0x90, 0x90, 0xf5, 0xce, 0xc8, 0x63, 0xe1, 0xee, 0x7f, - 0x15, 0x98, 0x1b, 0xff, 0x44, 0x44, 0x8b, 0x70, 0xab, 0xbc, 0xbe, 0x8e, 0x6b, 0xeb, 0xe5, 0x56, - 0xbd, 0xb1, 0xa3, 0xb5, 0x6a, 0xdb, 0xbb, 0x0d, 0x5c, 0xde, 0xaa, 0xb7, 0x9e, 0x68, 0x7b, 0x3b, - 0xcd, 0xdd, 0xda, 0x6a, 0x7d, 0xad, 0x5e, 0xab, 0x66, 0x43, 0xe8, 0x26, 0x2c, 0x5c, 0xa6, 0x58, - 0xad, 0x6d, 0xb5, 0xca, 0x59, 0x05, 0xdd, 0x81, 0xc2, 0x65, 0x2a, 0xab, 0x7b, 0xdb, 0x7b, 0x5b, - 0xe5, 0x56, 0x7d, 0xbf, 0x96, 0x0d, 0xdf, 0x7d, 0x0e, 0xd3, 0xe7, 0x7c, 0x5d, 0x93, 0xf7, 0xdb, - 0x0d, 0xf8, 0x43, 0xb5, 0xdc, 0x2a, 0x6b, 0xbb, 0x8d, 0xfa, 0x4e, 0x4b, 0x5b, 0xdb, 0x2a, 0xaf, - 0x37, 0xb5, 0x6a, 0x43, 0xdb, 0x69, 0xb4, 0xb4, 0xbd, 0x66, 0x2d, 0x1b, 0x42, 0x7f, 0x86, 0xc5, - 0x0b, 0x0a, 0x3b, 0x0d, 0x0d, 0xd7, 0x56, 0x1b, 0xb8, 0x5a, 0xab, 0x6a, 0xfb, 0xe5, 0xad, 0xbd, - 0x9a, 0xb6, 0x5d, 0x6e, 0x3e, 0xca, 0x2a, 0x95, 0xaf, 0x94, 0x57, 0x67, 0x39, 0xe5, 0xf5, 0x59, - 0x4e, 0xf9, 0xf1, 0x2c, 0xa7, 0xbc, 0x7c, 0x9b, 0x0b, 0xbd, 0x7e, 0x9b, 0x0b, 0x7d, 0xf7, 0x36, - 0x17, 0x82, 0x9b, 0x3a, 0x9b, 0x70, 0xa2, 0x2a, 0x19, 0xff, 0x17, 0xc6, 0xae, 0x58, 0xd8, 0x55, - 0x9e, 0xd6, 0xde, 0xbb, 0x1e, 0xde, 0x5f, 0xad, 0x2e, 0xb5, 0x06, 0x7e, 0xb4, 0xfd, 0x2f, 0x9c, - 0x6b, 0xf4, 0xa8, 0xd5, 0x3a, 0x07, 0x91, 0xf0, 0xfe, 0x3f, 0x0a, 0xa7, 0xb8, 0xbf, 0x7c, 0x10, - 0x97, 0x56, 0xf7, 0x7f, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x24, 0xc4, 0x73, 0x45, 0xb2, 0x13, 0x00, - 0x00, + 0x4a, 0x7b, 0xc8, 0xdf, 0xb1, 0xca, 0x6d, 0x4f, 0x73, 0x9b, 0x63, 0x8e, 0x99, 0xdb, 0x68, 0x34, + 0x8a, 0x46, 0xe4, 0x30, 0x23, 0xcd, 0x3f, 0x31, 0xaa, 0xea, 0x6e, 0xfc, 0x81, 0x89, 0xc9, 0xc7, + 0x21, 0x39, 0xb9, 0xea, 0xd5, 0x7b, 0xbf, 0x7a, 0xaf, 0xde, 0xef, 0xd5, 0x2b, 0x37, 0xdc, 0x63, + 0x3d, 0x6a, 0x71, 0x6a, 0x50, 0x93, 0x72, 0xfb, 0xb4, 0xd4, 0xb3, 0x19, 0x67, 0x25, 0x31, 0xd6, + 0xdb, 0x4e, 0xe9, 0x78, 0x39, 0x18, 0x16, 0xe5, 0x02, 0xca, 0x0d, 0x69, 0x7b, 0xc2, 0x62, 0xa0, + 0x72, 0xbc, 0x3c, 0x3f, 0xdb, 0x65, 0x5d, 0xe6, 0x61, 0x88, 0x91, 0xa7, 0x30, 0x7f, 0x77, 0xdc, + 0x1e, 0x6d, 0x66, 0x9a, 0xcc, 0x12, 0x5b, 0x78, 0x23, 0x5f, 0xb7, 0x38, 0x4e, 0xd7, 0xa6, 0x0e, + 0x73, 0xed, 0x36, 0x15, 0xda, 0xc1, 0xd8, 0xd3, 0x2f, 0xe8, 0x90, 0xde, 0xf6, 0xf6, 0xaf, 0x12, + 0x4e, 0xd0, 0x53, 0xc8, 0x06, 0x0a, 0x9a, 0xef, 0x97, 0xaa, 0xe4, 0x23, 0x4b, 0xe9, 0x95, 0x52, + 0xf1, 0xfd, 0xbe, 0x17, 0xb1, 0x6f, 0xe7, 0xc3, 0xe1, 0x19, 0x7b, 0x58, 0x50, 0xf8, 0x26, 0x0c, + 0x33, 0x23, 0x4a, 0xa8, 0x0b, 0x6a, 0x87, 0xf6, 0x6c, 0xda, 0x26, 0x9c, 0x76, 0x34, 0xa7, 0xcd, + 0x7a, 0xfd, 0x7d, 0x7f, 0x49, 0xc8, 0x8d, 0xef, 0x4d, 0xda, 0xb8, 0x29, 0xac, 0x82, 0x5d, 0xe7, + 0xfa, 0x70, 0x83, 0x72, 0xf4, 0x08, 0x92, 0x81, 0x3f, 0xaa, 0x92, 0x57, 0x96, 0xd2, 0x2b, 0x7f, + 0x1a, 0x8b, 0x7b, 0x7e, 0x3c, 0x03, 0x11, 0x55, 0xa2, 0xaf, 0xdf, 0xde, 0x08, 0xe1, 0x73, 0x00, + 0xf4, 0x18, 0xa6, 0x86, 0x5d, 0x0d, 0x7f, 0x84, 0xa7, 0x19, 0x67, 0xd0, 0xbf, 0x05, 0x00, 0xa7, + 0x7d, 0x44, 0x4d, 0xa2, 0xb9, 0xb6, 0xa1, 0x46, 0xf2, 0xca, 0x52, 0x0a, 0xa7, 0x3c, 0xc9, 0x9e, + 0x6d, 0x14, 0xbe, 0x55, 0x20, 0x33, 0x14, 0x4f, 0x03, 0x62, 0xd2, 0xde, 0x0f, 0xe6, 0xfe, 0xd8, + 0xad, 0x7d, 0x66, 0x1c, 0x2f, 0x17, 0xeb, 0x96, 0xc3, 0x6d, 0xd7, 0xa4, 0x16, 0x27, 0x5c, 0x67, + 0x96, 0x84, 0xf2, 0xc3, 0xf2, 0x70, 0xd0, 0x43, 0x48, 0x0c, 0x47, 0x73, 0x67, 0x52, 0x34, 0x9e, + 0x2b, 0x38, 0x30, 0x9b, 0x14, 0xc2, 0xab, 0x28, 0xc4, 0x3d, 0x13, 0x84, 0x20, 0x6a, 0x11, 0xd3, + 0xf3, 0x3d, 0x85, 0xe5, 0x18, 0xe5, 0x21, 0xdd, 0xa1, 0x4e, 0xdb, 0xd6, 0x7b, 0xc2, 0x41, 0x35, + 0x2c, 0x97, 0x06, 0x45, 0xc2, 0xca, 0xb5, 0x74, 0xee, 0x23, 0xcb, 0x31, 0x7a, 0x00, 0xb1, 0x2e, + 0x71, 0xbb, 0x54, 0x8d, 0xc9, 0x63, 0xb8, 0x3d, 0xc9, 0xe7, 0x75, 0xa1, 0xbc, 0x11, 0xc2, 0x9e, + 0x15, 0xfa, 0x3b, 0x44, 0x1c, 0xd7, 0x54, 0x13, 0xd2, 0xf8, 0xd6, 0xc4, 0xf4, 0xb9, 0xe6, 0x46, + 0x08, 0x0b, 0x0b, 0x54, 0x87, 0xd4, 0x91, 0xee, 0x70, 0xd6, 0xb5, 0x89, 0xa9, 0xa6, 0xde, 0xc3, + 0xa7, 0x01, 0xf3, 0x8d, 0xc0, 0x60, 0x23, 0x84, 0xfb, 0xd6, 0xe8, 0x05, 0xfc, 0x9e, 0x9e, 0xf4, + 0x98, 0x45, 0x2d, 0xae, 0x13, 0x43, 0xeb, 0xc3, 0x82, 0x84, 0xfd, 0xeb, 0x24, 0xd8, 0x5a, 0xdf, + 0x78, 0x70, 0x87, 0x59, 0x3a, 0x46, 0x8e, 0x56, 0x21, 0xe1, 0xb8, 0xa6, 0x49, 0xec, 0x53, 0x35, + 0x2d, 0xe1, 0x17, 0xaf, 0x10, 0xb4, 0x50, 0xdf, 0x08, 0xe1, 0xc0, 0x12, 0xd5, 0x21, 0x69, 0x52, + 0x4e, 0x3a, 0x84, 0x13, 0x35, 0x23, 0xb9, 0xb2, 0x38, 0x81, 0x7e, 0x8f, 0xe8, 0xe9, 0x3e, 0x31, + 0xdc, 0xf3, 0x4a, 0x0a, 0xcc, 0x2b, 0x71, 0x88, 0x8a, 0xdf, 0xcd, 0x68, 0x32, 0x9a, 0x8d, 0x6d, + 0x46, 0x93, 0xf1, 0x6c, 0x62, 0x33, 0x9a, 0x4c, 0x66, 0x53, 0x85, 0x27, 0x10, 0x93, 0xc9, 0x42, + 0xbb, 0x90, 0x16, 0x2a, 0x5a, 0x8f, 0xe9, 0x16, 0xbf, 0xf2, 0x6d, 0xb4, 0xe3, 0x9a, 0x07, 0xd4, + 0x16, 0x77, 0xda, 0xae, 0xb0, 0xc3, 0xd0, 0x09, 0x86, 0x4e, 0xe1, 0x57, 0x05, 0x22, 0x4d, 0xd7, + 0xfc, 0xfc, 0xc8, 0x88, 0xc1, 0x75, 0xd2, 0xed, 0xda, 0xb4, 0x2b, 0xab, 0x4c, 0xe3, 0xd4, 0xec, + 0x31, 0x9b, 0x18, 0x3a, 0x3f, 0x95, 0x84, 0x9e, 0x5e, 0xf9, 0xdb, 0x24, 0xf4, 0x72, 0xdf, 0xbc, + 0xd5, 0xb7, 0xc6, 0x73, 0x64, 0xac, 0x1c, 0xdd, 0x84, 0x8c, 0xee, 0x68, 0x26, 0xb3, 0x18, 0x67, + 0x96, 0xde, 0x96, 0xb5, 0x91, 0xc4, 0x69, 0xdd, 0xd9, 0x0e, 0x44, 0x85, 0xef, 0x14, 0x48, 0xf5, + 0x09, 0xd0, 0x1c, 0x17, 0xf3, 0xca, 0x95, 0xa9, 0xfb, 0x65, 0x84, 0x5d, 0xf8, 0x59, 0x81, 0xd9, + 0x71, 0xbc, 0x47, 0xcf, 0xc7, 0x85, 0xf7, 0xe0, 0x63, 0x4a, 0xe8, 0x0b, 0x89, 0xf4, 0x19, 0x24, + 0xfc, 0x0a, 0x44, 0x8f, 0xc7, 0xc5, 0xf6, 0x97, 0x2b, 0xd6, 0xef, 0xf8, 0x4a, 0x38, 0x0b, 0xc3, + 0xcc, 0x08, 0x9f, 0xd1, 0x36, 0x00, 0xe1, 0xdc, 0xd6, 0x0f, 0x5c, 0x4e, 0x1d, 0x35, 0xf1, 0x31, + 0xf5, 0x3d, 0x00, 0x80, 0x4a, 0x30, 0xeb, 0x70, 0x62, 0x73, 0x8d, 0xeb, 0x26, 0xd5, 0x5c, 0x4b, + 0x3f, 0xd1, 0x2c, 0x62, 0x31, 0x79, 0x5c, 0x71, 0x7c, 0x4d, 0xae, 0xb5, 0x74, 0x93, 0xee, 0x59, + 0xfa, 0xc9, 0x0e, 0xb1, 0x18, 0xfa, 0x23, 0x4c, 0x8f, 0xa8, 0x46, 0xa4, 0x6a, 0x86, 0x0f, 0x6a, + 0x2d, 0x40, 0x8a, 0x38, 0x5a, 0x87, 0xb9, 0x07, 0x06, 0x55, 0xa3, 0x79, 0x65, 0x49, 0xd9, 0x08, + 0xe1, 0x24, 0x71, 0xaa, 0x52, 0x82, 0xae, 0x43, 0x9c, 0x38, 0x9a, 0x6e, 0x71, 0x35, 0x9e, 0x57, + 0x96, 0xb2, 0xe2, 0xc6, 0x27, 0x4e, 0xdd, 0xe2, 0x68, 0x0b, 0x52, 0xf4, 0x84, 0x9a, 0x3d, 0x83, + 0xd8, 0x8e, 0x1a, 0x93, 0xc1, 0x2d, 0x4d, 0xa6, 0x87, 0x67, 0xe0, 0x47, 0xd7, 0x07, 0x40, 0xb3, + 0x10, 0x3b, 0x34, 0x48, 0xd7, 0x51, 0x93, 0x79, 0x65, 0x69, 0x0a, 0x7b, 0x93, 0x4a, 0x02, 0x62, + 0xc7, 0xe2, 0x34, 0x36, 0xa3, 0x49, 0x25, 0x1b, 0x2e, 0xfc, 0x18, 0x01, 0x74, 0x91, 0x56, 0x23, + 0xe7, 0x9c, 0xfa, 0x42, 0xcf, 0x79, 0x16, 0x62, 0x6d, 0xe6, 0x5a, 0x5c, 0x9e, 0x71, 0x1c, 0x7b, + 0x13, 0x84, 0xbc, 0xbe, 0x19, 0xf3, 0xcf, 0x5d, 0xb6, 0xc4, 0x5b, 0x30, 0x75, 0xe0, 0xb6, 0x5f, + 0x50, 0xae, 0x49, 0x1d, 0x47, 0x8d, 0xe7, 0x23, 0x02, 0xce, 0x13, 0xae, 0x4a, 0x19, 0x5a, 0x84, + 0x19, 0x7a, 0xd2, 0x33, 0xf4, 0xb6, 0xce, 0xb5, 0x03, 0xe6, 0x5a, 0x1d, 0x8f, 0x61, 0x0a, 0x9e, + 0x0e, 0xc4, 0x15, 0x29, 0x1d, 0xce, 0x53, 0xf2, 0xb3, 0xe5, 0x09, 0x06, 0xf2, 0x24, 0xa2, 0x30, + 0x75, 0x4b, 0x36, 0x42, 0x65, 0x43, 0xc1, 0x62, 0x22, 0x65, 0xe4, 0x44, 0xcd, 0x48, 0x59, 0x18, + 0x8b, 0x89, 0x68, 0x52, 0x8e, 0x6b, 0x6a, 0xe2, 0xd7, 0xd4, 0x2d, 0xef, 0x97, 0x9c, 0x68, 0x7e, + 0x7a, 0xff, 0x13, 0x87, 0x85, 0xf7, 0x5e, 0x20, 0x23, 0x99, 0x56, 0xbe, 0xfa, 0x4c, 0xcf, 0x8a, + 0xb7, 0x27, 0x31, 0xa8, 0xac, 0xad, 0x6b, 0xd8, 0x9b, 0x88, 0xe7, 0xdf, 0xbf, 0xa9, 0xcd, 0xbc, + 0xec, 0xcb, 0x27, 0x55, 0x1c, 0xa7, 0x84, 0x44, 0xa6, 0x1e, 0x75, 0x21, 0xd9, 0x63, 0x8e, 0xce, + 0xf5, 0x63, 0x2a, 0xab, 0x25, 0xbd, 0x52, 0xfb, 0xa4, 0x6b, 0xb9, 0x58, 0x91, 0xbc, 0x72, 0x82, + 0x27, 0x45, 0x00, 0x2e, 0x36, 0xb2, 0xe4, 0x45, 0x7a, 0x4c, 0xfd, 0x97, 0xd9, 0xe7, 0xdd, 0x28, + 0x00, 0xbf, 0x84, 0x54, 0x43, 0xc4, 0x4d, 0x7f, 0x2a, 0x71, 0x7d, 0x8a, 0x66, 0xc6, 0x50, 0x74, + 0x6a, 0x80, 0xa2, 0xe8, 0x36, 0x4c, 0xcb, 0xc3, 0xe7, 0x47, 0x36, 0x75, 0x8e, 0x98, 0xd1, 0x51, + 0xa7, 0xc5, 0x32, 0x9e, 0x12, 0xd2, 0x56, 0x20, 0x9c, 0x5f, 0x83, 0x84, 0x1f, 0x0d, 0x9a, 0x83, + 0x38, 0x3b, 0x3c, 0x74, 0x28, 0x97, 0xaf, 0xf0, 0x6b, 0xd8, 0x9f, 0x5d, 0x2c, 0x63, 0xf1, 0x6f, + 0x20, 0x3a, 0x5c, 0xc6, 0x97, 0x55, 0x44, 0xe1, 0x55, 0x04, 0xb2, 0xa3, 0x0d, 0xe7, 0x2b, 0x69, + 0x28, 0xe3, 0xe9, 0x9f, 0x1d, 0xa0, 0xbf, 0x47, 0x7e, 0x1d, 0x66, 0xfe, 0xe5, 0x12, 0x8b, 0xeb, + 0x06, 0xd5, 0xe4, 0x2d, 0xef, 0x5d, 0x74, 0xe9, 0x95, 0x87, 0x1f, 0xda, 0x89, 0x8b, 0x32, 0xc2, + 0x32, 0x7f, 0xec, 0xc3, 0xe1, 0xe9, 0x00, 0x58, 0x2e, 0x5c, 0xd2, 0x5d, 0xe6, 0x57, 0x61, 0x66, + 0xc4, 0x10, 0xcd, 0x43, 0x32, 0x30, 0x95, 0xd9, 0x54, 0xf0, 0xf9, 0x5c, 0x80, 0x48, 0x37, 0xe5, + 0xf9, 0x28, 0x78, 0xa8, 0x33, 0xbd, 0x8c, 0x40, 0x32, 0xe0, 0x1e, 0x7a, 0x0e, 0xbf, 0x3b, 0xd4, + 0x0d, 0x4e, 0x6d, 0xda, 0xd1, 0x3e, 0x35, 0x5f, 0x28, 0x40, 0x2a, 0xf7, 0xf3, 0x76, 0x31, 0x0d, + 0xe1, 0x49, 0x7d, 0x3d, 0x72, 0xf5, 0xbe, 0xfe, 0x04, 0x12, 0x4e, 0x8f, 0x58, 0x9a, 0xde, 0x91, + 0x09, 0xcc, 0x54, 0x1e, 0x0a, 0x47, 0x7e, 0x78, 0x7b, 0xe3, 0x1f, 0x5d, 0x36, 0xe2, 0xbb, 0xce, + 0x4a, 0x6d, 0x66, 0x18, 0xb4, 0xcd, 0x99, 0x5d, 0xea, 0x89, 0xd7, 0x50, 0x49, 0xb7, 0x38, 0xb5, + 0x2d, 0x62, 0x94, 0xc4, 0xac, 0xd8, 0xec, 0x11, 0xab, 0x5e, 0xc5, 0x71, 0x01, 0x58, 0xef, 0xa0, + 0x67, 0x90, 0xe4, 0x36, 0x69, 0x53, 0x81, 0x1d, 0x93, 0xd8, 0x65, 0x1f, 0xfb, 0x9f, 0x1f, 0x8e, + 0xdd, 0x12, 0x48, 0xf5, 0x2a, 0x4e, 0x48, 0xc8, 0x7a, 0x67, 0xe4, 0xb1, 0x70, 0xf7, 0xbf, 0x0a, + 0xcc, 0x8d, 0x7f, 0x22, 0xa2, 0x45, 0xb8, 0x55, 0x5e, 0x5f, 0xc7, 0xb5, 0xf5, 0x72, 0xab, 0xde, + 0xd8, 0xd1, 0x5a, 0xb5, 0xed, 0xdd, 0x06, 0x2e, 0x6f, 0xd5, 0x5b, 0x4f, 0xb4, 0xbd, 0x9d, 0xe6, + 0x6e, 0x6d, 0xb5, 0xbe, 0x56, 0xaf, 0x55, 0xb3, 0x21, 0x74, 0x13, 0x16, 0x2e, 0x53, 0xac, 0xd6, + 0xb6, 0x5a, 0xe5, 0xac, 0x82, 0xee, 0x40, 0xe1, 0x32, 0x95, 0xd5, 0xbd, 0xed, 0xbd, 0xad, 0x72, + 0xab, 0xbe, 0x5f, 0xcb, 0x86, 0xef, 0x3e, 0x87, 0xe9, 0x73, 0xbe, 0xae, 0xc9, 0xfb, 0xed, 0x06, + 0xfc, 0xa1, 0x5a, 0x6e, 0x95, 0xb5, 0xdd, 0x46, 0x7d, 0xa7, 0xa5, 0xad, 0x6d, 0x95, 0xd7, 0x9b, + 0x5a, 0xb5, 0xa1, 0xed, 0x34, 0x5a, 0xda, 0x5e, 0xb3, 0x96, 0x0d, 0xa1, 0x3f, 0xc3, 0xe2, 0x05, + 0x85, 0x9d, 0x86, 0x86, 0x6b, 0xab, 0x0d, 0x5c, 0xad, 0x55, 0xb5, 0xfd, 0xf2, 0xd6, 0x5e, 0x4d, + 0xdb, 0x2e, 0x37, 0x1f, 0x65, 0x95, 0xca, 0xff, 0x95, 0xd7, 0x67, 0x39, 0xe5, 0xcd, 0x59, 0x4e, + 0xf9, 0xe9, 0x2c, 0xa7, 0xbc, 0x7c, 0x97, 0x0b, 0xbd, 0x79, 0x97, 0x0b, 0x7d, 0xff, 0x2e, 0x17, + 0x82, 0x9b, 0x3a, 0x9b, 0x50, 0x51, 0x95, 0x8c, 0xff, 0x35, 0x64, 0x57, 0x2c, 0xec, 0x2a, 0x4f, + 0x6b, 0x1f, 0x9c, 0x0f, 0xef, 0x03, 0x59, 0x97, 0x5a, 0x03, 0xdf, 0xec, 0xfe, 0x17, 0xce, 0x35, + 0x7a, 0xd4, 0x6a, 0x9d, 0x83, 0x48, 0x78, 0xff, 0x73, 0x87, 0x53, 0xdc, 0x5f, 0x3e, 0x88, 0x4b, + 0xab, 0xfb, 0xbf, 0x05, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa3, 0x78, 0x2c, 0xfd, 0x13, 0x00, 0x00, } func (m *MetricsData) Marshal() (dAtA []byte, err error) { @@ -2245,6 +2260,20 @@ func (m *Metric) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Metadata) > 0 { + for iNdEx := len(m.Metadata) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Metadata[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMetrics(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 + } + } if m.Data != nil { { size := m.Data.Size() @@ -3386,6 +3415,12 @@ func (m *Metric) Size() (n int) { if m.Data != nil { n += m.Data.Size() } + if len(m.Metadata) > 0 { + for _, e := range m.Metadata { + l = e.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + } return n } @@ -4580,6 +4615,40 @@ func (m *Metric) Unmarshal(dAtA []byte) error { } m.Data = &Metric_Summary{v} iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMetrics + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Metadata = append(m.Metadata, v11.KeyValue{}) + if err := m.Metadata[len(m.Metadata)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipMetrics(dAtA[iNdEx:]) diff --git a/pdata/internal/data/protogen/trace/v1/trace.pb.go b/pdata/internal/data/protogen/trace/v1/trace.pb.go index 71f32df0f70..c1fcf0764e0 100644 --- a/pdata/internal/data/protogen/trace/v1/trace.pb.go +++ b/pdata/internal/data/protogen/trace/v1/trace.pb.go @@ -51,16 +51,25 @@ const ( SpanFlags_SPAN_FLAGS_DO_NOT_USE SpanFlags = 0 // Bits 0-7 are used for trace flags. SpanFlags_SPAN_FLAGS_TRACE_FLAGS_MASK SpanFlags = 255 + // Bits 8 and 9 are used to indicate that the parent span or link span is remote. + // Bit 8 (`HAS_IS_REMOTE`) indicates whether the value is known. + // Bit 9 (`IS_REMOTE`) indicates whether the span or link is remote. + SpanFlags_SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK SpanFlags = 256 + SpanFlags_SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK SpanFlags = 512 ) var SpanFlags_name = map[int32]string{ 0: "SPAN_FLAGS_DO_NOT_USE", 255: "SPAN_FLAGS_TRACE_FLAGS_MASK", + 256: "SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK", + 512: "SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK", } var SpanFlags_value = map[string]int32{ - "SPAN_FLAGS_DO_NOT_USE": 0, - "SPAN_FLAGS_TRACE_FLAGS_MASK": 255, + "SPAN_FLAGS_DO_NOT_USE": 0, + "SPAN_FLAGS_TRACE_FLAGS_MASK": 255, + "SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK": 256, + "SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK": 512, } func (x SpanFlags) String() string { @@ -388,20 +397,27 @@ 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`. + // Flags, a bit field. + // + // Bits 0-7 (8 least significant bits) are the trace flags as defined in W3C Trace + // Context specification. To read the 8-bit W3C trace flag, use + // `flags & SPAN_FLAGS_TRACE_FLAGS_MASK`. + // + // See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. + // + // Bits 8 and 9 represent the 3 states of whether a span's parent + // is remote. The states are (unknown, is not remote, is remote). + // To read whether the value is known, use `(flags & SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK) != 0`. + // To read whether the span is remote, use `(flags & SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK) != 0`. // // 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 + // (such as a runtime representation of an OpenTelemetry span), the high 22 bits MUST // be set to zero. + // Readers MUST NOT assume that bits 10-31 (22 most significant bits) will be 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. // @@ -687,14 +703,23 @@ 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]. + // Flags, a bit field. + // + // Bits 0-7 (8 least significant bits) are the trace flags as defined in W3C Trace + // Context specification. To read the 8-bit W3C trace flag, use + // `flags & SPAN_FLAGS_TRACE_FLAGS_MASK`. // // See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. + // + // Bits 8 and 9 represent the 3 states of whether the link is remote. + // The states are (unknown, is not remote, is remote). + // To read whether the value is known, use `(flags & SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK) != 0`. + // To read whether the link is remote, use `(flags & SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK) != 0`. + // + // Readers MUST NOT assume that bits 10-31 (22 most significant bits) will be zero. + // When creating new spans, bits 10-31 (most-significant 22-bits) MUST be zero. + // + // [Optional]. Flags uint32 `protobuf:"fixed32,6,opt,name=flags,proto3" json:"flags,omitempty"` } @@ -833,75 +858,77 @@ func init() { } var fileDescriptor_5c407ac9c675a601 = []byte{ - // 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, + // 1112 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x56, 0xcf, 0x6f, 0x1b, 0x45, + 0x14, 0xf6, 0x3a, 0x6b, 0x3b, 0x79, 0x49, 0xdc, 0xed, 0xe0, 0x56, 0x4b, 0x28, 0x8e, 0xb1, 0x0a, + 0x98, 0x56, 0xb2, 0x49, 0x7b, 0x29, 0x07, 0x44, 0x1d, 0x7b, 0x03, 0x8b, 0x13, 0x3b, 0x9a, 0x5d, + 0x47, 0x80, 0x90, 0x96, 0xad, 0x77, 0x6a, 0x56, 0xb1, 0x67, 0xad, 0xdd, 0x71, 0xd4, 0xde, 0xf8, + 0x13, 0xb8, 0x22, 0x71, 0x47, 0x02, 0xce, 0xdc, 0xb8, 0x57, 0x9c, 0x7a, 0x44, 0x1c, 0x2a, 0x94, + 0x5c, 0xf8, 0x2f, 0x8a, 0x66, 0x66, 0xd7, 0x5e, 0x47, 0x91, 0xd3, 0x48, 0xf4, 0xc2, 0x25, 0x99, + 0x79, 0x3f, 0xbe, 0xef, 0x7b, 0x6f, 0xde, 0x8c, 0x17, 0x6a, 0xc1, 0x84, 0x50, 0x46, 0x46, 0x64, + 0x4c, 0x58, 0xf8, 0xb4, 0x31, 0x09, 0x03, 0x16, 0x34, 0x58, 0xe8, 0x0e, 0x48, 0xe3, 0x64, 0x47, + 0x2e, 0xea, 0xc2, 0x88, 0x6e, 0x2d, 0x44, 0x4a, 0x63, 0x5d, 0x06, 0x9c, 0xec, 0x6c, 0x95, 0x86, + 0xc1, 0x30, 0x90, 0xd9, 0x7c, 0x25, 0xdd, 0x5b, 0x77, 0x2e, 0x42, 0x1f, 0x04, 0xe3, 0x71, 0x40, + 0x39, 0xbc, 0x5c, 0xc5, 0xb1, 0xf5, 0x8b, 0x62, 0x43, 0x12, 0x05, 0xd3, 0x50, 0x8a, 0x49, 0xd6, + 0x32, 0xbe, 0xfa, 0x0d, 0x80, 0xcd, 0xd9, 0xa3, 0xb6, 0xcb, 0x5c, 0x84, 0xa1, 0x98, 0xf8, 0x9d, + 0x68, 0xe2, 0xd2, 0x48, 0x57, 0x2a, 0x2b, 0xb5, 0xf5, 0x7b, 0x77, 0xeb, 0xcb, 0x64, 0xd7, 0x71, + 0x9c, 0x63, 0xf1, 0x14, 0xbc, 0x19, 0xa6, 0xb7, 0xd5, 0x9f, 0xb2, 0xb0, 0xb9, 0x10, 0x80, 0x1c, + 0xb8, 0xe9, 0x91, 0x49, 0x48, 0x06, 0x2e, 0x23, 0x9e, 0x13, 0x0d, 0x82, 0x49, 0xc2, 0xf6, 0x4f, + 0x41, 0xd0, 0xd5, 0x96, 0xd3, 0x59, 0x3c, 0x43, 0x72, 0x95, 0xe6, 0x40, 0x73, 0x2b, 0xea, 0xc0, + 0x6a, 0xa2, 0x41, 0x57, 0x2a, 0x4a, 0x6d, 0xfd, 0xde, 0x07, 0x17, 0x22, 0xce, 0x7a, 0x91, 0xaa, + 0x61, 0x57, 0x7d, 0xf6, 0x62, 0x3b, 0x83, 0x67, 0x00, 0xc8, 0x84, 0xf5, 0xb4, 0xc4, 0xec, 0x15, + 0x15, 0x42, 0x34, 0xd7, 0xf5, 0x36, 0x40, 0x34, 0xf8, 0x96, 0x8c, 0x5d, 0x67, 0x1a, 0x8e, 0xf4, + 0x95, 0x8a, 0x52, 0x5b, 0xc3, 0x6b, 0xd2, 0xd2, 0x0f, 0x47, 0xd5, 0xdf, 0x14, 0x80, 0x54, 0x15, + 0x3d, 0xc8, 0x89, 0xdc, 0xb8, 0x84, 0xfb, 0x17, 0x52, 0xc6, 0x87, 0x7f, 0xb2, 0x53, 0x37, 0x69, + 0xc4, 0xc2, 0xe9, 0x98, 0x50, 0xe6, 0x32, 0x3f, 0xa0, 0x02, 0x28, 0x2e, 0x46, 0xe2, 0xa0, 0x07, + 0x90, 0x4b, 0xd7, 0x50, 0xbd, 0xa4, 0x86, 0x89, 0x4b, 0xb1, 0x4c, 0xb8, 0x4c, 0xf8, 0xaf, 0x9b, + 0xa0, 0xf2, 0x70, 0xf4, 0x35, 0xac, 0x8a, 0x7c, 0xc7, 0xf7, 0x84, 0xea, 0x8d, 0xdd, 0x26, 0x17, + 0xf0, 0xd7, 0x8b, 0xed, 0x8f, 0x86, 0xc1, 0x39, 0x3a, 0x9f, 0xcf, 0xf0, 0x68, 0x44, 0x06, 0x2c, + 0x08, 0x1b, 0x13, 0xcf, 0x65, 0x6e, 0xc3, 0xa7, 0x8c, 0x84, 0xd4, 0x1d, 0x35, 0xf8, 0xae, 0x2e, + 0xe6, 0xd2, 0x6c, 0xe3, 0x82, 0x80, 0x34, 0x3d, 0xf4, 0x25, 0x14, 0xb8, 0x1c, 0x0e, 0x9e, 0x15, + 0xe0, 0x0f, 0x63, 0xf0, 0x07, 0x57, 0x07, 0xe7, 0x72, 0xcd, 0x36, 0xce, 0x73, 0x40, 0xd3, 0x43, + 0xdb, 0xb0, 0x2e, 0x85, 0x47, 0xcc, 0x65, 0x24, 0xae, 0x10, 0x84, 0xc9, 0xe2, 0x16, 0xf4, 0x18, + 0x8a, 0x13, 0x37, 0x24, 0x94, 0x39, 0x89, 0x04, 0xf5, 0x3f, 0x92, 0xb0, 0x21, 0x71, 0x2d, 0x29, + 0xa4, 0x04, 0xb9, 0xc7, 0x23, 0x77, 0x18, 0xe9, 0x5a, 0x45, 0xa9, 0x15, 0xb0, 0xdc, 0x20, 0x04, + 0x2a, 0x75, 0xc7, 0x44, 0xcf, 0x09, 0x5d, 0x62, 0x8d, 0x3e, 0x01, 0xf5, 0xd8, 0xa7, 0x9e, 0x9e, + 0xaf, 0x28, 0xb5, 0xe2, 0x65, 0x37, 0x94, 0xa3, 0x8b, 0x3f, 0x1d, 0x9f, 0x7a, 0x58, 0x24, 0xa2, + 0x06, 0x94, 0x22, 0xe6, 0x86, 0xcc, 0x61, 0xfe, 0x98, 0x38, 0x53, 0xea, 0x3f, 0x71, 0xa8, 0x4b, + 0x03, 0xbd, 0x50, 0x51, 0x6a, 0x79, 0x7c, 0x5d, 0xf8, 0x6c, 0x7f, 0x4c, 0xfa, 0xd4, 0x7f, 0xd2, + 0x75, 0x69, 0x80, 0xee, 0x02, 0x22, 0xd4, 0x3b, 0x1f, 0xbe, 0x2a, 0xc2, 0xaf, 0x11, 0xea, 0x2d, + 0x04, 0x1f, 0x00, 0xb8, 0x8c, 0x85, 0xfe, 0xa3, 0x29, 0x23, 0x91, 0xbe, 0x26, 0x26, 0xee, 0xfd, + 0x4b, 0x46, 0xb8, 0x43, 0x9e, 0x1e, 0xb9, 0xa3, 0x69, 0x32, 0xb6, 0x29, 0x00, 0xf4, 0x00, 0x74, + 0x2f, 0x0c, 0x26, 0x13, 0xe2, 0x39, 0x73, 0xab, 0x33, 0x08, 0xa6, 0x94, 0xe9, 0x50, 0x51, 0x6a, + 0x9b, 0xf8, 0x66, 0xec, 0x6f, 0xce, 0xdc, 0x2d, 0xee, 0x45, 0x0f, 0x21, 0x4f, 0x4e, 0x08, 0x65, + 0x91, 0xbe, 0xfe, 0x4a, 0x57, 0x97, 0x77, 0xca, 0xe0, 0x09, 0x38, 0xce, 0x43, 0x1f, 0x42, 0x29, + 0xe1, 0x96, 0x96, 0x98, 0x77, 0x43, 0xf0, 0xa2, 0xd8, 0x27, 0x72, 0x62, 0xce, 0x8f, 0x21, 0x37, + 0xf2, 0xe9, 0x71, 0xa4, 0x6f, 0x2e, 0xa9, 0x7b, 0x91, 0x72, 0xdf, 0xa7, 0xc7, 0x58, 0x66, 0xa1, + 0x3a, 0xbc, 0x91, 0x10, 0x0a, 0x43, 0xcc, 0x57, 0x14, 0x7c, 0xd7, 0x63, 0x17, 0x4f, 0x88, 0xe9, + 0x76, 0x21, 0xcf, 0xe7, 0x76, 0x1a, 0xe9, 0xd7, 0xc4, 0x53, 0x71, 0xfb, 0x12, 0x3e, 0x11, 0x1b, + 0x37, 0x39, 0xce, 0xdc, 0xfa, 0x43, 0x81, 0x9c, 0x28, 0x01, 0xdd, 0x86, 0xe2, 0xb9, 0x23, 0x56, + 0xc4, 0x11, 0x6f, 0xb0, 0xf4, 0xf9, 0x26, 0x23, 0x99, 0x4d, 0x8d, 0xe4, 0xe2, 0x99, 0xaf, 0xbc, + 0xce, 0x33, 0x57, 0x97, 0x9d, 0xf9, 0xd6, 0xcb, 0x2c, 0xa8, 0xbc, 0x3f, 0xff, 0xe3, 0x07, 0x69, + 0xb1, 0xd7, 0xea, 0xeb, 0xec, 0x75, 0x6e, 0xe9, 0xfd, 0x9a, 0xbd, 0x58, 0xf9, 0xd4, 0x8b, 0x55, + 0xfd, 0x41, 0x81, 0xd5, 0xe4, 0xbd, 0x41, 0x6f, 0xc2, 0x0d, 0xeb, 0xb0, 0xd9, 0x75, 0x3a, 0x66, + 0xb7, 0xed, 0xf4, 0xbb, 0xd6, 0xa1, 0xd1, 0x32, 0xf7, 0x4c, 0xa3, 0xad, 0x65, 0xd0, 0x4d, 0x40, + 0x73, 0x97, 0xd9, 0xb5, 0x0d, 0xdc, 0x6d, 0xee, 0x6b, 0x0a, 0x2a, 0x81, 0x36, 0xb7, 0x5b, 0x06, + 0x3e, 0x32, 0xb0, 0x96, 0x5d, 0xb4, 0xb6, 0xf6, 0x4d, 0xa3, 0x6b, 0x6b, 0x2b, 0x8b, 0x18, 0x87, + 0xb8, 0xd7, 0xee, 0xb7, 0x0c, 0xac, 0xa9, 0x8b, 0xf6, 0x56, 0xaf, 0x6b, 0xf5, 0x0f, 0x0c, 0xac, + 0xe5, 0xaa, 0xbf, 0x2b, 0x90, 0x97, 0x77, 0x00, 0xe9, 0x50, 0x18, 0x93, 0x28, 0x72, 0x87, 0xc9, + 0x20, 0x27, 0x5b, 0xd4, 0x02, 0x75, 0x10, 0x78, 0xb2, 0xf3, 0xc5, 0x7b, 0x8d, 0x57, 0xb9, 0x51, + 0xf1, 0xbf, 0x56, 0xe0, 0x11, 0x2c, 0x92, 0xab, 0x5d, 0x80, 0xb9, 0x0d, 0xdd, 0x80, 0xeb, 0x96, + 0xdd, 0xb4, 0xfb, 0x96, 0xd3, 0xea, 0xb5, 0x0d, 0xde, 0x08, 0xc3, 0xd6, 0x32, 0x08, 0x41, 0x31, + 0x6d, 0xee, 0x75, 0x34, 0xe5, 0x7c, 0xa8, 0x81, 0x71, 0x0f, 0x6b, 0xd9, 0xcf, 0xd5, 0x55, 0x45, + 0xcb, 0xde, 0xf9, 0x51, 0x81, 0x35, 0xde, 0xdb, 0x3d, 0xf1, 0xdb, 0x90, 0x34, 0x77, 0x6f, 0xbf, + 0xf9, 0xa9, 0xe5, 0xb4, 0x7b, 0x4e, 0xb7, 0x67, 0x3b, 0x7d, 0xcb, 0xd0, 0x32, 0xa8, 0x02, 0x6f, + 0xa5, 0x5c, 0x36, 0x6e, 0xb6, 0x8c, 0x78, 0x7d, 0xd0, 0xb4, 0x3a, 0xda, 0x4b, 0x05, 0xdd, 0x81, + 0x77, 0x53, 0x11, 0xad, 0x5e, 0xd7, 0x36, 0xbe, 0xb0, 0x9d, 0xcf, 0x9a, 0x96, 0x63, 0x5a, 0x0e, + 0x36, 0x0e, 0x7a, 0xb6, 0x21, 0x63, 0xbf, 0xcb, 0xa2, 0xf7, 0xe0, 0x9d, 0x0b, 0x62, 0xcf, 0xc7, + 0xa9, 0xbb, 0xbf, 0x28, 0xcf, 0x4e, 0xcb, 0xca, 0xf3, 0xd3, 0xb2, 0xf2, 0xf7, 0x69, 0x59, 0xf9, + 0xfe, 0xac, 0x9c, 0x79, 0x7e, 0x56, 0xce, 0xfc, 0x79, 0x56, 0xce, 0xc0, 0xb6, 0x1f, 0x2c, 0x6d, + 0xe4, 0xae, 0xfc, 0x18, 0x3d, 0xe4, 0xc6, 0x43, 0xe5, 0xab, 0xd6, 0x95, 0xaf, 0x91, 0xfc, 0xe0, + 0x1d, 0x12, 0x3a, 0xfb, 0xfa, 0xfe, 0x39, 0x7b, 0xab, 0x37, 0x21, 0xd4, 0x9e, 0x41, 0x08, 0x70, + 0x79, 0x97, 0xeb, 0x47, 0x3b, 0x8f, 0xf2, 0x22, 0xe3, 0xfe, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, + 0xfd, 0xbe, 0x84, 0xc3, 0xc3, 0x0b, 0x00, 0x00, } func (m *TracesData) Marshal() (dAtA []byte, err error) { diff --git a/pdata/pmetric/generated_metric.go b/pdata/pmetric/generated_metric.go index 839628520df..ecf2dba29ef 100644 --- a/pdata/pmetric/generated_metric.go +++ b/pdata/pmetric/generated_metric.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/pcommon" ) // Metric represents one metric as a collection of datapoints. @@ -79,6 +80,11 @@ func (ms Metric) SetUnit(v string) { ms.orig.Unit = v } +// Metadata returns the Metadata associated with this Metric. +func (ms Metric) Metadata() pcommon.Map { + return pcommon.Map(internal.NewMap(&ms.orig.Metadata, ms.state)) +} + // Type returns the type of the data for this Metric. // Calling this function on zero-initialized Metric will cause a panic. func (ms Metric) Type() MetricType { @@ -233,6 +239,7 @@ func (ms Metric) CopyTo(dest Metric) { dest.SetName(ms.Name()) dest.SetDescription(ms.Description()) dest.SetUnit(ms.Unit()) + ms.Metadata().CopyTo(dest.Metadata()) switch ms.Type() { case MetricTypeGauge: ms.Gauge().CopyTo(dest.SetEmptyGauge()) diff --git a/pdata/pmetric/generated_metric_test.go b/pdata/pmetric/generated_metric_test.go index 920891b6096..e761f14a321 100644 --- a/pdata/pmetric/generated_metric_test.go +++ b/pdata/pmetric/generated_metric_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/pcommon" ) func TestMetric_MoveTo(t *testing.T) { @@ -65,6 +66,13 @@ func TestMetric_Unit(t *testing.T) { assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetUnit("1") }) } +func TestMetric_Metadata(t *testing.T) { + ms := NewMetric() + assert.Equal(t, pcommon.NewMap(), ms.Metadata()) + internal.FillTestMap(internal.Map(ms.Metadata())) + assert.Equal(t, pcommon.Map(internal.GenerateTestMap()), ms.Metadata()) +} + func TestMetric_Type(t *testing.T) { tv := NewMetric() assert.Equal(t, MetricTypeEmpty, tv.Type()) @@ -175,6 +183,7 @@ func fillTestMetric(tv Metric) { tv.orig.Name = "test_name" tv.orig.Description = "test_description" tv.orig.Unit = "1" + internal.FillTestMap(internal.NewMap(&tv.orig.Metadata, tv.state)) tv.orig.Data = &otlpmetrics.Metric_Sum{Sum: &otlpmetrics.Sum{}} fillTestSum(newSum(tv.orig.GetSum(), tv.state)) } diff --git a/pdata/pmetric/json.go b/pdata/pmetric/json.go index c8b76b0e6ec..394b8af7c65 100644 --- a/pdata/pmetric/json.go +++ b/pdata/pmetric/json.go @@ -106,6 +106,11 @@ func (ms Metric) unmarshalJsoniter(iter *jsoniter.Iterator) { ms.orig.Description = iter.ReadString() case "unit": ms.orig.Unit = iter.ReadString() + case "metadata": + iter.ReadArrayCB(func(iter *jsoniter.Iterator) bool { + ms.orig.Metadata = append(ms.orig.Metadata, json.ReadAttribute(iter)) + return true + }) case "sum": ms.SetEmptySum().unmarshalJsoniter(iter) case "gauge": diff --git a/pdata/pmetric/json_test.go b/pdata/pmetric/json_test.go index cebc40e8e41..552eee39edf 100644 --- a/pdata/pmetric/json_test.go +++ b/pdata/pmetric/json_test.go @@ -21,11 +21,13 @@ var metricsOTLP = func() Metrics { il := rm.ScopeMetrics().AppendEmpty() il.Scope().SetName("name") il.Scope().SetVersion("version") - il.Metrics().AppendEmpty().SetName("testMetric") + m := il.Metrics().AppendEmpty() + m.SetName("testMetric") + m.Metadata().PutStr("metadatakey", "metadatavalue") return md }() -var metricsJSON = `{"resourceMetrics":[{"resource":{"attributes":[{"key":"host.name","value":{"stringValue":"testHost"}}]},"scopeMetrics":[{"scope":{"name":"name","version":"version"},"metrics":[{"name":"testMetric"}]}]}]}` +var metricsJSON = `{"resourceMetrics":[{"resource":{"attributes":[{"key":"host.name","value":{"stringValue":"testHost"}}]},"scopeMetrics":[{"scope":{"name":"name","version":"version"},"metrics":[{"name":"testMetric","metadata":[{"key":"metadatakey","value":{"stringValue":"metadatavalue"}}]}]}]}]}` func TestMetricsJSON(t *testing.T) { encoder := &JSONMarshaler{} diff --git a/pdata/testdata/Makefile b/pdata/testdata/Makefile new file mode 100644 index 00000000000..ded7a36092d --- /dev/null +++ b/pdata/testdata/Makefile @@ -0,0 +1 @@ +include ../../Makefile.Common diff --git a/internal/testdata/common.go b/pdata/testdata/common.go similarity index 100% rename from internal/testdata/common.go rename to pdata/testdata/common.go diff --git a/pdata/testdata/go.mod b/pdata/testdata/go.mod new file mode 100644 index 00000000000..a92f19a2e54 --- /dev/null +++ b/pdata/testdata/go.mod @@ -0,0 +1,21 @@ +module go.opentelemetry.io/collector/pdata/testdata + +go 1.21 + +require go.opentelemetry.io/collector/pdata v1.7.0 + +require ( + github.com/gogo/protobuf v1.3.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/net v0.23.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect +) + +replace go.opentelemetry.io/collector/pdata => ../ diff --git a/pdata/testdata/go.sum b/pdata/testdata/go.sum new file mode 100644 index 00000000000..54657892220 --- /dev/null +++ b/pdata/testdata/go.sum @@ -0,0 +1,68 @@ +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/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +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/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/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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.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= +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.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +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.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.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-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +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/testdata/log.go b/pdata/testdata/log.go similarity index 100% rename from internal/testdata/log.go rename to pdata/testdata/log.go diff --git a/internal/testdata/metric.go b/pdata/testdata/metric.go similarity index 100% rename from internal/testdata/metric.go rename to pdata/testdata/metric.go diff --git a/internal/testdata/resource.go b/pdata/testdata/resource.go similarity index 100% rename from internal/testdata/resource.go rename to pdata/testdata/resource.go diff --git a/internal/testdata/trace.go b/pdata/testdata/trace.go similarity index 100% rename from internal/testdata/trace.go rename to pdata/testdata/trace.go diff --git a/processor/batchprocessor/batch_processor.go b/processor/batchprocessor/batch_processor.go index 4853eef524a..60c6fa10ef6 100644 --- a/processor/batchprocessor/batch_processor.go +++ b/processor/batchprocessor/batch_processor.go @@ -129,7 +129,9 @@ func newBatchProcessor(set processor.CreateSettings, cfg *Config, batchFunc func metadataLimit: int(cfg.MetadataCardinalityLimit), } if len(bp.metadataKeys) == 0 { - bp.batcher = &singleShardBatcher{batcher: bp.newShard(nil)} + s := bp.newShard(nil) + s.start() + bp.batcher = &singleShardBatcher{batcher: s} } else { bp.batcher = &multiShardBatcher{ batchProcessor: bp, @@ -156,8 +158,6 @@ func (bp *batchProcessor) newShard(md map[string][]string) *shard { exportCtx: exportCtx, batch: bp.batchFunc(), } - b.processor.goroutines.Add(1) - go b.start() return b } @@ -180,6 +180,11 @@ func (bp *batchProcessor) Shutdown(context.Context) error { } func (b *shard) start() { + b.processor.goroutines.Add(1) + go b.startLoop() +} + +func (b *shard) startLoop() { defer b.processor.goroutines.Done() // timerCh ensures we only block when there is a @@ -320,6 +325,8 @@ func (mb *multiShardBatcher) consume(ctx context.Context, data any) error { var loaded bool b, loaded = mb.batchers.LoadOrStore(aset, mb.newShard(md)) if !loaded { + // Start the goroutine only if we added the object to the map, otherwise is already started. + b.(*shard).start() mb.size++ } mb.lock.Unlock() diff --git a/processor/batchprocessor/batch_processor_test.go b/processor/batchprocessor/batch_processor_test.go index a3a618c0f3e..6e8033fb387 100644 --- a/processor/batchprocessor/batch_processor_test.go +++ b/processor/batchprocessor/batch_processor_test.go @@ -20,10 +20,10 @@ import ( "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" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/collector/pdata/testdata" "go.opentelemetry.io/collector/processor/processortest" ) diff --git a/processor/batchprocessor/generated_component_test.go b/processor/batchprocessor/generated_component_test.go new file mode 100644 index 00000000000..656dad9986b --- /dev/null +++ b/processor/batchprocessor/generated_component_test.go @@ -0,0 +1,150 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package batchprocessor + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/consumer/consumertest" + "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/processor" + "go.opentelemetry.io/collector/processor/processortest" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "batch", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +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) + }{ + + { + name: "logs", + createFn: func(ctx context.Context, set processor.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsProcessor(ctx, set, cfg, consumertest.NewNop()) + }, + }, + + { + name: "metrics", + createFn: func(ctx context.Context, set processor.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsProcessor(ctx, set, cfg, consumertest.NewNop()) + }, + }, + + { + name: "traces", + createFn: func(ctx context.Context, set processor.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesProcessor(ctx, set, cfg, consumertest.NewNop()) + }, + }, + } + + 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) { + 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 test.name { + case "logs": + e, ok := c.(processor.Logs) + require.True(t, ok) + logs := generateLifecycleTestLogs() + if !e.Capabilities().MutatesData { + logs.MarkReadOnly() + } + err = e.ConsumeLogs(context.Background(), logs) + case "metrics": + e, ok := c.(processor.Metrics) + require.True(t, ok) + metrics := generateLifecycleTestMetrics() + if !e.Capabilities().MutatesData { + metrics.MarkReadOnly() + } + err = e.ConsumeMetrics(context.Background(), metrics) + case "traces": + e, ok := c.(processor.Traces) + require.True(t, ok) + traces := generateLifecycleTestTraces() + 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) + }) + } +} + +func generateLifecycleTestLogs() plog.Logs { + logs := plog.NewLogs() + rl := logs.ResourceLogs().AppendEmpty() + rl.Resource().Attributes().PutStr("resource", "R1") + l := rl.ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() + l.Body().SetStr("test log message") + l.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return logs +} + +func generateLifecycleTestMetrics() pmetric.Metrics { + metrics := pmetric.NewMetrics() + rm := metrics.ResourceMetrics().AppendEmpty() + rm.Resource().Attributes().PutStr("resource", "R1") + m := rm.ScopeMetrics().AppendEmpty().Metrics().AppendEmpty() + m.SetName("test_metric") + dp := m.SetEmptyGauge().DataPoints().AppendEmpty() + dp.Attributes().PutStr("test_attr", "value_1") + dp.SetIntValue(123) + dp.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return metrics +} + +func generateLifecycleTestTraces() ptrace.Traces { + traces := ptrace.NewTraces() + rs := traces.ResourceSpans().AppendEmpty() + rs.Resource().Attributes().PutStr("resource", "R1") + span := rs.ScopeSpans().AppendEmpty().Spans().AppendEmpty() + span.Attributes().PutStr("test_attr", "value_1") + span.SetName("test_span") + span.SetStartTimestamp(pcommon.NewTimestampFromTime(time.Now().Add(-1 * time.Second))) + span.SetEndTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return traces +} diff --git a/processor/batchprocessor/package_test.go b/processor/batchprocessor/generated_package_test.go similarity index 62% rename from processor/batchprocessor/package_test.go rename to processor/batchprocessor/generated_package_test.go index 58d64e47b57..d8cd79854bc 100644 --- a/processor/batchprocessor/package_test.go +++ b/processor/batchprocessor/generated_package_test.go @@ -1,5 +1,4 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 +// Code generated by mdatagen. DO NOT EDIT. package batchprocessor diff --git a/processor/batchprocessor/go.mod b/processor/batchprocessor/go.mod index 7dd14964033..eeeeba8a4a1 100644 --- a/processor/batchprocessor/go.mod +++ b/processor/batchprocessor/go.mod @@ -4,22 +4,23 @@ 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 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 + github.com/prometheus/client_model v0.6.1 + github.com/prometheus/common v0.53.0 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/collector/pdata/testdata v0.100.0 + go.opentelemetry.io/collector/processor v0.100.0 + go.opentelemetry.io/otel v1.26.0 + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/sdk v1.26.0 + go.opentelemetry.io/otel/sdk/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 @@ -33,23 +34,23 @@ require ( 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/google/uuid 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.1 // 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/procfs v0.12.0 // indirect - golang.org/x/net v0.21.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -65,6 +66,8 @@ replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata + replace go.opentelemetry.io/collector/consumer => ../../consumer retract ( diff --git a/processor/batchprocessor/go.sum b/processor/batchprocessor/go.sum index 06616cda85d..4394e616fe3 100644 --- a/processor/batchprocessor/go.sum +++ b/processor/batchprocessor/go.sum @@ -14,13 +14,11 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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/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= @@ -29,8 +27,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -48,32 +46,32 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.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.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -89,16 +87,16 @@ 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -111,14 +109,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/processor/batchprocessor/internal/metadata/generated_status.go b/processor/batchprocessor/internal/metadata/generated_status.go index b3956d2b0a2..c77d7c0a539 100644 --- a/processor/batchprocessor/internal/metadata/generated_status.go +++ b/processor/batchprocessor/internal/metadata/generated_status.go @@ -3,15 +3,11 @@ 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" + Type = component.MustNewType("batch") ) const ( @@ -19,11 +15,3 @@ const ( 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/internal/metadata/generated_telemetry.go b/processor/batchprocessor/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..9a1991a4795 --- /dev/null +++ b/processor/batchprocessor/internal/metadata/generated_telemetry.go @@ -0,0 +1,18 @@ +// 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" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/processor/batchprocessor") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/processor/batchprocessor") +} diff --git a/processor/batchprocessor/internal/metadata/generated_telemetry_test.go b/processor/batchprocessor/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..22002cbff85 --- /dev/null +++ b/processor/batchprocessor/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/processor/batchprocessor", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/processor/batchprocessor", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/processor/batchprocessor/metadata.yaml b/processor/batchprocessor/metadata.yaml index f535dc6c6c7..d96e0f80d9b 100644 --- a/processor/batchprocessor/metadata.yaml +++ b/processor/batchprocessor/metadata.yaml @@ -5,3 +5,5 @@ status: stability: beta: [traces, metrics, logs] distributions: [core, contrib] + +tests: diff --git a/processor/batchprocessor/metrics.go b/processor/batchprocessor/metrics.go index d10727813eb..95fe7f28e16 100644 --- a/processor/batchprocessor/metrics.go +++ b/processor/batchprocessor/metrics.go @@ -8,18 +8,17 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" + noopmetric "go.opentelemetry.io/otel/metric/noop" "go.uber.org/multierr" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configtelemetry" "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" "go.opentelemetry.io/collector/processor" + "go.opentelemetry.io/collector/processor/batchprocessor/internal/metadata" "go.opentelemetry.io/collector/processor/processorhelper" ) -const ( - scopeName = "go.opentelemetry.io/collector/processor/batchprocessor" -) - type trigger int const ( @@ -50,16 +49,25 @@ func newBatchProcessorTelemetry(set processor.CreateSettings, currentMetadataCar detailed: set.MetricsLevel == configtelemetry.LevelDetailed, } - if err := bpt.createOtelMetrics(set.MeterProvider, currentMetadataCardinality); err != nil { + if err := bpt.createOtelMetrics(set.TelemetrySettings, currentMetadataCardinality); err != nil { return nil, err } return bpt, nil } -func (bpt *batchProcessorTelemetry) createOtelMetrics(mp metric.MeterProvider, currentMetadataCardinality func() int) error { - var errors, err error - meter := mp.Meter(scopeName) +func (bpt *batchProcessorTelemetry) createOtelMetrics(set component.TelemetrySettings, currentMetadataCardinality func() int) error { + var ( + errors, err error + meter metric.Meter + ) + + // BatchProcessor are emitted starting from Normal level only. + if bpt.level >= configtelemetry.LevelNormal { + meter = metadata.Meter(set) + } else { + meter = noopmetric.Meter{} + } bpt.batchSizeTriggerSend, err = meter.Int64Counter( processorhelper.BuildCustomMetricName(typeStr, "batch_size_trigger_send"), diff --git a/processor/batchprocessor/splitlogs_test.go b/processor/batchprocessor/splitlogs_test.go index d112cd1069e..74ac51c8521 100644 --- a/processor/batchprocessor/splitlogs_test.go +++ b/processor/batchprocessor/splitlogs_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/assert" - "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/testdata" ) func TestSplitLogs_noop(t *testing.T) { diff --git a/processor/batchprocessor/splitmetrics_test.go b/processor/batchprocessor/splitmetrics_test.go index e81cc73b5db..fd40ec8f9fb 100644 --- a/processor/batchprocessor/splitmetrics_test.go +++ b/processor/batchprocessor/splitmetrics_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/assert" - "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/testdata" ) func TestSplitMetrics_noop(t *testing.T) { diff --git a/processor/batchprocessor/splittraces_test.go b/processor/batchprocessor/splittraces_test.go index 5316aab66a2..62d8b1e0e4d 100644 --- a/processor/batchprocessor/splittraces_test.go +++ b/processor/batchprocessor/splittraces_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/assert" - "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/collector/pdata/testdata" ) func TestSplitTraces_noop(t *testing.T) { diff --git a/processor/go.mod b/processor/go.mod index ebb68ddd8da..e569ac163d8 100644 --- a/processor/go.mod +++ b/processor/go.mod @@ -3,15 +3,17 @@ module go.opentelemetry.io/collector/processor 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/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 + github.com/google/uuid v1.6.0 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/collector/pdata/testdata v0.100.0 + go.opentelemetry.io/otel v1.26.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 @@ -25,30 +27,29 @@ require ( 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/knadh/koanf/v2 v2.1.1 // 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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 + go.opentelemetry.io/collector/confmap v0.100.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -64,4 +65,6 @@ replace go.opentelemetry.io/collector/featuregate => ../featuregate replace go.opentelemetry.io/collector/pdata => ../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../pdata/testdata + replace go.opentelemetry.io/collector/config/configtelemetry => ../config/configtelemetry diff --git a/processor/go.sum b/processor/go.sum index 06616cda85d..4394e616fe3 100644 --- a/processor/go.sum +++ b/processor/go.sum @@ -14,13 +14,11 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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/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= @@ -29,8 +27,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -48,32 +46,32 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.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.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -89,16 +87,16 @@ 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -111,14 +109,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/processor/memorylimiterprocessor/generated_component_test.go b/processor/memorylimiterprocessor/generated_component_test.go new file mode 100644 index 00000000000..7144d4a3901 --- /dev/null +++ b/processor/memorylimiterprocessor/generated_component_test.go @@ -0,0 +1,144 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package memorylimiterprocessor + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/consumer/consumertest" + "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/processor" + "go.opentelemetry.io/collector/processor/processortest" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "memory_limiter", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +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) + }{ + + { + name: "logs", + createFn: func(ctx context.Context, set processor.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsProcessor(ctx, set, cfg, consumertest.NewNop()) + }, + }, + + { + name: "metrics", + createFn: func(ctx context.Context, set processor.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsProcessor(ctx, set, cfg, consumertest.NewNop()) + }, + }, + + { + name: "traces", + createFn: func(ctx context.Context, set processor.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesProcessor(ctx, set, cfg, consumertest.NewNop()) + }, + }, + } + + 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+"-lifecycle", func(t *testing.T) { + 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 test.name { + case "logs": + e, ok := c.(processor.Logs) + require.True(t, ok) + logs := generateLifecycleTestLogs() + if !e.Capabilities().MutatesData { + logs.MarkReadOnly() + } + err = e.ConsumeLogs(context.Background(), logs) + case "metrics": + e, ok := c.(processor.Metrics) + require.True(t, ok) + metrics := generateLifecycleTestMetrics() + if !e.Capabilities().MutatesData { + metrics.MarkReadOnly() + } + err = e.ConsumeMetrics(context.Background(), metrics) + case "traces": + e, ok := c.(processor.Traces) + require.True(t, ok) + traces := generateLifecycleTestTraces() + 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) + }) + } +} + +func generateLifecycleTestLogs() plog.Logs { + logs := plog.NewLogs() + rl := logs.ResourceLogs().AppendEmpty() + rl.Resource().Attributes().PutStr("resource", "R1") + l := rl.ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() + l.Body().SetStr("test log message") + l.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return logs +} + +func generateLifecycleTestMetrics() pmetric.Metrics { + metrics := pmetric.NewMetrics() + rm := metrics.ResourceMetrics().AppendEmpty() + rm.Resource().Attributes().PutStr("resource", "R1") + m := rm.ScopeMetrics().AppendEmpty().Metrics().AppendEmpty() + m.SetName("test_metric") + dp := m.SetEmptyGauge().DataPoints().AppendEmpty() + dp.Attributes().PutStr("test_attr", "value_1") + dp.SetIntValue(123) + dp.SetTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return metrics +} + +func generateLifecycleTestTraces() ptrace.Traces { + traces := ptrace.NewTraces() + rs := traces.ResourceSpans().AppendEmpty() + rs.Resource().Attributes().PutStr("resource", "R1") + span := rs.ScopeSpans().AppendEmpty().Spans().AppendEmpty() + span.Attributes().PutStr("test_attr", "value_1") + span.SetName("test_span") + span.SetStartTimestamp(pcommon.NewTimestampFromTime(time.Now().Add(-1 * time.Second))) + span.SetEndTimestamp(pcommon.NewTimestampFromTime(time.Now())) + return traces +} diff --git a/processor/memorylimiterprocessor/package_test.go b/processor/memorylimiterprocessor/generated_package_test.go similarity index 63% rename from processor/memorylimiterprocessor/package_test.go rename to processor/memorylimiterprocessor/generated_package_test.go index 77bee80493d..969659943d8 100644 --- a/processor/memorylimiterprocessor/package_test.go +++ b/processor/memorylimiterprocessor/generated_package_test.go @@ -1,5 +1,4 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 +// Code generated by mdatagen. DO NOT EDIT. package memorylimiterprocessor diff --git a/processor/memorylimiterprocessor/go.mod b/processor/memorylimiterprocessor/go.mod index a82f08150c3..87ab2ea6753 100644 --- a/processor/memorylimiterprocessor/go.mod +++ b/processor/memorylimiterprocessor/go.mod @@ -3,14 +3,15 @@ module go.opentelemetry.io/collector/processor/memorylimiterprocessor 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/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 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/collector/processor v0.100.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.0 go.uber.org/goleak v1.3.0 ) @@ -23,11 +24,11 @@ require ( 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/google/uuid 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.1 // 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 @@ -36,27 +37,27 @@ require ( 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/shirou/gopsutil/v3 v3.24.1 // indirect + github.com/shirou/gopsutil/v3 v3.24.3 // 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/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 + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/pdata/testdata v0.100.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.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/net v0.24.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -72,6 +73,8 @@ replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata + replace go.opentelemetry.io/collector/consumer => ../../consumer retract ( diff --git a/processor/memorylimiterprocessor/go.sum b/processor/memorylimiterprocessor/go.sum index 7a84d36f2e3..a2c03ed5c2f 100644 --- a/processor/memorylimiterprocessor/go.sum +++ b/processor/memorylimiterprocessor/go.sum @@ -16,15 +16,13 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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/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= @@ -33,8 +31,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -56,46 +54,48 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF 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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE= +github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg= 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/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 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= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -111,8 +111,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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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= @@ -123,9 +123,9 @@ 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.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/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -138,14 +138,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/processor/memorylimiterprocessor/internal/metadata/generated_status.go b/processor/memorylimiterprocessor/internal/metadata/generated_status.go index 0b2058d89df..bd77272f645 100644 --- a/processor/memorylimiterprocessor/internal/metadata/generated_status.go +++ b/processor/memorylimiterprocessor/internal/metadata/generated_status.go @@ -3,15 +3,11 @@ 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" + Type = component.MustNewType("memory_limiter") ) const ( @@ -19,11 +15,3 @@ const ( 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/internal/metadata/generated_telemetry.go b/processor/memorylimiterprocessor/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..9ae63c09a87 --- /dev/null +++ b/processor/memorylimiterprocessor/internal/metadata/generated_telemetry.go @@ -0,0 +1,18 @@ +// 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" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/processor/memorylimiterprocessor") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/processor/memorylimiterprocessor") +} diff --git a/processor/memorylimiterprocessor/internal/metadata/generated_telemetry_test.go b/processor/memorylimiterprocessor/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..21c22f3a34c --- /dev/null +++ b/processor/memorylimiterprocessor/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/processor/memorylimiterprocessor", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/processor/memorylimiterprocessor", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/processor/memorylimiterprocessor/internal/mock_exporter.go b/processor/memorylimiterprocessor/internal/mock_exporter.go index 1a55c9299e9..fee7503dd26 100644 --- a/processor/memorylimiterprocessor/internal/mock_exporter.go +++ b/processor/memorylimiterprocessor/internal/mock_exporter.go @@ -8,14 +8,15 @@ import ( "sync/atomic" "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/pdata/plog" ) type MockExporter struct { - destAvailable int64 - acceptedLogCount int64 - deliveredLogCount int64 - Logs []plog.Logs + destAvailable atomic.Bool + acceptedLogCount atomic.Int64 + deliveredLogCount atomic.Int64 + Logs consumertest.LogsSink } var _ consumer.Logs = (*MockExporter)(nil) @@ -24,15 +25,15 @@ func (e *MockExporter) Capabilities() consumer.Capabilities { return consumer.Capabilities{} } -func (e *MockExporter) ConsumeLogs(_ context.Context, ld plog.Logs) error { - atomic.AddInt64(&e.acceptedLogCount, int64(ld.LogRecordCount())) +func (e *MockExporter) ConsumeLogs(ctx context.Context, ld plog.Logs) error { + e.acceptedLogCount.Add(int64(ld.LogRecordCount())) - if atomic.LoadInt64(&e.destAvailable) == 1 { + if e.destAvailable.Load() { // Destination is available, immediately deliver. - atomic.AddInt64(&e.deliveredLogCount, int64(ld.LogRecordCount())) + e.deliveredLogCount.Add(int64(ld.LogRecordCount())) } else { // Destination is not available. Queue the logs in the exporter. - e.Logs = append(e.Logs, ld) + return e.Logs.ConsumeLogs(ctx, ld) } return nil } @@ -40,28 +41,32 @@ func (e *MockExporter) ConsumeLogs(_ context.Context, ld plog.Logs) error { func (e *MockExporter) SetDestAvailable(available bool) { if available { // Pretend we delivered all queued accepted logs. - atomic.AddInt64(&e.deliveredLogCount, atomic.LoadInt64(&e.acceptedLogCount)) + e.deliveredLogCount.Add(int64(e.Logs.LogRecordCount())) // Get rid of the delivered logs so that memory can be collected. - e.Logs = nil + e.Logs.Reset() // Now mark destination available so that subsequent ConsumeLogs // don't queue the logs anymore. - atomic.StoreInt64(&e.destAvailable, 1) - + e.destAvailable.Store(true) } else { - atomic.StoreInt64(&e.destAvailable, 0) + e.destAvailable.Store(false) } } func (e *MockExporter) AcceptedLogCount() int { - return int(atomic.LoadInt64(&e.acceptedLogCount)) + return int(e.acceptedLogCount.Load()) } func (e *MockExporter) DeliveredLogCount() int { - return int(atomic.LoadInt64(&e.deliveredLogCount)) + return int(e.deliveredLogCount.Load()) } func NewMockExporter() *MockExporter { - return &MockExporter{} + return &MockExporter{ + destAvailable: atomic.Bool{}, + acceptedLogCount: atomic.Int64{}, + deliveredLogCount: atomic.Int64{}, + Logs: consumertest.LogsSink{}, + } } diff --git a/processor/memorylimiterprocessor/memorylimiter_test.go b/processor/memorylimiterprocessor/memorylimiter_test.go index 626bf877d7c..10bc8d7911c 100644 --- a/processor/memorylimiterprocessor/memorylimiter_test.go +++ b/processor/memorylimiterprocessor/memorylimiter_test.go @@ -99,8 +99,10 @@ func TestNoDataLoss(t *testing.T) { // And eventually the exporter must confirm that it delivered exact number of produced logs. require.Eventually(t, func() bool { - return receiver.ProduceCount == exporter.DeliveredLogCount() - }, 5*time.Second, 1*time.Millisecond) + d := exporter.DeliveredLogCount() + t.Logf("received: %d, expected: %d\n", d, receiver.ProduceCount) + return receiver.ProduceCount == d + }, 5*time.Second, 100*time.Millisecond) // Double check that the number of logs accepted by exporter matches the number of produced by receiver. assert.Equal(t, receiver.ProduceCount, exporter.AcceptedLogCount()) diff --git a/processor/memorylimiterprocessor/metadata.yaml b/processor/memorylimiterprocessor/metadata.yaml index bc9e1829149..92f9d2f821b 100644 --- a/processor/memorylimiterprocessor/metadata.yaml +++ b/processor/memorylimiterprocessor/metadata.yaml @@ -5,3 +5,11 @@ status: stability: beta: [traces, metrics, logs] distributions: [core, contrib] + +tests: + config: + check_interval: 5s + limit_mib: 400 + spike_limit_mib: 50 + # TODO: https://github.com/open-telemetry/opentelemetry-collector/issues/9687 + skip_shutdown: true diff --git a/processor/processorhelper/obsreport.go b/processor/processorhelper/obsreport.go index 9d1188f1408..17b20704f0d 100644 --- a/processor/processorhelper/obsreport.go +++ b/processor/processorhelper/obsreport.go @@ -19,21 +19,21 @@ import ( ) var ( - processorScope = obsmetrics.Scope + obsmetrics.NameSep + obsmetrics.ProcessorKey + processorScope = obsmetrics.Scope + obsmetrics.SpanNameSep + obsmetrics.ProcessorKey ) // BuildCustomMetricName 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. func BuildCustomMetricName(configType, metric string) string { - componentPrefix := obsmetrics.ProcessorPrefix - if !strings.HasSuffix(componentPrefix, obsmetrics.NameSep) { - componentPrefix += obsmetrics.NameSep + componentPrefix := obsmetrics.ProcessorMetricPrefix + if !strings.HasSuffix(componentPrefix, obsmetrics.MetricNameSep) { + componentPrefix += obsmetrics.MetricNameSep } if configType == "" { return componentPrefix } - return componentPrefix + configType + obsmetrics.NameSep + metric + return componentPrefix + configType + obsmetrics.MetricNameSep + metric } // ObsReport is a helper to add observability to a processor. @@ -87,63 +87,63 @@ func (or *ObsReport) createOtelMetrics(cfg ObsReportSettings) error { var errors, err error or.acceptedSpansCounter, err = meter.Int64Counter( - obsmetrics.ProcessorPrefix+obsmetrics.AcceptedSpansKey, + obsmetrics.ProcessorMetricPrefix+obsmetrics.AcceptedSpansKey, metric.WithDescription("Number of spans successfully pushed into the next component in the pipeline."), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) or.refusedSpansCounter, err = meter.Int64Counter( - obsmetrics.ProcessorPrefix+obsmetrics.RefusedSpansKey, + obsmetrics.ProcessorMetricPrefix+obsmetrics.RefusedSpansKey, metric.WithDescription("Number of spans that were rejected by the next component in the pipeline."), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) or.droppedSpansCounter, err = meter.Int64Counter( - obsmetrics.ProcessorPrefix+obsmetrics.DroppedSpansKey, + obsmetrics.ProcessorMetricPrefix+obsmetrics.DroppedSpansKey, metric.WithDescription("Number of spans that were dropped."), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) or.acceptedMetricPointsCounter, err = meter.Int64Counter( - obsmetrics.ProcessorPrefix+obsmetrics.AcceptedMetricPointsKey, + obsmetrics.ProcessorMetricPrefix+obsmetrics.AcceptedMetricPointsKey, metric.WithDescription("Number of metric points successfully pushed into the next component in the pipeline."), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) or.refusedMetricPointsCounter, err = meter.Int64Counter( - obsmetrics.ProcessorPrefix+obsmetrics.RefusedMetricPointsKey, + obsmetrics.ProcessorMetricPrefix+obsmetrics.RefusedMetricPointsKey, metric.WithDescription("Number of metric points that were rejected by the next component in the pipeline."), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) or.droppedMetricPointsCounter, err = meter.Int64Counter( - obsmetrics.ProcessorPrefix+obsmetrics.DroppedMetricPointsKey, + obsmetrics.ProcessorMetricPrefix+obsmetrics.DroppedMetricPointsKey, metric.WithDescription("Number of metric points that were dropped."), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) or.acceptedLogRecordsCounter, err = meter.Int64Counter( - obsmetrics.ProcessorPrefix+obsmetrics.AcceptedLogRecordsKey, + obsmetrics.ProcessorMetricPrefix+obsmetrics.AcceptedLogRecordsKey, metric.WithDescription("Number of log records successfully pushed into the next component in the pipeline."), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) or.refusedLogRecordsCounter, err = meter.Int64Counter( - obsmetrics.ProcessorPrefix+obsmetrics.RefusedLogRecordsKey, + obsmetrics.ProcessorMetricPrefix+obsmetrics.RefusedLogRecordsKey, metric.WithDescription("Number of log records that were rejected by the next component in the pipeline."), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) or.droppedLogRecordsCounter, err = meter.Int64Counter( - obsmetrics.ProcessorPrefix+obsmetrics.DroppedLogRecordsKey, + obsmetrics.ProcessorMetricPrefix+obsmetrics.DroppedLogRecordsKey, metric.WithDescription("Number of log records that were dropped."), metric.WithUnit("1"), ) diff --git a/processor/processorhelper/obsreport_test.go b/processor/processorhelper/obsreport_test.go index 2cd4500e299..d80c1c180f6 100644 --- a/processor/processorhelper/obsreport_test.go +++ b/processor/processorhelper/obsreport_test.go @@ -63,11 +63,11 @@ func TestBuildProcessorCustomMetricName(t *testing.T) { }{ { name: "firstMeasure", - want: "processor/test_type/firstMeasure", + want: "processor_test_type_firstMeasure", }, { name: "secondMeasure", - want: "processor/test_type/secondMeasure", + want: "processor_test_type_secondMeasure", }, } for _, tt := range tests { diff --git a/processor/processortest/nop_processor.go b/processor/processortest/nop_processor.go index 0651bc5b6ba..6ac5eb1bbbd 100644 --- a/processor/processortest/nop_processor.go +++ b/processor/processortest/nop_processor.go @@ -6,6 +6,8 @@ package processortest // import "go.opentelemetry.io/collector/processor/process import ( "context" + "github.com/google/uuid" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/consumer" @@ -18,7 +20,7 @@ var nopType = component.MustNewType("nop") // NewNopCreateSettings returns a new nop settings for Create*Processor functions. func NewNopCreateSettings() processor.CreateSettings { return processor.CreateSettings{ - ID: component.NewID(nopType), + ID: component.NewIDWithName(nopType, uuid.NewString()), TelemetrySettings: componenttest.NewNopTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo(), } diff --git a/processor/processortest/shutdown_verifier.go b/processor/processortest/shutdown_verifier.go index e0c3becac24..1048fe7b712 100644 --- a/processor/processortest/shutdown_verifier.go +++ b/processor/processortest/shutdown_verifier.go @@ -14,7 +14,7 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/consumer/consumertest" - "go.opentelemetry.io/collector/internal/testdata" + "go.opentelemetry.io/collector/pdata/testdata" "go.opentelemetry.io/collector/processor" ) diff --git a/receiver/go.mod b/receiver/go.mod index 468ae1f821d..600c47a82ef 100644 --- a/receiver/go.mod +++ b/receiver/go.mod @@ -3,16 +3,17 @@ module go.opentelemetry.io/collector/receiver 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/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 + github.com/google/uuid v1.6.0 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/otel v1.26.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/sdk v1.26.0 + go.opentelemetry.io/otel/trace v1.26.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 @@ -26,29 +27,28 @@ require ( 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/knadh/koanf/v2 v2.1.1 // 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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 + go.opentelemetry.io/collector/confmap v0.100.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -64,6 +64,8 @@ replace go.opentelemetry.io/collector/featuregate => ../featuregate replace go.opentelemetry.io/collector/pdata => ../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../pdata/testdata + retract v0.76.0 // Depends on retracted pdata v1.0.0-rc10 module replace go.opentelemetry.io/collector/config/configtelemetry => ../config/configtelemetry diff --git a/receiver/go.sum b/receiver/go.sum index 06616cda85d..4394e616fe3 100644 --- a/receiver/go.sum +++ b/receiver/go.sum @@ -14,13 +14,11 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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/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= @@ -29,8 +27,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -48,32 +46,32 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.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.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= 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= @@ -89,16 +87,16 @@ 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -111,14 +109,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-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= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/receiver/nopreceiver/Makefile b/receiver/nopreceiver/Makefile new file mode 100644 index 00000000000..ded7a36092d --- /dev/null +++ b/receiver/nopreceiver/Makefile @@ -0,0 +1 @@ +include ../../Makefile.Common diff --git a/receiver/nopreceiver/README.md b/receiver/nopreceiver/README.md new file mode 100644 index 00000000000..62a699bb438 --- /dev/null +++ b/receiver/nopreceiver/README.md @@ -0,0 +1,26 @@ +# No-op Receiver + + +| 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%3Areceiver%2Fnop%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Areceiver%2Fnop) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Areceiver%2Fnop%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Areceiver%2Fnop) | + +[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 + + +Serves as a placeholder receiver in a pipeline. This can be useful if you want +to e.g. start a Collector with only extensions enabled. + +## Getting Started + +All that is required to enable the No-op receiver is to include it in the +receiver definitions. It takes no configuration. + +```yaml +receivers: + nop: +``` diff --git a/receiver/nopreceiver/doc.go b/receiver/nopreceiver/doc.go new file mode 100644 index 00000000000..597f9ac3e53 --- /dev/null +++ b/receiver/nopreceiver/doc.go @@ -0,0 +1,7 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +//go:generate mdatagen metadata.yaml + +// Package nopreceiver serves as a placeholder receiver. +package nopreceiver // import "go.opentelemetry.io/collector/receiver/nopreceiver" diff --git a/receiver/nopreceiver/generated_component_test.go b/receiver/nopreceiver/generated_component_test.go new file mode 100644 index 00000000000..14f8840b1e7 --- /dev/null +++ b/receiver/nopreceiver/generated_component_test.go @@ -0,0 +1,84 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package nopreceiver + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/receiver" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "nop", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +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) + }{ + + { + name: "logs", + createFn: func(ctx context.Context, set receiver.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsReceiver(ctx, set, cfg, consumertest.NewNop()) + }, + }, + + { + name: "metrics", + createFn: func(ctx context.Context, set receiver.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsReceiver(ctx, set, cfg, consumertest.NewNop()) + }, + }, + + { + name: "traces", + createFn: func(ctx context.Context, set receiver.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesReceiver(ctx, set, cfg, consumertest.NewNop()) + }, + }, + } + + 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) { + 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())) + }) + } +} diff --git a/receiver/nopreceiver/generated_package_test.go b/receiver/nopreceiver/generated_package_test.go new file mode 100644 index 00000000000..0472e5e1cd3 --- /dev/null +++ b/receiver/nopreceiver/generated_package_test.go @@ -0,0 +1,13 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package nopreceiver + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/receiver/nopreceiver/go.mod b/receiver/nopreceiver/go.mod new file mode 100644 index 00000000000..8f2e843d625 --- /dev/null +++ b/receiver/nopreceiver/go.mod @@ -0,0 +1,73 @@ +module go.opentelemetry.io/collector/receiver/nopreceiver + +go 1.21 + +toolchain go1.21.6 + +require ( + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/receiver v0.100.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.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/google/uuid 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.1.1 // 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.1 // indirect + github.com/prometheus/common v0.53.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/pdata v1.7.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.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/consumer => ../../consumer + +replace go.opentelemetry.io/collector/receiver => ../ + +replace go.opentelemetry.io/collector/pdata => ../../pdata + +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata + +replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry + +replace go.opentelemetry.io/collector => ../.. + +replace go.opentelemetry.io/collector/featuregate => ../../featuregate diff --git a/receiver/nopreceiver/go.sum b/receiver/nopreceiver/go.sum new file mode 100644 index 00000000000..4394e616fe3 --- /dev/null +++ b/receiver/nopreceiver/go.sum @@ -0,0 +1,122 @@ +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/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.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/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= +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.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= +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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +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.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +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.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/receiver/nopreceiver/internal/metadata/generated_status.go b/receiver/nopreceiver/internal/metadata/generated_status.go new file mode 100644 index 00000000000..1901cab9ee6 --- /dev/null +++ b/receiver/nopreceiver/internal/metadata/generated_status.go @@ -0,0 +1,17 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("nop") +) + +const ( + TracesStability = component.StabilityLevelBeta + MetricsStability = component.StabilityLevelBeta + LogsStability = component.StabilityLevelBeta +) diff --git a/receiver/nopreceiver/internal/metadata/generated_telemetry.go b/receiver/nopreceiver/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..9f3838ece6c --- /dev/null +++ b/receiver/nopreceiver/internal/metadata/generated_telemetry.go @@ -0,0 +1,18 @@ +// 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" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/receiver/nopreceiver") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/receiver/nopreceiver") +} diff --git a/receiver/nopreceiver/internal/metadata/generated_telemetry_test.go b/receiver/nopreceiver/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..95dde48b83a --- /dev/null +++ b/receiver/nopreceiver/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/receiver/nopreceiver", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/receiver/nopreceiver", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/receiver/nopreceiver/metadata.yaml b/receiver/nopreceiver/metadata.yaml new file mode 100644 index 00000000000..6a03166e73d --- /dev/null +++ b/receiver/nopreceiver/metadata.yaml @@ -0,0 +1,7 @@ +type: nop + +status: + class: receiver + stability: + beta: [traces, metrics, logs] + distributions: [core, contrib] diff --git a/receiver/nopreceiver/nop_receiver.go b/receiver/nopreceiver/nop_receiver.go new file mode 100644 index 00000000000..2463a89ef65 --- /dev/null +++ b/receiver/nopreceiver/nop_receiver.go @@ -0,0 +1,42 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package nopreceiver // import "go.opentelemetry.io/collector/receiver/nopreceiver" + +import ( + "context" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/receiver" + "go.opentelemetry.io/collector/receiver/nopreceiver/internal/metadata" +) + +// NewFactory returns a receiver.Factory that constructs nop receivers. +func NewFactory() receiver.Factory { + return receiver.NewFactory( + metadata.Type, + func() component.Config { return &struct{}{} }, + receiver.WithTraces(createTraces, metadata.TracesStability), + receiver.WithMetrics(createMetrics, metadata.MetricsStability), + receiver.WithLogs(createLogs, metadata.LogsStability)) +} + +func createTraces(context.Context, receiver.CreateSettings, component.Config, consumer.Traces) (receiver.Traces, error) { + return nopInstance, nil +} + +func createMetrics(context.Context, receiver.CreateSettings, component.Config, consumer.Metrics) (receiver.Metrics, error) { + return nopInstance, nil +} + +func createLogs(context.Context, receiver.CreateSettings, component.Config, consumer.Logs) (receiver.Logs, error) { + return nopInstance, nil +} + +var nopInstance = &nopReceiver{} + +type nopReceiver struct { + component.StartFunc + component.ShutdownFunc +} diff --git a/receiver/nopreceiver/nop_receiver_test.go b/receiver/nopreceiver/nop_receiver_test.go new file mode 100644 index 00000000000..31f78e10756 --- /dev/null +++ b/receiver/nopreceiver/nop_receiver_test.go @@ -0,0 +1,40 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package nopreceiver // import "go.opentelemetry.io/collector/receiver/nopreceiver" + +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/consumertest" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +func TestNewNopFactory(t *testing.T) { + factory := NewFactory() + require.NotNil(t, factory) + assert.Equal(t, component.MustNewType("nop"), factory.Type()) + cfg := factory.CreateDefaultConfig() + assert.Equal(t, &struct{}{}, cfg) + + traces, err := factory.CreateTracesReceiver(context.Background(), receivertest.NewNopCreateSettings(), cfg, consumertest.NewNop()) + require.NoError(t, err) + assert.NoError(t, traces.Start(context.Background(), componenttest.NewNopHost())) + assert.NoError(t, traces.Shutdown(context.Background())) + + metrics, err := factory.CreateMetricsReceiver(context.Background(), receivertest.NewNopCreateSettings(), cfg, consumertest.NewNop()) + require.NoError(t, err) + assert.NoError(t, metrics.Start(context.Background(), componenttest.NewNopHost())) + assert.NoError(t, metrics.Shutdown(context.Background())) + + logs, err := factory.CreateLogsReceiver(context.Background(), receivertest.NewNopCreateSettings(), cfg, consumertest.NewNop()) + require.NoError(t, err) + assert.NoError(t, logs.Start(context.Background(), componenttest.NewNopHost())) + assert.NoError(t, logs.Shutdown(context.Background())) +} diff --git a/receiver/otlpreceiver/README.md b/receiver/otlpreceiver/README.md index 0d6e5ef5a2c..a5572071629 100644 --- a/receiver/otlpreceiver/README.md +++ b/receiver/otlpreceiver/README.md @@ -53,7 +53,7 @@ Several helper files are leveraged to provide additional capabilities automatica The OTLP receiver can receive trace export calls via HTTP/JSON in addition to gRPC. The HTTP/JSON address is the same as gRPC as the protocol is recognized -and processed accordingly. Note the serialization format needs to be [protobuf JSON](https://developers.google.com/protocol-buffers/docs/proto3#json). +and processed accordingly. Note the serialization format needs to be [OTLP JSON](https://opentelemetry.io/docs/specs/otlp/#json-protobuf-encoding). The HTTP/JSON configuration also provides `traces_url_path`, `metrics_url_path`, and `logs_url_path` configuration to allow the URL paths that signal data needs to be sent to be modified per signal type. These default to diff --git a/receiver/otlpreceiver/config_test.go b/receiver/otlpreceiver/config_test.go index 031d8943cc3..9604d507812 100644 --- a/receiver/otlpreceiver/config_test.go +++ b/receiver/otlpreceiver/config_test.go @@ -89,10 +89,10 @@ func TestUnmarshalConfig(t *testing.T) { GRPC: &configgrpc.ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "0.0.0.0:4317", - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, TLSSetting: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CertFile: "test.crt", KeyFile: "test.key", }, @@ -119,7 +119,7 @@ func TestUnmarshalConfig(t *testing.T) { ServerConfig: &confighttp.ServerConfig{ Endpoint: "0.0.0.0:4318", TLSSetting: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CertFile: "test.crt", KeyFile: "test.key", }, @@ -150,7 +150,7 @@ func TestUnmarshalConfigUnix(t *testing.T) { GRPC: &configgrpc.ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "/tmp/grpc_otlp.sock", - Transport: "unix", + Transport: confignet.TransportTypeUnix, }, ReadBufferSize: 512 * 1024, }, diff --git a/receiver/otlpreceiver/factory.go b/receiver/otlpreceiver/factory.go index 3e1df39032b..4b148c40be3 100644 --- a/receiver/otlpreceiver/factory.go +++ b/receiver/otlpreceiver/factory.go @@ -44,7 +44,7 @@ func createDefaultConfig() component.Config { GRPC: &configgrpc.ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: localhostgate.EndpointForPort(grpcPort), - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, // We almost write 0 bytes, so no need to tune WriteBufferSize. ReadBufferSize: 512 * 1024, diff --git a/receiver/otlpreceiver/factory_test.go b/receiver/otlpreceiver/factory_test.go index 21a3a051f27..d844760947f 100644 --- a/receiver/otlpreceiver/factory_test.go +++ b/receiver/otlpreceiver/factory_test.go @@ -55,7 +55,7 @@ func TestCreateTracesReceiver(t *testing.T) { defaultGRPCSettings := &configgrpc.ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, } defaultHTTPSettings := &HTTPConfig{ @@ -91,7 +91,7 @@ func TestCreateTracesReceiver(t *testing.T) { GRPC: &configgrpc.ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "localhost:112233", - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, }, HTTP: defaultHTTPSettings, @@ -149,7 +149,7 @@ func TestCreateMetricReceiver(t *testing.T) { defaultGRPCSettings := &configgrpc.ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, } defaultHTTPSettings := &HTTPConfig{ @@ -185,7 +185,7 @@ func TestCreateMetricReceiver(t *testing.T) { GRPC: &configgrpc.ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "327.0.0.1:1122", - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, }, HTTP: defaultHTTPSettings, @@ -243,7 +243,7 @@ func TestCreateLogReceiver(t *testing.T) { defaultGRPCSettings := &configgrpc.ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, } defaultHTTPSettings := &HTTPConfig{ @@ -279,7 +279,7 @@ func TestCreateLogReceiver(t *testing.T) { GRPC: &configgrpc.ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: "327.0.0.1:1122", - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, }, HTTP: defaultHTTPSettings, diff --git a/receiver/otlpreceiver/generated_component_test.go b/receiver/otlpreceiver/generated_component_test.go new file mode 100644 index 00000000000..e4c99be47ac --- /dev/null +++ b/receiver/otlpreceiver/generated_component_test.go @@ -0,0 +1,84 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package otlpreceiver + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/confmap/confmaptest" + "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/receiver" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +func TestComponentFactoryType(t *testing.T) { + require.Equal(t, "otlp", NewFactory().Type().String()) +} + +func TestComponentConfigStruct(t *testing.T) { + require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig())) +} + +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) + }{ + + { + name: "logs", + createFn: func(ctx context.Context, set receiver.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateLogsReceiver(ctx, set, cfg, consumertest.NewNop()) + }, + }, + + { + name: "metrics", + createFn: func(ctx context.Context, set receiver.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateMetricsReceiver(ctx, set, cfg, consumertest.NewNop()) + }, + }, + + { + name: "traces", + createFn: func(ctx context.Context, set receiver.CreateSettings, cfg component.Config) (component.Component, error) { + return factory.CreateTracesReceiver(ctx, set, cfg, consumertest.NewNop()) + }, + }, + } + + 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) { + 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())) + }) + } +} diff --git a/receiver/otlpreceiver/generated_package_test.go b/receiver/otlpreceiver/generated_package_test.go new file mode 100644 index 00000000000..5e08a4e06fc --- /dev/null +++ b/receiver/otlpreceiver/generated_package_test.go @@ -0,0 +1,13 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package otlpreceiver + +import ( + "testing" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} diff --git a/receiver/otlpreceiver/go.mod b/receiver/otlpreceiver/go.mod index 0ff401c1840..b104a35ba7a 100644 --- a/receiver/otlpreceiver/go.mod +++ b/receiver/otlpreceiver/go.mod @@ -4,30 +4,31 @@ go 1.21 require ( github.com/gogo/protobuf v1.3.2 - github.com/klauspost/compress v1.17.7 - 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/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 + github.com/klauspost/compress v1.17.8 + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/config/configgrpc v0.100.0 + go.opentelemetry.io/collector/config/confighttp v0.100.0 + go.opentelemetry.io/collector/config/confignet v0.100.0 + go.opentelemetry.io/collector/config/configtls v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/collector/pdata/testdata v0.100.0 + go.opentelemetry.io/collector/receiver v0.100.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.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 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda + google.golang.org/grpc v1.63.2 + google.golang.org/protobuf v1.34.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // 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 @@ -35,14 +36,14 @@ require ( 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/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/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.1 // 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 @@ -50,35 +51,38 @@ require ( 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/client_model v0.6.1 // indirect + github.com/prometheus/common v0.53.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.opentelemetry.io/collector/config/configauth v0.100.0 // indirect + go.opentelemetry.io/collector/config/configcompression v1.7.0 // indirect + go.opentelemetry.io/collector/config/configopaque v1.7.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 // indirect + go.opentelemetry.io/collector/config/internal v0.100.0 // indirect + go.opentelemetry.io/collector/extension v0.100.0 // indirect + go.opentelemetry.io/collector/extension/auth v0.100.0 // indirect + go.opentelemetry.io/collector/featuregate v1.7.0 // indirect + go.opentelemetry.io/contrib/config v0.6.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 // indirect + go.opentelemetry.io/otel v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.26.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.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/net v0.24.0 // indirect + golang.org/x/sys v0.19.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/api v0.0.0-20240227224415-6ceb2ff114de // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -114,6 +118,8 @@ replace go.opentelemetry.io/collector/featuregate => ../../featuregate replace go.opentelemetry.io/collector/pdata => ../../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata + replace go.opentelemetry.io/collector/receiver => ../ replace go.opentelemetry.io/collector/consumer => ../../consumer diff --git a/receiver/otlpreceiver/go.sum b/receiver/otlpreceiver/go.sum index 6dc69bb0e99..ee0cdcbf90e 100644 --- a/receiver/otlpreceiver/go.sum +++ b/receiver/otlpreceiver/go.sum @@ -1,20 +1,12 @@ -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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/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= @@ -28,31 +20,29 @@ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsM 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/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.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= 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/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/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/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -72,50 +62,56 @@ 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/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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/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/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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/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.opentelemetry.io/contrib/config v0.6.0 h1:M1SRD1Z15XHPGk61tMLI1up77XT5FdrqQSRrlH0fYuk= +go.opentelemetry.io/contrib/config v0.6.0/go.mod h1:t+/kzmRWLN7J+4F/dD4fFvlYCmCO63WYwy/B00IC++c= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 h1:A3SayB3rNyt+1S6qpI9mHPkeHTZbD7XILEqWnYZb2l0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0/go.mod h1:27iA5uvhuRNmalO+iEUdVn5ZMj2qy10Mm+XRIpRmyuU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 h1:Xs2Ncz0gNihqu9iosIZ5SkBbWo5T8JhhLJFMQL1qmLI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0/go.mod h1:vy+2G/6NvVMpwGX/NyLqcC41fxepnuKHk16E6IZUcJc= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 h1:+hm+I+KigBy3M24/h1p/NHkUx/evbLH0PNcjpMyCHc4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0/go.mod h1:NjC8142mLvvNT6biDpaMjyz78kyEHIwAJlSX0N9P5KI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 h1:HGZWGmCVRCVyAs2GQaiHQPbDHo+ObFWeUEOd+zDnp64= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0/go.mod h1:SaH+v38LSCHddyk7RGlU9uZyQoRrKao6IBnJw6Kbn+c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 h1:1u/AyyOqAWzy+SkPxDpahCNZParHV8Vid1RnI2clyDE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0/go.mod h1:z46paqbJ9l7c9fIPCXTqTGwhQZ5XoTIsfeFYWboizjs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 h1:Waw9Wfpo/IXzOI8bCB7DIk+0JZcqqsyn1JFnAc+iam8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0/go.mod h1:wnJIG4fOqyynOnnQF/eQb4/16VlX2EJAHhHgqIqWfAo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 h1:1wp/gyxsuYtuE/JFxsQRtcCDtMrO2qMvlfXALU5wkzI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0/go.mod h1:gbTHmghkGgqxMomVQQMur1Nba4M0MQ8AYThXDUjsJ38= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 h1:5fnmgteaar1VcAA69huatudPduNFz7guRtCmfZCooZI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0/go.mod h1:lsPccfZiz1cb1AhBPmicWM2E4F1VynFXEvD8SEBS4TM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 h1:0W5o9SzoR15ocYHEQfvfipzcNog1lBxOLfnex91Hk6s= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0/go.mod h1:zVZ8nz+VSggWmnh6tTsJqXQ7rU4xLwRtna1M4x5jq58= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= 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= @@ -131,18 +127,16 @@ 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.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/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -155,20 +149,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.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= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/receiver/otlpreceiver/internal/errors/errors.go b/receiver/otlpreceiver/internal/errors/errors.go index ee9d79e1c7c..0619b7aa8ea 100644 --- a/receiver/otlpreceiver/internal/errors/errors.go +++ b/receiver/otlpreceiver/internal/errors/errors.go @@ -4,6 +4,8 @@ package errors // import "go.opentelemetry.io/collector/receiver/otlpreceiver/internal/errors" import ( + "net/http" + "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -24,3 +26,21 @@ func GetStatusFromError(err error) error { } return s.Err() } + +func GetHTTPStatusCodeFromStatus(s *status.Status) int { + // See https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md#failures + // to see if a code is retryable. + // See https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md#failures-1 + // to see a list of retryable http status codes. + switch s.Code() { + // Retryable + case codes.Canceled, codes.DeadlineExceeded, codes.Aborted, codes.OutOfRange, codes.Unavailable, codes.DataLoss: + return http.StatusServiceUnavailable + // Retryable + case codes.ResourceExhausted: + return http.StatusTooManyRequests + // Not Retryable + default: + return http.StatusInternalServerError + } +} diff --git a/receiver/otlpreceiver/internal/errors/errors_test.go b/receiver/otlpreceiver/internal/errors/errors_test.go index c75b5bf041f..35d8255ffcf 100644 --- a/receiver/otlpreceiver/internal/errors/errors_test.go +++ b/receiver/otlpreceiver/internal/errors/errors_test.go @@ -5,6 +5,7 @@ package errors // import "go.opentelemetry.io/collector/receiver/otlpreceiver/in import ( "fmt" + "net/http" "testing" "github.com/stretchr/testify/assert" @@ -43,3 +44,33 @@ func Test_GetStatusFromError(t *testing.T) { }) } } + +func Test_GetHTTPStatusCodeFromStatus(t *testing.T) { + tests := []struct { + name string + input *status.Status + expected int + }{ + { + name: "Retryable Status", + input: status.New(codes.Unavailable, "test"), + expected: http.StatusServiceUnavailable, + }, + { + name: "Non-retryable Status", + input: status.New(codes.InvalidArgument, "test"), + expected: http.StatusInternalServerError, + }, + { + name: "Specifically 429", + input: status.New(codes.ResourceExhausted, "test"), + expected: http.StatusTooManyRequests, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := GetHTTPStatusCodeFromStatus(tt.input) + assert.Equal(t, tt.expected, result) + }) + } +} diff --git a/receiver/otlpreceiver/internal/logs/otlp_test.go b/receiver/otlpreceiver/internal/logs/otlp_test.go index b2d3178d011..cc87f527681 100644 --- a/receiver/otlpreceiver/internal/logs/otlp_test.go +++ b/receiver/otlpreceiver/internal/logs/otlp_test.go @@ -20,8 +20,8 @@ import ( "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" + "go.opentelemetry.io/collector/pdata/testdata" "go.opentelemetry.io/collector/receiver/receiverhelper" "go.opentelemetry.io/collector/receiver/receivertest" ) @@ -74,7 +74,7 @@ func TestExport_PermanentErrorConsumer(t *testing.T) { func makeLogsServiceClient(t *testing.T, lc consumer.Logs) plogotlp.GRPCClient { addr := otlpReceiverOnGRPCServer(t, lc) - cc, err := grpc.Dial(addr.String(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) + cc, err := grpc.NewClient(addr.String(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) require.NoError(t, err, "Failed to create the TraceServiceClient: %v", err) t.Cleanup(func() { require.NoError(t, cc.Close()) diff --git a/receiver/otlpreceiver/internal/metadata/generated_status.go b/receiver/otlpreceiver/internal/metadata/generated_status.go index aa5483d7b5a..c9cff844fa2 100644 --- a/receiver/otlpreceiver/internal/metadata/generated_status.go +++ b/receiver/otlpreceiver/internal/metadata/generated_status.go @@ -3,15 +3,11 @@ 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" + Type = component.MustNewType("otlp") ) const ( @@ -19,11 +15,3 @@ const ( 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/metadata/generated_telemetry.go b/receiver/otlpreceiver/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..6115bffcf56 --- /dev/null +++ b/receiver/otlpreceiver/internal/metadata/generated_telemetry.go @@ -0,0 +1,18 @@ +// 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" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/receiver/otlpreceiver") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/receiver/otlpreceiver") +} diff --git a/receiver/otlpreceiver/internal/metadata/generated_telemetry_test.go b/receiver/otlpreceiver/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..155056b256a --- /dev/null +++ b/receiver/otlpreceiver/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/receiver/otlpreceiver", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/receiver/otlpreceiver", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/receiver/otlpreceiver/internal/metrics/otlp_test.go b/receiver/otlpreceiver/internal/metrics/otlp_test.go index babc366119f..accd6102e27 100644 --- a/receiver/otlpreceiver/internal/metrics/otlp_test.go +++ b/receiver/otlpreceiver/internal/metrics/otlp_test.go @@ -20,8 +20,8 @@ import ( "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" + "go.opentelemetry.io/collector/pdata/testdata" "go.opentelemetry.io/collector/receiver/receiverhelper" "go.opentelemetry.io/collector/receiver/receivertest" ) @@ -75,7 +75,7 @@ func TestExport_PermanentErrorConsumer(t *testing.T) { func makeMetricsServiceClient(t *testing.T, mc consumer.Metrics) pmetricotlp.GRPCClient { addr := otlpReceiverOnGRPCServer(t, mc) - cc, err := grpc.Dial(addr.String(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) + cc, err := grpc.NewClient(addr.String(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) require.NoError(t, err, "Failed to create the MetricsServiceClient: %v", err) t.Cleanup(func() { require.NoError(t, cc.Close()) diff --git a/receiver/otlpreceiver/internal/trace/otlp_test.go b/receiver/otlpreceiver/internal/trace/otlp_test.go index 58bfc61f4fc..f0dab89069d 100644 --- a/receiver/otlpreceiver/internal/trace/otlp_test.go +++ b/receiver/otlpreceiver/internal/trace/otlp_test.go @@ -20,8 +20,8 @@ import ( "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" + "go.opentelemetry.io/collector/pdata/testdata" "go.opentelemetry.io/collector/receiver/receiverhelper" "go.opentelemetry.io/collector/receiver/receivertest" ) @@ -71,7 +71,7 @@ func TestExport_PermanentErrorConsumer(t *testing.T) { func makeTraceServiceClient(t *testing.T, tc consumer.Traces) ptraceotlp.GRPCClient { addr := otlpReceiverOnGRPCServer(t, tc) - cc, err := grpc.Dial(addr.String(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) + cc, err := grpc.NewClient(addr.String(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) require.NoError(t, err, "Failed to create the TraceServiceClient: %v", err) t.Cleanup(func() { require.NoError(t, cc.Close()) diff --git a/receiver/otlpreceiver/otlp.go b/receiver/otlpreceiver/otlp.go index 91936bfb6a5..43eed9b821a 100644 --- a/receiver/otlpreceiver/otlp.go +++ b/receiver/otlpreceiver/otlp.go @@ -83,7 +83,7 @@ func (r *otlpReceiver) startGRPCServer(host component.Host) error { } var err error - if r.serverGRPC, err = r.cfg.GRPC.ToServerContext(context.Background(), host, r.settings.TelemetrySettings); err != nil { + if r.serverGRPC, err = r.cfg.GRPC.ToServer(context.Background(), host, r.settings.TelemetrySettings); err != nil { return err } @@ -116,7 +116,7 @@ func (r *otlpReceiver) startGRPCServer(host component.Host) error { return nil } -func (r *otlpReceiver) startHTTPServer(host component.Host) error { +func (r *otlpReceiver) startHTTPServer(ctx context.Context, host component.Host) error { // If HTTP is not enabled, nothing to start. if r.cfg.HTTP == nil { return nil @@ -145,13 +145,13 @@ func (r *otlpReceiver) startHTTPServer(host component.Host) error { } var err error - if r.serverHTTP, err = r.cfg.HTTP.ToServer(host, r.settings.TelemetrySettings, httpMux, confighttp.WithErrorHandler(errorHandler)); err != nil { + if r.serverHTTP, err = r.cfg.HTTP.ToServer(ctx, 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 - if hln, err = r.cfg.HTTP.ServerConfig.ToListener(); err != nil { + if hln, err = r.cfg.HTTP.ServerConfig.ToListener(ctx); err != nil { return err } @@ -172,7 +172,7 @@ func (r *otlpReceiver) Start(ctx context.Context, host component.Host) error { if err := r.startGRPCServer(host); err != nil { return err } - if err := r.startHTTPServer(host); err != nil { + if err := r.startHTTPServer(ctx, 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. diff --git a/receiver/otlpreceiver/otlp_test.go b/receiver/otlpreceiver/otlp_test.go index 85b261cd6af..1920ac8de91 100644 --- a/receiver/otlpreceiver/otlp_test.go +++ b/receiver/otlpreceiver/otlp_test.go @@ -37,12 +37,12 @@ import ( "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/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/pdata/testdata" "go.opentelemetry.io/collector/receiver/receivertest" ) @@ -52,10 +52,12 @@ var otlpReceiverID = component.MustNewIDWithName("otlp", otlpReceiverName) func TestJsonHttp(t *testing.T) { tests := []struct { - name string - encoding string - contentType string - err error + name string + encoding string + contentType string + err error + expectedStatus *spb.Status + expectedStatusCode int }{ { name: "JSONUncompressed", @@ -83,16 +85,36 @@ func TestJsonHttp(t *testing.T) { contentType: "application/json", }, { - name: "NotGRPCError", - encoding: "", - contentType: "application/json", - err: errors.New("my error"), + name: "Permanent NotGRPCError", + encoding: "", + contentType: "application/json", + err: consumererror.NewPermanent(errors.New("my error")), + expectedStatus: &spb.Status{Code: int32(codes.Internal), Message: "Permanent error: my error"}, + expectedStatusCode: http.StatusInternalServerError, }, { - name: "GRPCError", - encoding: "", - contentType: "application/json", - err: status.New(codes.Unavailable, "").Err(), + name: "Retryable NotGRPCError", + encoding: "", + contentType: "application/json", + err: errors.New("my error"), + expectedStatus: &spb.Status{Code: int32(codes.Unavailable), Message: "my error"}, + expectedStatusCode: http.StatusServiceUnavailable, + }, + { + name: "Permanent GRPCError", + encoding: "", + contentType: "application/json", + err: status.New(codes.InvalidArgument, "").Err(), + expectedStatus: &spb.Status{Code: int32(codes.InvalidArgument), Message: ""}, + expectedStatusCode: http.StatusInternalServerError, + }, + { + name: "Retryable GRPCError", + encoding: "", + contentType: "application/json", + err: status.New(codes.Unavailable, "").Err(), + expectedStatus: &spb.Status{Code: int32(codes.Unavailable), Message: ""}, + expectedStatusCode: http.StatusServiceUnavailable, }, } addr := testutil.GetAvailableLocalAddress(t) @@ -108,7 +130,7 @@ func TestJsonHttp(t *testing.T) { for _, dr := range generateDataRequests(t) { url := "http://" + addr + dr.path - respBytes := doHTTPRequest(t, url, tt.encoding, tt.contentType, dr.jsonBytes, tt.err != nil) + respBytes := doHTTPRequest(t, url, tt.encoding, tt.contentType, dr.jsonBytes, tt.expectedStatusCode) if tt.err == nil { tr := ptraceotlp.NewExportResponse() assert.NoError(t, tr.UnmarshalJSON(respBytes), "Unable to unmarshal response to Response") @@ -120,7 +142,7 @@ func TestJsonHttp(t *testing.T) { 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"})) + assert.True(t, proto.Equal(errStatus, tt.expectedStatus)) } sink.checkData(t, dr.data, 0) } @@ -302,9 +324,11 @@ func TestHandleInvalidRequests(t *testing.T) { func TestProtoHttp(t *testing.T) { tests := []struct { - name string - encoding string - err error + name string + encoding string + err error + expectedStatus *spb.Status + expectedStatusCode int }{ { name: "ProtoUncompressed", @@ -319,14 +343,32 @@ func TestProtoHttp(t *testing.T) { encoding: "zstd", }, { - name: "NotGRPCError", - encoding: "", - err: errors.New("my error"), + name: "Permanent NotGRPCError", + encoding: "", + err: consumererror.NewPermanent(errors.New("my error")), + expectedStatus: &spb.Status{Code: int32(codes.Internal), Message: "Permanent error: my error"}, + expectedStatusCode: http.StatusInternalServerError, }, { - name: "GRPCError", - encoding: "", - err: status.New(codes.Unavailable, "").Err(), + name: "Retryable NotGRPCError", + encoding: "", + err: errors.New("my error"), + expectedStatus: &spb.Status{Code: int32(codes.Unavailable), Message: "my error"}, + expectedStatusCode: http.StatusServiceUnavailable, + }, + { + name: "Permanent GRPCError", + encoding: "", + err: status.New(codes.InvalidArgument, "").Err(), + expectedStatus: &spb.Status{Code: int32(codes.InvalidArgument), Message: ""}, + expectedStatusCode: http.StatusInternalServerError, + }, + { + name: "Retryable GRPCError", + encoding: "", + err: status.New(codes.Unavailable, "").Err(), + expectedStatus: &spb.Status{Code: int32(codes.Unavailable), Message: ""}, + expectedStatusCode: http.StatusServiceUnavailable, }, } addr := testutil.GetAvailableLocalAddress(t) @@ -345,7 +387,7 @@ func TestProtoHttp(t *testing.T) { for _, dr := range generateDataRequests(t) { url := "http://" + addr + dr.path - respBytes := doHTTPRequest(t, url, tt.encoding, "application/x-protobuf", dr.protoBytes, tt.err != nil) + respBytes := doHTTPRequest(t, url, tt.encoding, "application/x-protobuf", dr.protoBytes, tt.expectedStatusCode) if tt.err == nil { tr := ptraceotlp.NewExportResponse() assert.NoError(t, tr.UnmarshalProto(respBytes)) @@ -356,7 +398,7 @@ func TestProtoHttp(t *testing.T) { 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"})) + assert.True(t, proto.Equal(errStatus, tt.expectedStatus)) } sink.checkData(t, dr.data, 0) } @@ -524,7 +566,7 @@ func TestOTLPReceiverGRPCTracesIngestTest(t *testing.T) { 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()) + cc, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) require.NoError(t, err) defer func() { assert.NoError(t, cc.Close()) @@ -552,7 +594,7 @@ func TestOTLPReceiverGRPCTracesIngestTest(t *testing.T) { require.NoError(t, tt.CheckReceiverTraces("grpc", int64(expectedReceivedBatches), int64(expectedIngestionBlockedRPCs))) } -// TestOTLPReceiverHTTPTracesNextConsumerResponse checks that the HTTP trace receiver +// TestOTLPReceiverHTTPTracesIngestTest checks that the HTTP trace receiver // is returning the proper response (return and metrics) when the next consumer // in the pipeline reports error. The test changes the responses returned by the // next trace consumer, checks if data was passed down the pipeline and if @@ -560,20 +602,30 @@ func TestOTLPReceiverGRPCTracesIngestTest(t *testing.T) { // trace receiver. func TestOTLPReceiverHTTPTracesIngestTest(t *testing.T) { type ingestionStateTest struct { - okToIngest bool - expectedCode codes.Code + okToIngest bool + err error + expectedCode codes.Code + expectedStatusCode int } expectedReceivedBatches := 2 - expectedIngestionBlockedRPCs := 1 + expectedIngestionBlockedRPCs := 2 ingestionStates := []ingestionStateTest{ { okToIngest: true, expectedCode: codes.OK, }, { - okToIngest: false, - expectedCode: codes.Unavailable, + okToIngest: false, + err: consumererror.NewPermanent(errors.New("consumer error")), + expectedCode: codes.Internal, + expectedStatusCode: http.StatusInternalServerError, + }, + { + okToIngest: false, + err: errors.New("consumer error"), + expectedCode: codes.Unavailable, + expectedStatusCode: http.StatusServiceUnavailable, }, { okToIngest: true, @@ -599,7 +651,7 @@ func TestOTLPReceiverHTTPTracesIngestTest(t *testing.T) { if ingestionState.okToIngest { sink.SetConsumeError(nil) } else { - sink.SetConsumeError(errors.New("consumer error")) + sink.SetConsumeError(ingestionState.err) } pbMarshaler := ptrace.ProtoMarshaler{} @@ -620,7 +672,7 @@ func TestOTLPReceiverHTTPTracesIngestTest(t *testing.T) { } else { errStatus := &spb.Status{} assert.NoError(t, proto.Unmarshal(respBytes, errStatus)) - assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) + assert.Equal(t, ingestionState.expectedStatusCode, resp.StatusCode) assert.Equal(t, ingestionState.expectedCode, codes.Code(errStatus.Code)) } } @@ -636,10 +688,10 @@ func TestGRPCInvalidTLSCredentials(t *testing.T) { GRPC: &configgrpc.ServerConfig{ NetAddr: confignet.AddrConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), - Transport: "tcp", + Transport: confignet.TransportTypeTCP, }, TLSSetting: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CertFile: "willfail", }, }, @@ -670,7 +722,7 @@ func TestGRPCMaxRecvSize(t *testing.T) { 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()) + cc, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) require.NoError(t, err) td := testdata.GenerateTraces(50000) @@ -683,7 +735,7 @@ func TestGRPCMaxRecvSize(t *testing.T) { 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()) + cc, err = grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) require.NoError(t, err) defer func() { assert.NoError(t, cc.Close()) @@ -702,7 +754,7 @@ func TestHTTPInvalidTLSCredentials(t *testing.T) { ServerConfig: &confighttp.ServerConfig{ Endpoint: testutil.GetAvailableLocalAddress(t), TLSSetting: &configtls.ServerConfig{ - TLSSetting: configtls.Config{ + Config: configtls.Config{ CertFile: "willfail", }, }, @@ -853,7 +905,7 @@ func doHTTPRequest( encoding string, contentType string, data []byte, - expectErr bool, + expectStatusCode int, ) []byte { req := createHTTPRequest(t, url, encoding, contentType, data) resp, err := http.DefaultClient.Do(req) @@ -866,10 +918,10 @@ func doHTTPRequest( // 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 { + if expectStatusCode == 0 { require.Equal(t, http.StatusOK, resp.StatusCode) } else { - require.Equal(t, http.StatusInternalServerError, resp.StatusCode) + require.Equal(t, expectStatusCode, resp.StatusCode) } return respBytes @@ -956,7 +1008,7 @@ func TestShutdown(t *testing.T) { require.NotNil(t, r) require.NoError(t, r.Start(context.Background(), componenttest.NewNopHost())) - conn, err := grpc.Dial(endpointGrpc, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) + conn, err := grpc.NewClient(endpointGrpc, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, conn.Close()) diff --git a/receiver/otlpreceiver/otlphttp.go b/receiver/otlpreceiver/otlphttp.go index dca42737052..b895b8d2e7c 100644 --- a/receiver/otlpreceiver/otlphttp.go +++ b/receiver/otlpreceiver/otlphttp.go @@ -10,9 +10,10 @@ import ( "net/http" spb "google.golang.org/genproto/googleapis/rpc/status" - "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "go.opentelemetry.io/collector/internal/httphelper" + "go.opentelemetry.io/collector/receiver/otlpreceiver/internal/errors" "go.opentelemetry.io/collector/receiver/otlpreceiver/internal/logs" "go.opentelemetry.io/collector/receiver/otlpreceiver/internal/metrics" "go.opentelemetry.io/collector/receiver/otlpreceiver/internal/trace" @@ -149,8 +150,10 @@ func readAndCloseBody(resp http.ResponseWriter, req *http.Request, enc encoder) // writeError encodes the HTTP error inside a rpc.Status message as required by the OTLP protocol. func writeError(w http.ResponseWriter, encoder encoder, err error, statusCode int) { s, ok := status.FromError(err) - if !ok { - s = errorMsgToStatus(err.Error(), statusCode) + if ok { + statusCode = errors.GetHTTPStatusCodeFromStatus(s) + } else { + s = httphelper.NewStatusFromMsgAndHTTPCode(err.Error(), statusCode) } writeStatusResponse(w, encoder, statusCode, s.Proto()) } @@ -158,7 +161,7 @@ func writeError(w http.ResponseWriter, encoder encoder, err error, statusCode in // errorHandler encodes the HTTP error message inside a rpc.Status message as required // by the OTLP protocol. func errorHandler(w http.ResponseWriter, r *http.Request, errMsg string, statusCode int) { - s := errorMsgToStatus(errMsg, statusCode) + s := httphelper.NewStatusFromMsgAndHTTPCode(errMsg, statusCode) switch getMimeTypeFromContentType(r.Header.Get("Content-Type")) { case pbContentType: writeStatusResponse(w, pbEncoder, statusCode, s.Proto()) @@ -187,13 +190,6 @@ func writeResponse(w http.ResponseWriter, contentType string, statusCode int, ms _, _ = w.Write(msg) } -func errorMsgToStatus(errMsg string, statusCode int) *status.Status { - if statusCode == http.StatusBadRequest { - return status.New(codes.InvalidArgument, errMsg) - } - return status.New(codes.Unknown, errMsg) -} - func getMimeTypeFromContentType(contentType string) string { mediatype, _, err := mime.ParseMediaType(contentType) if err != nil { diff --git a/receiver/otlpreceiver/package_test.go b/receiver/otlpreceiver/package_test.go deleted file mode 100644 index 9d49b5c8f7b..00000000000 --- a/receiver/otlpreceiver/package_test.go +++ /dev/null @@ -1,17 +0,0 @@ -// 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/receiverhelper/obsreport.go b/receiver/receiverhelper/obsreport.go index d70f6789157..ae1422b68f1 100644 --- a/receiver/receiverhelper/obsreport.go +++ b/receiver/receiverhelper/obsreport.go @@ -20,7 +20,7 @@ import ( ) const ( - receiverScope = obsmetrics.Scope + obsmetrics.NameSep + obsmetrics.ReceiverKey + receiverScope = obsmetrics.Scope + obsmetrics.SpanNameSep + obsmetrics.ReceiverKey ) // ObsReport is a helper to add observability to a receiver. @@ -88,42 +88,42 @@ func (rec *ObsReport) createOtelMetrics() error { var errors, err error rec.acceptedSpansCounter, err = rec.meter.Int64Counter( - obsmetrics.ReceiverPrefix+obsmetrics.AcceptedSpansKey, + obsmetrics.ReceiverMetricPrefix+obsmetrics.AcceptedSpansKey, metric.WithDescription("Number of spans successfully pushed into the pipeline."), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) rec.refusedSpansCounter, err = rec.meter.Int64Counter( - obsmetrics.ReceiverPrefix+obsmetrics.RefusedSpansKey, + obsmetrics.ReceiverMetricPrefix+obsmetrics.RefusedSpansKey, metric.WithDescription("Number of spans that could not be pushed into the pipeline."), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) rec.acceptedMetricPointsCounter, err = rec.meter.Int64Counter( - obsmetrics.ReceiverPrefix+obsmetrics.AcceptedMetricPointsKey, + obsmetrics.ReceiverMetricPrefix+obsmetrics.AcceptedMetricPointsKey, metric.WithDescription("Number of metric points successfully pushed into the pipeline."), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) rec.refusedMetricPointsCounter, err = rec.meter.Int64Counter( - obsmetrics.ReceiverPrefix+obsmetrics.RefusedMetricPointsKey, + obsmetrics.ReceiverMetricPrefix+obsmetrics.RefusedMetricPointsKey, metric.WithDescription("Number of metric points that could not be pushed into the pipeline."), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) rec.acceptedLogRecordsCounter, err = rec.meter.Int64Counter( - obsmetrics.ReceiverPrefix+obsmetrics.AcceptedLogRecordsKey, + obsmetrics.ReceiverMetricPrefix+obsmetrics.AcceptedLogRecordsKey, metric.WithDescription("Number of log records successfully pushed into the pipeline."), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) rec.refusedLogRecordsCounter, err = rec.meter.Int64Counter( - obsmetrics.ReceiverPrefix+obsmetrics.RefusedLogRecordsKey, + obsmetrics.ReceiverMetricPrefix+obsmetrics.RefusedLogRecordsKey, metric.WithDescription("Number of log records that could not be pushed into the pipeline."), metric.WithUnit("1"), ) diff --git a/receiver/receivertest/contract_checker.go b/receiver/receivertest/contract_checker.go index 37dd68b7f80..6951b5f41f4 100644 --- a/receiver/receivertest/contract_checker.go +++ b/receiver/receivertest/contract_checker.go @@ -390,7 +390,7 @@ func (m *mockConsumer) ConsumeMetrics(_ context.Context, data pmetric.Metrics) e return m.consume(ids) } -// idSetFromLogs computes an idSet from given pmetric.Metrics. The idSet will contain ids of all metric data points. +// idSetFromMetrics 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() diff --git a/receiver/receivertest/nop_receiver.go b/receiver/receivertest/nop_receiver.go index 0c7cee87cf3..e9cec06ca1b 100644 --- a/receiver/receivertest/nop_receiver.go +++ b/receiver/receivertest/nop_receiver.go @@ -6,33 +6,56 @@ package receivertest // import "go.opentelemetry.io/collector/receiver/receivert import ( "context" + "github.com/google/uuid" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/receiver" ) -var componentType = component.MustNewType("nop") +var defaultComponentType = component.MustNewType("nop") // NewNopCreateSettings returns a new nop settings for Create*Receiver functions. func NewNopCreateSettings() receiver.CreateSettings { return receiver.CreateSettings{ - ID: component.NewID(componentType), + ID: component.NewIDWithName(defaultComponentType, uuid.NewString()), TelemetrySettings: componenttest.NewNopTelemetrySettings(), BuildInfo: component.NewDefaultBuildInfo(), } } -// NewNopFactory returns a receiver.Factory that constructs nop receivers. +// NewNopFactory returns a receiver.Factory that constructs nop receivers supporting all data types. func NewNopFactory() receiver.Factory { return receiver.NewFactory( - componentType, + defaultComponentType, func() component.Config { return &nopConfig{} }, receiver.WithTraces(createTraces, component.StabilityLevelStable), receiver.WithMetrics(createMetrics, component.StabilityLevelStable), receiver.WithLogs(createLogs, component.StabilityLevelStable)) } +// NewNopFactoryForType returns a receiver.Factory that constructs nop receivers supporting only the +// given data type. +func NewNopFactoryForType(dataType component.DataType) receiver.Factory { + var factoryOpt receiver.FactoryOption + switch dataType { + case component.DataTypeTraces: + factoryOpt = receiver.WithTraces(createTraces, component.StabilityLevelStable) + case component.DataTypeMetrics: + factoryOpt = receiver.WithMetrics(createMetrics, component.StabilityLevelStable) + case component.DataTypeLogs: + factoryOpt = receiver.WithLogs(createLogs, component.StabilityLevelStable) + default: + panic("unsupported data type for creating nop receiver factory: " + dataType.String()) + } + + componentType := component.MustNewType(defaultComponentType.String() + "_" + dataType.String()) + return receiver.NewFactory(componentType, func() component.Config { return &nopConfig{} }, factoryOpt) +} + +type nopConfig struct{} + func createTraces(context.Context, receiver.CreateSettings, component.Config, consumer.Traces) (receiver.Traces, error) { return nopInstance, nil } @@ -45,8 +68,6 @@ func createLogs(context.Context, receiver.CreateSettings, component.Config, cons return nopInstance, nil } -type nopConfig struct{} - var nopInstance = &nopReceiver{} // nopReceiver acts as a receiver for testing purposes. @@ -59,6 +80,6 @@ type nopReceiver struct { func NewNopBuilder() *receiver.Builder { nopFactory := NewNopFactory() return receiver.NewBuilder( - map[component.ID]component.Config{component.NewID(componentType): nopFactory.CreateDefaultConfig()}, - map[component.Type]receiver.Factory{componentType: nopFactory}) + map[component.ID]component.Config{component.NewID(defaultComponentType): nopFactory.CreateDefaultConfig()}, + map[component.Type]receiver.Factory{defaultComponentType: nopFactory}) } diff --git a/receiver/scraperhelper/config.go b/receiver/scraperhelper/config.go index 68f0a56297d..84b7cd2073e 100644 --- a/receiver/scraperhelper/config.go +++ b/receiver/scraperhelper/config.go @@ -9,20 +9,12 @@ import ( "time" "go.uber.org/multierr" - - "go.opentelemetry.io/collector/component" ) var ( errNonPositiveInterval = errors.New("requires positive value") ) -// 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. -// 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. @@ -38,13 +30,6 @@ type ControllerConfig struct { Timeout time.Duration `mapstructure:"timeout"` } -// NewDefaultScraperControllerSettings returns default scraper controller -// settings with a collection interval of one minute. -// 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 { diff --git a/receiver/scraperhelper/obsreport.go b/receiver/scraperhelper/obsreport.go index a8ba76b66e7..89ad80fdc08 100644 --- a/receiver/scraperhelper/obsreport.go +++ b/receiver/scraperhelper/obsreport.go @@ -22,7 +22,7 @@ import ( ) var ( - scraperScope = obsmetrics.Scope + obsmetrics.NameSep + obsmetrics.ScraperKey + scraperScope = obsmetrics.Scope + obsmetrics.SpanNameSep + obsmetrics.ScraperKey ) // ObsReport is a helper to add observability to a scraper. @@ -98,7 +98,7 @@ 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 { - spanName := obsmetrics.ScraperPrefix + s.receiverID.String() + obsmetrics.NameSep + s.scraper.String() + obsmetrics.ScraperMetricsOperationSuffix + spanName := obsmetrics.ScraperPrefix + s.receiverID.String() + obsmetrics.SpanNameSep + s.scraper.String() + obsmetrics.ScraperMetricsOperationSuffix ctx, _ = s.tracer.Start(ctx, spanName) return ctx } diff --git a/receiver/scraperhelper/scrapercontroller.go b/receiver/scraperhelper/scrapercontroller.go index 2f2896f6903..eb13ee66cc4 100644 --- a/receiver/scraperhelper/scrapercontroller.go +++ b/receiver/scraperhelper/scrapercontroller.go @@ -33,7 +33,7 @@ func AddScraper(scraper Scraper) ScraperControllerOption { } } -// WithTickerChannel allows you to override the scraper controllers ticker +// WithTickerChannel allows you to override the scraper controller's ticker // channel to specify when scrape is called. This is only expected to be // used by tests. func WithTickerChannel(tickerCh <-chan time.Time) ScraperControllerOption { @@ -163,7 +163,7 @@ func (sc *controller) startScraping() { sc.tickerCh = ticker.C } - // Call scrape method on initialision to ensure + // Call scrape method on initialization to ensure // that scrapers start from when the component starts // instead of waiting for the full duration to start. sc.scrapeMetricsAndReport() diff --git a/renovate.json b/renovate.json index 9f645452830..bcbc26dd133 100644 --- a/renovate.json +++ b/renovate.json @@ -35,8 +35,10 @@ }, { "matchManagers": ["gomod"], - "matchSourceUrlPrefixes": ["https://go.opentelemetry.io/contrib"], - "groupName": "All go.opentelemetry.io/contrib packages" + "matchSourceUrls": [ + "https://github.com/open-telemetry/opentelemetry-go-contrib" + ], + "groupName": "All opentelemetry-go-contrib packages" }, { "matchManagers": ["gomod"], @@ -50,8 +52,13 @@ }, { "matchManagers": ["gomod"], - "matchSourceUrlPrefixes": ["https://golang.org"], - "groupName": "All golang.org packages" + "matchSourceUrlPrefixes": ["https://golang.org/x"], + "groupName": "All golang.org/x packages" + }, + { + "matchManagers": ["gomod"], + "matchSourceUrlPrefixes": ["https://go.opentelemetry.io/build-tools"], + "groupName": "All go.opentelemetry.io/build-tools packages" } ], "ignoreDeps": [ diff --git a/semconv/go.mod b/semconv/go.mod index 6f758cc6751..ca3f2b7da1a 100644 --- a/semconv/go.mod +++ b/semconv/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/hashicorp/go-version v1.6.0 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 go.uber.org/goleak v1.3.0 ) diff --git a/semconv/go.sum b/semconv/go.sum index 8ca3cb9177c..180ea53240d 100644 --- a/semconv/go.sum +++ b/semconv/go.sum @@ -16,8 +16,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN 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= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/semconv/v1.25.0/doc.go b/semconv/v1.25.0/doc.go new file mode 100644 index 00000000000..ad9e94a49f8 --- /dev/null +++ b/semconv/v1.25.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.25.0 +// version of the OpenTelemetry semantic conventions. +package semconv // import "go.opentelemetry.io/collector/semconv/v1.25.0" diff --git a/semconv/v1.25.0/generated_attribute_group.go b/semconv/v1.25.0/generated_attribute_group.go new file mode 100644 index 00000000000..0d8fc75a410 --- /dev/null +++ b/semconv/v1.25.0/generated_attribute_group.go @@ -0,0 +1,4796 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Code generated from semantic convention specification. DO NOT EDIT. + +package semconv + +// Attributes for Events represented using Log Records. +const ( + // Identifies the class / type of event. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'browser.mouse.click', 'device.app.lifecycle' + // Note: Event names are subject to the same rules as attribute names. Notably, + // event names are namespaced to avoid collisions and provide a clean separation + // of semantics for events in separate domains like browser, mobile, and + // kubernetes. + AttributeEventName = "event.name" +) + +// The attributes described in this section are rather generic. They may be +// used in any Log Record they apply to. +const ( + // A unique identifier for the Log Record. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '01ARZ3NDEKTSV4RRFFQ69G5FAV' + // Note: If an id is provided, other log records with the same id will be + // considered duplicates and can be removed safely. This means, that two + // distinguishable log records MUST have different values. + // The id MAY be an Universally Unique Lexicographically Sortable Identifier + // (ULID), but other identifiers (e.g. UUID) may be used as needed. + AttributeLogRecordUID = "log.record.uid" +) + +// Describes Log attributes +const ( + // The stream associated with the log. See below for a list of well-known values. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeLogIostream = "log.iostream" +) + +const ( + // Logs from stdout stream + AttributeLogIostreamStdout = "stdout" + // Events from stderr stream + AttributeLogIostreamStderr = "stderr" +) + +// A file to which log was emitted. +const ( + // The basename of the file. + // + // Type: string + // Requirement Level: Recommended + // Stability: experimental + // Examples: 'audit.log' + AttributeLogFileName = "log.file.name" + // The basename of the file, with symlinks resolved. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'uuid.log' + AttributeLogFileNameResolved = "log.file.name_resolved" + // The full path to the file. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '/var/log/mysql/audit.log' + AttributeLogFilePath = "log.file.path" + // The full path to the file, with symlinks resolved. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '/var/lib/docker/uuid.log' + AttributeLogFilePathResolved = "log.file.path_resolved" +) + +// Describes Database attributes +const ( + // The name of the connection pool; unique within the instrumented application. In + // case the connection pool implementation doesn't provide a name, instrumentation + // should use a combination of server.address and server.port attributes formatted + // as server.address:server.port. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'myDataSource' + AttributePoolName = "pool.name" + // The state of a connection in the pool + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + // Examples: 'idle' + AttributeState = "state" +) + +const ( + // idle + AttributeStateIdle = "idle" + // used + AttributeStateUsed = "used" +) + +// ASP.NET Core attributes +const ( + // Rate-limiting result, shows whether the lease was acquired or contains a + // rejection reason + // + // Type: Enum + // Requirement Level: Required + // Stability: stable + // Examples: 'acquired', 'request_canceled' + AttributeAspnetcoreRateLimitingResult = "aspnetcore.rate_limiting.result" + // Full type name of the IExceptionHandler implementation that handled the + // exception. + // + // Type: string + // Requirement Level: Conditionally Required - if and only if the exception was + // handled by this handler. + // Stability: stable + // Examples: 'Contoso.MyHandler' + AttributeAspnetcoreDiagnosticsHandlerType = "aspnetcore.diagnostics.handler.type" + // Rate limiting policy name. + // + // Type: string + // Requirement Level: Conditionally Required - if the matched endpoint for the + // request had a rate-limiting policy. + // Stability: stable + // Examples: 'fixed', 'sliding', 'token' + AttributeAspnetcoreRateLimitingPolicy = "aspnetcore.rate_limiting.policy" + // Flag indicating if request was handled by the application pipeline. + // + // Type: boolean + // Requirement Level: Conditionally Required - if and only if the request was not + // handled. + // Stability: stable + // Examples: True + AttributeAspnetcoreRequestIsUnhandled = "aspnetcore.request.is_unhandled" + // A value that indicates whether the matched route is a fallback route. + // + // Type: boolean + // Requirement Level: Conditionally Required - If and only if a route was + // successfully matched. + // Stability: stable + // Examples: True + AttributeAspnetcoreRoutingIsFallback = "aspnetcore.routing.is_fallback" +) + +const ( + // Lease was acquired + AttributeAspnetcoreRateLimitingResultAcquired = "acquired" + // Lease request was rejected by the endpoint limiter + AttributeAspnetcoreRateLimitingResultEndpointLimiter = "endpoint_limiter" + // Lease request was rejected by the global limiter + AttributeAspnetcoreRateLimitingResultGlobalLimiter = "global_limiter" + // Lease request was canceled + AttributeAspnetcoreRateLimitingResultRequestCanceled = "request_canceled" +) + +// SignalR attributes +const ( + // SignalR HTTP connection closure status. + // + // Type: Enum + // Requirement Level: Optional + // Stability: stable + // Examples: 'app_shutdown', 'timeout' + AttributeSignalrConnectionStatus = "signalr.connection.status" + // SignalR transport type + // + // Type: Enum + // Requirement Level: Optional + // Stability: stable + // Examples: 'web_sockets', 'long_polling' + AttributeSignalrTransport = "signalr.transport" +) + +const ( + // The connection was closed normally + AttributeSignalrConnectionStatusNormalClosure = "normal_closure" + // The connection was closed due to a timeout + AttributeSignalrConnectionStatusTimeout = "timeout" + // The connection was closed because the app is shutting down + AttributeSignalrConnectionStatusAppShutdown = "app_shutdown" +) + +const ( + // ServerSentEvents protocol + AttributeSignalrTransportServerSentEvents = "server_sent_events" + // LongPolling protocol + AttributeSignalrTransportLongPolling = "long_polling" + // WebSockets protocol + AttributeSignalrTransportWebSockets = "web_sockets" +) + +// Describes JVM buffer metric attributes. +const ( + // Name of the buffer pool. + // + // Type: string + // Requirement Level: Recommended + // Stability: experimental + // Examples: 'mapped', 'direct' + // Note: Pool names are generally obtained via BufferPoolMXBean#getName(). + AttributeJvmBufferPoolName = "jvm.buffer.pool.name" +) + +// Describes JVM memory metric attributes. +const ( + // Name of the memory pool. + // + // Type: string + // Requirement Level: Recommended + // Stability: stable + // Examples: 'G1 Old Gen', 'G1 Eden space', 'G1 Survivor Space' + // Note: Pool names are generally obtained via MemoryPoolMXBean#getName(). + AttributeJvmMemoryPoolName = "jvm.memory.pool.name" + // The type of memory. + // + // Type: Enum + // Requirement Level: Recommended + // Stability: stable + // Examples: 'heap', 'non_heap' + AttributeJvmMemoryType = "jvm.memory.type" +) + +const ( + // Heap memory + AttributeJvmMemoryTypeHeap = "heap" + // Non-heap memory + AttributeJvmMemoryTypeNonHeap = "non_heap" +) + +// Attributes for process CPU metrics. +const ( + // The CPU state for this data point. A process SHOULD be characterized either by + // data points with no state labels, or only data points with state labels. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeProcessCPUState = "process.cpu.state" +) + +const ( + // system + AttributeProcessCPUStateSystem = "system" + // user + AttributeProcessCPUStateUser = "user" + // wait + AttributeProcessCPUStateWait = "wait" +) + +// Describes System metric attributes +const ( + // The device identifier + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '(identifier)' + AttributeSystemDevice = "system.device" +) + +// Describes System CPU metric attributes +const ( + // The logical CPU number [0..n-1] + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 1 + AttributeSystemCPULogicalNumber = "system.cpu.logical_number" + // The CPU state for this data point. A system's CPU SHOULD be characterized + // either by data points with no state labels, or only data points with state + // labels. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'idle', 'interrupt' + AttributeSystemCPUState = "system.cpu.state" +) + +const ( + // user + AttributeSystemCPUStateUser = "user" + // system + AttributeSystemCPUStateSystem = "system" + // nice + AttributeSystemCPUStateNice = "nice" + // idle + AttributeSystemCPUStateIdle = "idle" + // iowait + AttributeSystemCPUStateIowait = "iowait" + // interrupt + AttributeSystemCPUStateInterrupt = "interrupt" + // steal + AttributeSystemCPUStateSteal = "steal" +) + +// Describes System Memory metric attributes +const ( + // The memory state + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'free', 'cached' + AttributeSystemMemoryState = "system.memory.state" +) + +const ( + // used + AttributeSystemMemoryStateUsed = "used" + // free + AttributeSystemMemoryStateFree = "free" + // shared + AttributeSystemMemoryStateShared = "shared" + // buffers + AttributeSystemMemoryStateBuffers = "buffers" + // cached + AttributeSystemMemoryStateCached = "cached" +) + +// Describes System Memory Paging metric attributes +const ( + // The paging access direction + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'in' + AttributeSystemPagingDirection = "system.paging.direction" + // The memory paging state + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'free' + AttributeSystemPagingState = "system.paging.state" + // The memory paging type + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'minor' + AttributeSystemPagingType = "system.paging.type" +) + +const ( + // in + AttributeSystemPagingDirectionIn = "in" + // out + AttributeSystemPagingDirectionOut = "out" +) + +const ( + // used + AttributeSystemPagingStateUsed = "used" + // free + AttributeSystemPagingStateFree = "free" +) + +const ( + // major + AttributeSystemPagingTypeMajor = "major" + // minor + AttributeSystemPagingTypeMinor = "minor" +) + +// Describes Filesystem metric attributes +const ( + // The filesystem mode + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'rw, ro' + AttributeSystemFilesystemMode = "system.filesystem.mode" + // The filesystem mount path + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '/mnt/data' + AttributeSystemFilesystemMountpoint = "system.filesystem.mountpoint" + // The filesystem state + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'used' + AttributeSystemFilesystemState = "system.filesystem.state" + // The filesystem type + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'ext4' + AttributeSystemFilesystemType = "system.filesystem.type" +) + +const ( + // used + AttributeSystemFilesystemStateUsed = "used" + // free + AttributeSystemFilesystemStateFree = "free" + // reserved + AttributeSystemFilesystemStateReserved = "reserved" +) + +const ( + // fat32 + AttributeSystemFilesystemTypeFat32 = "fat32" + // exfat + AttributeSystemFilesystemTypeExfat = "exfat" + // ntfs + AttributeSystemFilesystemTypeNtfs = "ntfs" + // refs + AttributeSystemFilesystemTypeRefs = "refs" + // hfsplus + AttributeSystemFilesystemTypeHfsplus = "hfsplus" + // ext4 + AttributeSystemFilesystemTypeExt4 = "ext4" +) + +// Describes Network metric attributes +const ( + // A stateless protocol MUST NOT set this attribute + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'close_wait' + AttributeSystemNetworkState = "system.network.state" +) + +const ( + // close + AttributeSystemNetworkStateClose = "close" + // close_wait + AttributeSystemNetworkStateCloseWait = "close_wait" + // closing + AttributeSystemNetworkStateClosing = "closing" + // delete + AttributeSystemNetworkStateDelete = "delete" + // established + AttributeSystemNetworkStateEstablished = "established" + // fin_wait_1 + AttributeSystemNetworkStateFinWait1 = "fin_wait_1" + // fin_wait_2 + AttributeSystemNetworkStateFinWait2 = "fin_wait_2" + // last_ack + AttributeSystemNetworkStateLastAck = "last_ack" + // listen + AttributeSystemNetworkStateListen = "listen" + // syn_recv + AttributeSystemNetworkStateSynRecv = "syn_recv" + // syn_sent + AttributeSystemNetworkStateSynSent = "syn_sent" + // time_wait + AttributeSystemNetworkStateTimeWait = "time_wait" +) + +// Describes System Process metric attributes +const ( + // The process state, e.g., Linux Process State Codes + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'running' + AttributeSystemProcessStatus = "system.process.status" +) + +const ( + // running + AttributeSystemProcessStatusRunning = "running" + // sleeping + AttributeSystemProcessStatusSleeping = "sleeping" + // stopped + AttributeSystemProcessStatusStopped = "stopped" + // defunct + AttributeSystemProcessStatusDefunct = "defunct" +) + +// 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" +) + +// Attributes for AWS DynamoDB. +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 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 Count response parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 10 + AttributeAWSDynamoDBCount = "aws.dynamodb.count" + // The value of the ExclusiveStartTableName request parameter. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Users', 'CatsTable' + AttributeAWSDynamoDBExclusiveStartTable = "aws.dynamodb.exclusive_start_table" + // The JSON-serialized value of each item in 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" + // 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 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 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" + // 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 ScanIndexForward request parameter. + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + AttributeAWSDynamoDBScanForward = "aws.dynamodb.scan_forward" + // 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 Select request parameter. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'ALL_ATTRIBUTES', 'COUNT' + AttributeAWSDynamoDBSelect = "aws.dynamodb.select" + // The number of items in the TableNames response parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 20 + AttributeAWSDynamoDBTableCount = "aws.dynamodb.table_count" + // The keys in the RequestItems object field. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Users', 'Cats' + AttributeAWSDynamoDBTableNames = "aws.dynamodb.table_names" + // The value of the TotalSegments request parameter. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 100 + AttributeAWSDynamoDBTotalSegments = "aws.dynamodb.total_segments" +) + +// The web browser attributes +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" +) + +// These attributes may be used to describe the client in a connection-based +// network interaction where there is one side that initiates the connection +// (the client is the side that initiates the connection). This covers all TCP +// network interactions since TCP is connection-based and one side initiates +// the connection (an exception is made for peer-to-peer communication over TCP +// where the "user-facing" surface of the protocol / API doesn't expose a clear +// notion of client and server). This also covers UDP network interactions +// where one side initiates the interaction, e.g. QUIC (HTTP/3) and DNS. +const ( + // Client address - domain name if available without reverse DNS lookup; + // otherwise, IP address or Unix domain socket name. + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: 'client.example.com', '10.1.2.80', '/tmp/my.sock' + // Note: When observed from the server side, and when communicating through an + // intermediary, client.address SHOULD represent the client address behind any + // intermediaries, for example proxies, if it's available. + AttributeClientAddress = "client.address" + // Client port number. + // + // Type: int + // Requirement Level: Optional + // Stability: stable + // Examples: 65123 + // Note: When observed from the server side, and when communicating through an + // intermediary, client.port SHOULD represent the client port behind any + // intermediaries, for example proxies, if it's available. + AttributeClientPort = "client.port" +) + +// 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:

+ 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 Apps + AttributeCloudPlatformAzureContainerApps = "azure_container_apps" + // 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" +) + +// Attributes for CloudEvents. +const ( + // The event_id uniquely identifies the event. + // + // Type: string + // Requirement Level: Optional + // 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: Optional + // 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" +) + +// 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" + // 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: '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)' + AttributeCodeStacktrace = "code.stacktrace" +) + +// 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" + // The CPU state for this data point. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'user', 'kernel' + AttributeContainerCPUState = "container.cpu.state" + // 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" +) + +const ( + // When tasks of the cgroup are in user mode (Linux). When all container processes are in user mode (Windows) + AttributeContainerCPUStateUser = "user" + // When CPU is used by the system (host OS) + AttributeContainerCPUStateSystem = "system" + // When tasks of the cgroup are in kernel mode (Linux). When all container processes are in kernel mode (Windows) + AttributeContainerCPUStateKernel = "kernel" +) + +// The attributes used to describe telemetry in the context of databases. +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 Cassandra table that the operation is acting upon, + // including the keyspace name (if applicable). + // + // Type: string + // Requirement Level: Optional + // 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" + // 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: Optional + // Stability: experimental + AttributeDBCosmosDBConnectionMode = "db.cosmosdb.connection_mode" + // Cosmos DB container name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'anystring' + AttributeDBCosmosDBContainer = "db.cosmosdb.container" + // CosmosDB Operation Type. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeDBCosmosDBOperationType = "db.cosmosdb.operation_type" + // RU consumed for that operation + // + // Type: double + // Requirement Level: Optional + // 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: Optional + // Stability: experimental + // Examples: 200, 201 + AttributeDBCosmosDBStatusCode = "db.cosmosdb.status_code" + // Cosmos DB sub status code. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 1000, 1002 + AttributeDBCosmosDBSubStatusCode = "db.cosmosdb.sub_status_code" + // Represents the identifier of an Elasticsearch cluster. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'e9106fc68e3044f0b1475b04bf4ffd5f' + AttributeDBElasticsearchClusterName = "db.elasticsearch.cluster.name" + // An identifier (address, unique name, or any other identifier) of the database + // instance that is executing queries or mutations on the current connection. This + // is useful in cases where the database is running in a clustered environment and + // the instrumentation is able to record the node executing the query. The client + // may obtain this value in databases like MySQL using queries like select + // @@hostname. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'mysql-e26b99z.example.com' + AttributeDBInstanceID = "db.instance.id" + // The MongoDB collection being accessed within the database stated in db.name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'customers', 'products' + AttributeDBMongoDBCollection = "db.mongodb.collection" + // 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" + // 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: Optional + // 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: Optional + // 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 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: Optional + // Stability: experimental + // Examples: 0, 1, 15 + AttributeDBRedisDBIndex = "db.redis.database_index" + // The name of the primary table that the operation is acting upon, including the + // database name (if applicable). + // + // Type: string + // Requirement Level: Optional + // 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" + // The database statement being executed. + // + // Type: string + // Requirement Level: Optional + // 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: Optional + // 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 ( + // 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" +) + +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" +) + +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" +) + +// Attributes for software deployments. +const ( + // Name of the deployment environment (aka deployment tier). + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'staging', 'production' + // Note: deployment.environment does not affect the uniqueness constraints defined + // through + // the service.namespace, service.name and service.instance.id resource + // attributes. + // This implies that resources carrying the following attribute combinations MUST + // be + // considered to be identifying the same service:
    + //
  • service.name=frontend, deployment.environment=production
  • + //
  • service.name=frontend, deployment.environment=staging.
  • + //
+ AttributeDeploymentEnvironment = "deployment.environment" +) + +// "Describes deprecated db attributes." +const ( + // Deprecated, use server.address, server.port attributes instead. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: "Replaced by `server.address` and `server.port`." + // Examples: 'Server=(localdb)\\v11.0;Integrated Security=true;' + AttributeDBConnectionString = "db.connection_string" + // Deprecated, use db.instance.id instead. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `db.instance.id`. + // Examples: 'instance-0000000001' + AttributeDBElasticsearchNodeName = "db.elasticsearch.node.name" + // Removed, no replacement at this time. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Removed as not used. + // Examples: 'org.postgresql.Driver', + // 'com.microsoft.sqlserver.jdbc.SQLServerDriver' + AttributeDBJDBCDriverClassname = "db.jdbc.driver_classname" +) + +// Describes deprecated HTTP attributes. +const ( + // Deprecated, use network.protocol.name instead. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `network.protocol.name`. + AttributeHTTPFlavor = "http.flavor" + // Deprecated, use http.request.method instead. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `http.request.method`. + // Examples: 'GET', 'POST', 'HEAD' + AttributeHTTPMethod = "http.method" + // Deprecated, use http.request.header.content-length instead. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `http.request.header.content-length`. + // Examples: 3495 + AttributeHTTPRequestContentLength = "http.request_content_length" + // Deprecated, use http.response.header.content-length instead. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `http.response.header.content-length`. + // Examples: 3495 + AttributeHTTPResponseContentLength = "http.response_content_length" + // Deprecated, use url.scheme instead. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `url.scheme` instead. + // Examples: 'http', 'https' + AttributeHTTPScheme = "http.scheme" + // Deprecated, use http.response.status_code instead. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `http.response.status_code`. + // Examples: 200 + AttributeHTTPStatusCode = "http.status_code" + // Deprecated, use url.path and url.query instead. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Split to `url.path` and `url.query. + // Examples: '/search?q=OpenTelemetry#SemConv' + AttributeHTTPTarget = "http.target" + // Deprecated, use url.full instead. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `url.full`. + // Examples: 'https://www.foo.bar/search?q=OpenTelemetry#SemConv' + AttributeHTTPURL = "http.url" + // Deprecated, use user_agent.original instead. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `user_agent.original`. + // Examples: 'CERN-LineMode/2.15 libwww/2.17b3', 'Mozilla/5.0 (iPhone; CPU iPhone + // OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) + // Version/14.1.2 Mobile/15E148 Safari/604.1' + AttributeHTTPUserAgent = "http.user_agent" +) + +const ( + // HTTP/1.0 + AttributeHTTPFlavorHTTP10 = "1.0" + // HTTP/1.1 + AttributeHTTPFlavorHTTP11 = "1.1" + // HTTP/2 + AttributeHTTPFlavorHTTP20 = "2.0" + // HTTP/3 + AttributeHTTPFlavorHTTP30 = "3.0" + // SPDY protocol + AttributeHTTPFlavorSPDY = "SPDY" + // QUIC protocol + AttributeHTTPFlavorQUIC = "QUIC" +) + +// Describes deprecated messaging attributes. +const ( + // "Deprecated, use messaging.destination.partition.id instead." + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `messaging.destination.partition.id`. + // Examples: 2 + AttributeMessagingKafkaDestinationPartition = "messaging.kafka.destination.partition" +) + +// These attributes may be used for any network related operation. +const ( + // Deprecated, use server.address. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `server.address`. + // Examples: 'example.com' + AttributeNetHostName = "net.host.name" + // Deprecated, use server.port. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `server.port`. + // Examples: 8080 + AttributeNetHostPort = "net.host.port" + // Deprecated, use server.address on client spans and client.address on server + // spans. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `server.address` on client spans and `client.address` + // on server spans. + // Examples: 'example.com' + AttributeNetPeerName = "net.peer.name" + // Deprecated, use server.port on client spans and client.port on server spans. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `server.port` on client spans and `client.port` on + // server spans. + // Examples: 8080 + AttributeNetPeerPort = "net.peer.port" + // Deprecated, use network.protocol.name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `network.protocol.name`. + // Examples: 'amqp', 'http', 'mqtt' + AttributeNetProtocolName = "net.protocol.name" + // Deprecated, use network.protocol.version. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `network.protocol.version`. + // Examples: '3.1.1' + AttributeNetProtocolVersion = "net.protocol.version" + // Deprecated, use network.transport and network.type. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Split to `network.transport` and `network.type`. + AttributeNetSockFamily = "net.sock.family" + // Deprecated, use network.local.address. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `network.local.address`. + // Examples: '/var/my.sock' + AttributeNetSockHostAddr = "net.sock.host.addr" + // Deprecated, use network.local.port. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `network.local.port`. + // Examples: 8080 + AttributeNetSockHostPort = "net.sock.host.port" + // Deprecated, use network.peer.address. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `network.peer.address`. + // Examples: '192.168.0.1' + AttributeNetSockPeerAddr = "net.sock.peer.addr" + // Deprecated, no replacement at this time. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Removed. + // Examples: '/var/my.sock' + AttributeNetSockPeerName = "net.sock.peer.name" + // Deprecated, use network.peer.port. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `network.peer.port`. + // Examples: 65531 + AttributeNetSockPeerPort = "net.sock.peer.port" + // Deprecated, use network.transport. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `network.transport`. + AttributeNetTransport = "net.transport" +) + +const ( + // IPv4 address + AttributeNetSockFamilyInet = "inet" + // IPv6 address + AttributeNetSockFamilyInet6 = "inet6" + // Unix domain socket path + AttributeNetSockFamilyUnix = "unix" +) + +const ( + // ip_tcp + AttributeNetTransportTCP = "ip_tcp" + // ip_udp + AttributeNetTransportUDP = "ip_udp" + // Named or anonymous pipe + AttributeNetTransportPipe = "pipe" + // In-process communication + AttributeNetTransportInProc = "inproc" + // Something else (non IP-based) + AttributeNetTransportOther = "other" +) + +// Deprecated system attributes. +const ( + // Deprecated, use system.process.status instead. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Deprecated: Replaced by `system.process.status`. + // Examples: 'running' + AttributeSystemProcessesStatus = "system.processes.status" +) + +const ( + // running + AttributeSystemProcessesStatusRunning = "running" + // sleeping + AttributeSystemProcessesStatusSleeping = "sleeping" + // stopped + AttributeSystemProcessesStatusStopped = "stopped" + // defunct + AttributeSystemProcessesStatusDefunct = "defunct" +) + +// These attributes may be used to describe the receiver of a network +// exchange/packet. These should be used when there is no client/server +// relationship between the two sides, or when that relationship is unknown. +// This covers low-level network interactions (e.g. packet tracing) where you +// don't know if there was a connection or which side initiated it. This also +// covers unidirectional UDP flows and peer-to-peer communication where the +// "user-facing" surface of the protocol / API doesn't expose a clear notion of +// client and server. +const ( + // Destination address - domain name if available without reverse DNS lookup; + // otherwise, IP address or Unix domain socket name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'destination.example.com', '10.1.2.80', '/tmp/my.sock' + // Note: When observed from the source side, and when communicating through an + // intermediary, destination.address SHOULD represent the destination address + // behind any intermediaries, for example proxies, if it's available. + AttributeDestinationAddress = "destination.address" + // Destination port number + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 3389, 2888 + AttributeDestinationPort = "destination.port" +) + +// Describes device attributes. +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" +) + +// These attributes may be used for any disk related operation. +const ( + // The disk IO operation direction. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'read' + AttributeDiskIoDirection = "disk.io.direction" +) + +const ( + // read + AttributeDiskIoDirectionRead = "read" + // write + AttributeDiskIoDirectionWrite = "write" +) + +// The shared attributes used to report a DNS query. +const ( + // The name being queried. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'www.example.com', 'opentelemetry.io' + // Note: If the name field contains non-printable characters (below 32 or above + // 126), those characters should be represented as escaped base 10 integers + // (\DDD). Back slashes and quotes should be escaped. Tabs, carriage returns, and + // line feeds should be converted to \t, \r, and \n respectively. + AttributeDNSQuestionName = "dns.question.name" +) + +// Attributes for operations 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" +) + +// The shared attributes used to report an error. +const ( + // Describes a class of error the operation ended with. + // + // Type: Enum + // Requirement Level: Optional + // Stability: stable + // Examples: 'timeout', 'java.net.UnknownHostException', + // 'server_certificate_invalid', '500' + // Note: The error.type SHOULD be predictable and SHOULD have low cardinality. + // Instrumentations SHOULD document the list of errors they report.The cardinality + // of error.type within one instrumentation library SHOULD be low. + // Telemetry consumers that aggregate data from multiple instrumentation libraries + // and applications + // should be prepared for error.type to have high cardinality at query time when + // no + // additional filters are applied.If the operation has completed successfully, + // instrumentations SHOULD NOT set error.type.If a specific domain defines its own + // set of error identifiers (such as HTTP or gRPC status codes), + // it's RECOMMENDED to:
    + //
  • Use a domain-specific attribute
  • + //
  • Set error.type to capture all errors, regardless of whether they are + // defined within the domain-specific set or not.
  • + //
+ AttributeErrorType = "error.type" +) + +const ( + // A fallback error value to be used when the instrumentation doesn't define a custom value + AttributeErrorTypeOther = "_OTHER" +) + +// The shared attributes used to report a single exception associated with a +// span or log. +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: stable + // 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 for recording span exceptions.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" + // The exception message. + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // 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: stable + // 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: stable + // Examples: 'java.net.ConnectException', 'OSError' + AttributeExceptionType = "exception.type" +) + +// FaaS attributes +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" + // A string containing the schedule period as Cron Expression. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '0/5 * * * ? *' + AttributeFaaSCron = "faas.cron" + // 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: Optional + // 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: Optional + // 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" + // 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 invocation ID of the current function invocation. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'af9d5aa4-a685-4c5f-a22b-444f80b3cc28' + AttributeFaaSInvocationID = "faas.invocation_id" + // The name of the invoked function. + // + // Type: string + // Requirement Level: Optional + // 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: Optional + // 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: 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" + // 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: Optional + // 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" + // 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" + // Type of the trigger which caused this function invocation. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeFaaSTrigger = "faas.trigger" + // 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" +) + +const ( + // When a new object is created + AttributeFaaSDocumentOperationInsert = "insert" + // When an object is modified + AttributeFaaSDocumentOperationEdit = "edit" + // When an object is deleted + AttributeFaaSDocumentOperationDelete = "delete" +) + +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" +) + +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" +) + +// Attributes for Feature Flags. +const ( + // The unique identifier of the feature flag. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'logo-color' + AttributeFeatureFlagKey = "feature_flag.key" + // The name of the service provider that performs the flag evaluation. + // + // Type: string + // Requirement Level: Optional + // 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: Optional + // 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" +) + +// Describes file attributes. +const ( + // Directory where the file is located. It should include the drive letter, when + // appropriate. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '/home/user', 'C:\\Program Files\\MyApp' + AttributeFileDirectory = "file.directory" + // File extension, excluding the leading dot. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'png', 'gz' + // Note: When the file name has multiple extensions (example.tar.gz), only the + // last one should be captured ("gz", not "tar.gz"). + AttributeFileExtension = "file.extension" + // Name of the file including the extension, without the directory. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'example.png' + AttributeFileName = "file.name" + // Full path to the file, including the file name. It should include the drive + // letter, when appropriate. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '/home/alice/example.png', 'C:\\Program Files\\MyApp\\myapp.exe' + AttributeFilePath = "file.path" + // File size in bytes. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + AttributeFileSize = "file.size" +) + +// Attributes for 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" +) + +// Attributes for 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" +) + +// 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" + // 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" + // Family or generation of the CPU. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '6', 'PA-RISC 1.1e' + AttributeHostCPUFamily = "host.cpu.family" + // Model identifier. It provides more granular information about the CPU, + // distinguishing it from other CPUs within the same family. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '6', '9000/778/B180L' + 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: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '1', 'r1p1' + 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" + // 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" + // Available MAC addresses of the host, excluding loopback interfaces. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'AC-DE-48-23-45-67', 'AC-DE-48-23-45-67-01-9F' + // Note: MAC Addresses MUST be represented in IEEE RA hexadecimal form: as hyphen- + // separated octets in uppercase hexadecimal form from most to least significant. + AttributeHostMac = "host.mac" + // 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" +) + +// Semantic convention attributes in the HTTP namespace. +const ( + // State of the HTTP connection in the HTTP connection pool. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'active', 'idle' + AttributeHTTPConnectionState = "http.connection.state" + // The size of the request payload body in bytes. This is the number of bytes + // transferred excluding headers and is often, but not always, present as the + // Content-Length header. For requests using transport encoding, this should be + // the compressed size. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 3495 + AttributeHTTPRequestBodySize = "http.request.body.size" + // HTTP request method. + // + // Type: Enum + // Requirement Level: Optional + // Stability: stable + // Examples: 'GET', 'POST', 'HEAD' + // Note: HTTP request method value SHOULD be "known" to the + // instrumentation. + // By default, this convention defines "known" methods as the ones + // listed in RFC9110 + // and the PATCH method defined in RFC5789.If the HTTP request method is not known + // to instrumentation, it MUST set the http.request.method attribute to _OTHER.If + // the HTTP instrumentation could end up converting valid HTTP request methods to + // _OTHER, then it MUST provide a way to override + // the list of known HTTP methods. If this override is done via environment + // variable, then the environment variable MUST be named + // OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list of + // case-sensitive known HTTP methods + // (this list MUST be a full override of the default known method, it is not a + // list of known methods in addition to the defaults).HTTP method names are case- + // sensitive and http.request.method attribute value MUST match a known HTTP + // method name exactly. + // Instrumentations for specific web frameworks that consider HTTP methods to be + // case insensitive, SHOULD populate a canonical equivalent. + // Tracing instrumentations that do so, MUST also set http.request.method_original + // to the original value. + AttributeHTTPRequestMethod = "http.request.method" + // Original HTTP method sent by the client in the request line. + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: 'GeT', 'ACL', 'foo' + AttributeHTTPRequestMethodOriginal = "http.request.method_original" + // The ordinal number of request resending attempt (for any reason, including + // redirects). + // + // Type: int + // Requirement Level: Optional + // Stability: stable + // 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). + AttributeHTTPRequestResendCount = "http.request.resend_count" + // The total size of the request in bytes. This should be the total number of + // bytes sent over the wire, including the request line (HTTP/1.1), framing + // (HTTP/2 and HTTP/3), headers, and request body if any. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 1437 + AttributeHTTPRequestSize = "http.request.size" + // The size of the response payload body in bytes. This is the number of bytes + // transferred excluding headers and is often, but not always, present as the + // Content-Length header. For requests using transport encoding, this should be + // the compressed size. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 3495 + AttributeHTTPResponseBodySize = "http.response.body.size" + // The total size of the response in bytes. This should be the total number of + // bytes sent over the wire, including the status line (HTTP/1.1), framing (HTTP/2 + // and HTTP/3), headers, and response body and trailers if any. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 1437 + AttributeHTTPResponseSize = "http.response.size" + // HTTP response status code. + // + // Type: int + // Requirement Level: Optional + // Stability: stable + // Examples: 200 + AttributeHTTPResponseStatusCode = "http.response.status_code" + // The matched route, that is, the path template in the format used by the + // respective server framework. + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: '/users/:userID?', '{controller}/{action}/{id?}' + // Note: MUST NOT be populated when this is not supported by the HTTP server + // framework as the route attribute should have low-cardinality and the URI path + // can NOT substitute it. + // SHOULD include the application root if there is one. + AttributeHTTPRoute = "http.route" +) + +const ( + // active state + AttributeHTTPConnectionStateActive = "active" + // idle state + AttributeHTTPConnectionStateIdle = "idle" +) + +const ( + // CONNECT method + AttributeHTTPRequestMethodConnect = "CONNECT" + // DELETE method + AttributeHTTPRequestMethodDelete = "DELETE" + // GET method + AttributeHTTPRequestMethodGet = "GET" + // HEAD method + AttributeHTTPRequestMethodHead = "HEAD" + // OPTIONS method + AttributeHTTPRequestMethodOptions = "OPTIONS" + // PATCH method + AttributeHTTPRequestMethodPatch = "PATCH" + // POST method + AttributeHTTPRequestMethodPost = "POST" + // PUT method + AttributeHTTPRequestMethodPut = "PUT" + // TRACE method + AttributeHTTPRequestMethodTrace = "TRACE" + // Any HTTP method that the instrumentation has no prior knowledge of + AttributeHTTPRequestMethodOther = "_OTHER" +) + +// Kubernetes resource attributes. +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 doesn't 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" + // 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" + // 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 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" + // 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" + // 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" + // The name of the namespace that the pod is running in. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'default' + AttributeK8SNamespaceName = "k8s.namespace.name" + // 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" + // 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" + // 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" + // 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" +) + +// Attributes describing telemetry around messaging systems and messaging +// activities. +const ( + // The number of messages sent, received, or processed in the scope of the + // batching operation. + // + // Type: int + // Requirement Level: Optional + // 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: Optional + // Stability: experimental + // Examples: 'client-5', 'myhost@8742@s8083jm' + AttributeMessagingClientID = "messaging.client_id" + // A boolean that is true if the message destination is anonymous (could be + // unnamed or have auto-generated name). + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + AttributeMessagingDestinationAnonymous = "messaging.destination.anonymous" + // The message destination name + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'MyQueue', 'MyTopic' + // Note: Destination name SHOULD uniquely identify a specific queue, topic or + // other entity within the broker. If + // the broker doesn't have such notion, the destination name SHOULD uniquely + // identify the broker. + AttributeMessagingDestinationName = "messaging.destination.name" + // The identifier of the partition messages are sent to or received from, unique + // within the messaging.destination.name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '1' + AttributeMessagingDestinationPartitionID = "messaging.destination.partition.id" + // Low cardinality representation of the messaging destination name + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '/customers/{customerID}' + // Note: Destination names could be constructed from templates. An example would + // be a destination name involving a user name or product id. Although the + // destination name in this case is of high cardinality, the underlying template + // is of low cardinality and can be effectively used for grouping and aggregation. + AttributeMessagingDestinationTemplate = "messaging.destination.template" + // A boolean that is true if the message destination is temporary and might not + // exist anymore after messages are processed. + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + AttributeMessagingDestinationTemporary = "messaging.destination.temporary" + // A boolean that is true if the publish message destination is anonymous (could + // be unnamed or have auto-generated name). + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + AttributeMessagingDestinationPublishAnonymous = "messaging.destination_publish.anonymous" + // The name of the original destination the message was published to + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'MyQueue', 'MyTopic' + // Note: The name SHOULD uniquely identify a specific queue, topic, or other + // entity within the broker. If + // the broker doesn't have such notion, the original destination name SHOULD + // uniquely identify the broker. + AttributeMessagingDestinationPublishName = "messaging.destination_publish.name" + // The name of the consumer group the event consumer is associated with. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'indexer' + AttributeMessagingEventhubsConsumerGroup = "messaging.eventhubs.consumer.group" + // The UTC epoch seconds at which the message has been accepted and stored in the + // entity. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 1701393730 + AttributeMessagingEventhubsMessageEnqueuedTime = "messaging.eventhubs.message.enqueued_time" + // The ordering key for a given message. If the attribute is not present, the + // message does not have an ordering key. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'ordering_key' + AttributeMessagingGCPPubsubMessageOrderingKey = "messaging.gcp_pubsub.message.ordering_key" + // Name of the Kafka Consumer Group that is handling the message. Only applies to + // consumers, not producers. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'my-group' + AttributeMessagingKafkaConsumerGroup = "messaging.kafka.consumer.group" + // Message keys in Kafka are used for grouping alike messages to ensure they're + // processed on the same partition. They differ from messaging.message.id in that + // they're not unique. If the key is null, the attribute MUST NOT be set. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'myKey' + // Note: If the key type is not string, it's string representation has to be + // supplied for the attribute. If the key has no unambiguous, canonical string + // form, don't include its value. + AttributeMessagingKafkaMessageKey = "messaging.kafka.message.key" + // The offset of a record in the corresponding Kafka partition. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 42 + AttributeMessagingKafkaMessageOffset = "messaging.kafka.message.offset" + // A boolean that is true if the message is a tombstone. + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + AttributeMessagingKafkaMessageTombstone = "messaging.kafka.message.tombstone" + // The size of the message body in bytes. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 1439 + // Note: This can refer to both the compressed or uncompressed body size. If both + // sizes are known, the uncompressed + // body size should be used. + AttributeMessagingMessageBodySize = "messaging.message.body.size" + // The conversation ID identifying the conversation to which the message belongs, + // represented as a string. Sometimes called "Correlation ID". + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'MyConversationID' + AttributeMessagingMessageConversationID = "messaging.message.conversation_id" + // The size of the message body and metadata in bytes. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 2738 + // Note: This can refer to both the compressed or uncompressed size. If both sizes + // are known, the uncompressed + // size should be used. + AttributeMessagingMessageEnvelopeSize = "messaging.message.envelope.size" + // A value used by the messaging system as an identifier for the message, + // represented as a string. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '452a7c7c7c7048c2f887f61572b18fc2' + AttributeMessagingMessageID = "messaging.message.id" + // A string identifying the kind of messaging operation. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Note: If a custom value is used, it MUST be of low cardinality. + AttributeMessagingOperation = "messaging.operation" + // RabbitMQ message routing key. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'myKey' + AttributeMessagingRabbitmqDestinationRoutingKey = "messaging.rabbitmq.destination.routing_key" + // RabbitMQ message delivery tag + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 123 + AttributeMessagingRabbitmqMessageDeliveryTag = "messaging.rabbitmq.message.delivery_tag" + // Name of the RocketMQ producer/consumer group that is handling the message. The + // client type is identified by the SpanKind. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'myConsumerGroup' + AttributeMessagingRocketmqClientGroup = "messaging.rocketmq.client_group" + // Model of message consumption. This only applies to consumer spans. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeMessagingRocketmqConsumptionModel = "messaging.rocketmq.consumption_model" + // The delay time level for delay message, which determines the message delay + // time. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 3 + AttributeMessagingRocketmqMessageDelayTimeLevel = "messaging.rocketmq.message.delay_time_level" + // The timestamp in milliseconds that the delay message is expected to be + // delivered to consumer. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 1665987217045 + AttributeMessagingRocketmqMessageDeliveryTimestamp = "messaging.rocketmq.message.delivery_timestamp" + // It is essential for FIFO message. Messages that belong to the same message + // group are always processed one by one within the same consumer group. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'myMessageGroup' + AttributeMessagingRocketmqMessageGroup = "messaging.rocketmq.message.group" + // Key(s) of message, another way to mark message besides message id. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'keyA', 'keyB' + AttributeMessagingRocketmqMessageKeys = "messaging.rocketmq.message.keys" + // The secondary classifier of message besides topic. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'tagA' + AttributeMessagingRocketmqMessageTag = "messaging.rocketmq.message.tag" + // Type of message. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeMessagingRocketmqMessageType = "messaging.rocketmq.message.type" + // Namespace of RocketMQ resources, resources in different namespaces are + // individual. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'myNamespace' + AttributeMessagingRocketmqNamespace = "messaging.rocketmq.namespace" + // The name of the subscription in the topic messages are received from. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'mySubscription' + AttributeMessagingServicebusDestinationSubscriptionName = "messaging.servicebus.destination.subscription_name" + // Describes the settlement type. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeMessagingServicebusDispositionStatus = "messaging.servicebus.disposition_status" + // Number of deliveries that have been attempted for this message. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 2 + AttributeMessagingServicebusMessageDeliveryCount = "messaging.servicebus.message.delivery_count" + // The UTC epoch seconds at which the message has been accepted and stored in the + // entity. + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 1701393730 + AttributeMessagingServicebusMessageEnqueuedTime = "messaging.servicebus.message.enqueued_time" + // An identifier for the messaging system being used. See below for a list of + // well-known identifiers. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeMessagingSystem = "messaging.system" +) + +const ( + // One or more messages are provided for publishing to an intermediary. If a single message is published, the context of the "Publish" span can be used as the creation context and no "Create" span needs to be created + AttributeMessagingOperationPublish = "publish" + // A message is created. "Create" spans always refer to a single message and are used to provide a unique creation context for messages in batch publishing scenarios + AttributeMessagingOperationCreate = "create" + // One or more messages are requested by a consumer. This operation refers to pull-based scenarios, where consumers explicitly call methods of messaging SDKs to receive messages + AttributeMessagingOperationReceive = "receive" + // One or more messages are delivered to or processed by a consumer + AttributeMessagingOperationDeliver = "process" + // One or more messages are settled + AttributeMessagingOperationSettle = "settle" +) + +const ( + // Clustering consumption model + AttributeMessagingRocketmqConsumptionModelClustering = "clustering" + // Broadcasting consumption model + AttributeMessagingRocketmqConsumptionModelBroadcasting = "broadcasting" +) + +const ( + // Normal message + AttributeMessagingRocketmqMessageTypeNormal = "normal" + // FIFO message + AttributeMessagingRocketmqMessageTypeFifo = "fifo" + // Delay message + AttributeMessagingRocketmqMessageTypeDelay = "delay" + // Transaction message + AttributeMessagingRocketmqMessageTypeTransaction = "transaction" +) + +const ( + // Message is completed + AttributeMessagingServicebusDispositionStatusComplete = "complete" + // Message is abandoned + AttributeMessagingServicebusDispositionStatusAbandon = "abandon" + // Message is sent to dead letter queue + AttributeMessagingServicebusDispositionStatusDeadLetter = "dead_letter" + // Message is deferred + AttributeMessagingServicebusDispositionStatusDefer = "defer" +) + +const ( + // Apache ActiveMQ + AttributeMessagingSystemActivemq = "activemq" + // Amazon Simple Queue Service (SQS) + AttributeMessagingSystemAWSSqs = "aws_sqs" + // Azure Event Grid + AttributeMessagingSystemEventgrid = "eventgrid" + // Azure Event Hubs + AttributeMessagingSystemEventhubs = "eventhubs" + // Azure Service Bus + AttributeMessagingSystemServicebus = "servicebus" + // Google Cloud Pub/Sub + AttributeMessagingSystemGCPPubsub = "gcp_pubsub" + // Java Message Service + AttributeMessagingSystemJms = "jms" + // Apache Kafka + AttributeMessagingSystemKafka = "kafka" + // RabbitMQ + AttributeMessagingSystemRabbitmq = "rabbitmq" + // Apache RocketMQ + AttributeMessagingSystemRocketmq = "rocketmq" +) + +// These attributes may be used for any network related operation. +const ( + // The ISO 3166-1 alpha-2 2-character country code associated with the mobile + // carrier network. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'DE' + AttributeNetworkCarrierIcc = "network.carrier.icc" + // The mobile carrier country code. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '310' + AttributeNetworkCarrierMcc = "network.carrier.mcc" + // The mobile carrier network code. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '001' + AttributeNetworkCarrierMnc = "network.carrier.mnc" + // The name of the mobile carrier. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'sprint' + AttributeNetworkCarrierName = "network.carrier.name" + // This describes more details regarding the connection.type. It may be the type + // of cell technology connection, but it could be used for describing details + // about a wifi connection. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'LTE' + AttributeNetworkConnectionSubtype = "network.connection.subtype" + // The internet connection type. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'wifi' + AttributeNetworkConnectionType = "network.connection.type" + // The network IO operation direction. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + // Examples: 'transmit' + AttributeNetworkIoDirection = "network.io.direction" + // Local address of the network connection - IP address or Unix domain socket + // name. + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: '10.1.2.80', '/tmp/my.sock' + AttributeNetworkLocalAddress = "network.local.address" + // Local port number of the network connection. + // + // Type: int + // Requirement Level: Optional + // Stability: stable + // Examples: 65123 + AttributeNetworkLocalPort = "network.local.port" + // Peer address of the network connection - IP address or Unix domain socket name. + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: '10.1.2.80', '/tmp/my.sock' + AttributeNetworkPeerAddress = "network.peer.address" + // Peer port number of the network connection. + // + // Type: int + // Requirement Level: Optional + // Stability: stable + // Examples: 65123 + AttributeNetworkPeerPort = "network.peer.port" + // OSI application layer or non-OSI equivalent. + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: 'amqp', 'http', 'mqtt' + // Note: The value SHOULD be normalized to lowercase. + AttributeNetworkProtocolName = "network.protocol.name" + // The actual version of the protocol used for network communication. + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: '1.1', '2' + // Note: If protocol version is subject to negotiation (for example using ALPN), + // this attribute SHOULD be set to the negotiated version. If the actual protocol + // version is not known, this attribute SHOULD NOT be set. + AttributeNetworkProtocolVersion = "network.protocol.version" + // OSI transport layer or inter-process communication method. + // + // Type: Enum + // Requirement Level: Optional + // Stability: stable + // Examples: 'tcp', 'udp' + // Note: The value SHOULD be normalized to lowercase.Consider always setting the + // transport when setting a port number, since + // a port number is ambiguous without knowing the transport. For example + // different processes could be listening on TCP port 12345 and UDP port 12345. + AttributeNetworkTransport = "network.transport" + // OSI network layer or non-OSI equivalent. + // + // Type: Enum + // Requirement Level: Optional + // Stability: stable + // Examples: 'ipv4', 'ipv6' + // Note: The value SHOULD be normalized to lowercase. + AttributeNetworkType = "network.type" +) + +const ( + // GPRS + AttributeNetworkConnectionSubtypeGprs = "gprs" + // EDGE + AttributeNetworkConnectionSubtypeEdge = "edge" + // UMTS + AttributeNetworkConnectionSubtypeUmts = "umts" + // CDMA + AttributeNetworkConnectionSubtypeCdma = "cdma" + // EVDO Rel. 0 + AttributeNetworkConnectionSubtypeEvdo0 = "evdo_0" + // EVDO Rev. A + AttributeNetworkConnectionSubtypeEvdoA = "evdo_a" + // CDMA2000 1XRTT + AttributeNetworkConnectionSubtypeCdma20001xrtt = "cdma2000_1xrtt" + // HSDPA + AttributeNetworkConnectionSubtypeHsdpa = "hsdpa" + // HSUPA + AttributeNetworkConnectionSubtypeHsupa = "hsupa" + // HSPA + AttributeNetworkConnectionSubtypeHspa = "hspa" + // IDEN + AttributeNetworkConnectionSubtypeIden = "iden" + // EVDO Rev. B + AttributeNetworkConnectionSubtypeEvdoB = "evdo_b" + // LTE + AttributeNetworkConnectionSubtypeLte = "lte" + // EHRPD + AttributeNetworkConnectionSubtypeEhrpd = "ehrpd" + // HSPAP + AttributeNetworkConnectionSubtypeHspap = "hspap" + // GSM + AttributeNetworkConnectionSubtypeGsm = "gsm" + // TD-SCDMA + AttributeNetworkConnectionSubtypeTdScdma = "td_scdma" + // IWLAN + AttributeNetworkConnectionSubtypeIwlan = "iwlan" + // 5G NR (New Radio) + AttributeNetworkConnectionSubtypeNr = "nr" + // 5G NRNSA (New Radio Non-Standalone) + AttributeNetworkConnectionSubtypeNrnsa = "nrnsa" + // LTE CA + AttributeNetworkConnectionSubtypeLteCa = "lte_ca" +) + +const ( + // wifi + AttributeNetworkConnectionTypeWifi = "wifi" + // wired + AttributeNetworkConnectionTypeWired = "wired" + // cell + AttributeNetworkConnectionTypeCell = "cell" + // unavailable + AttributeNetworkConnectionTypeUnavailable = "unavailable" + // unknown + AttributeNetworkConnectionTypeUnknown = "unknown" +) + +const ( + // transmit + AttributeNetworkIoDirectionTransmit = "transmit" + // receive + AttributeNetworkIoDirectionReceive = "receive" +) + +const ( + // TCP + AttributeNetworkTransportTCP = "tcp" + // UDP + AttributeNetworkTransportUDP = "udp" + // Named or anonymous pipe + AttributeNetworkTransportPipe = "pipe" + // Unix domain socket + AttributeNetworkTransportUnix = "unix" +) + +const ( + // IPv4 + AttributeNetworkTypeIpv4 = "ipv4" + // IPv6 + AttributeNetworkTypeIpv6 = "ipv6" +) + +// 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: Optional + // 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: Optional + // 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: Optional + // 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: Optional + // 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: Optional + // 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: Optional + // 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 (PPID). + // + // 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" + // 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" +) + +// Attributes for remote procedure calls. +const ( + // The error codes of the Connect request. Error codes are always string values. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeRPCConnectRPCErrorCode = "rpc.connect_rpc.error_code" + // The numeric status code of the gRPC request. + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeRPCGRPCStatusCode = "rpc.grpc.status_code" + // error.code property of response if it is an error response. + // + // Type: int + // Requirement Level: Optional + // 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 + // doesn't specify this, the value can be omitted. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2.0', '1.0' + AttributeRPCJsonrpcVersion = "rpc.jsonrpc.version" + // The name of the (logical) method being called, must be equal to the $method + // part in the span name. + // + // Type: string + // Requirement Level: Optional + // 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: Optional + // 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: Optional + // Stability: experimental + AttributeRPCSystem = "rpc.system" +) + +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" +) + +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" +) + +const ( + // gRPC + AttributeRPCSystemGRPC = "grpc" + // Java RMI + AttributeRPCSystemJavaRmi = "java_rmi" + // .NET WCF + AttributeRPCSystemDotnetWcf = "dotnet_wcf" + // Apache Dubbo + AttributeRPCSystemApacheDubbo = "apache_dubbo" + // Connect RPC + AttributeRPCSystemConnectRPC = "connect_rpc" +) + +// These attributes may be used to describe the server in a connection-based +// network interaction where there is one side that initiates the connection +// (the client is the side that initiates the connection). This covers all TCP +// network interactions since TCP is connection-based and one side initiates +// the connection (an exception is made for peer-to-peer communication over TCP +// where the "user-facing" surface of the protocol / API doesn't expose a clear +// notion of client and server). This also covers UDP network interactions +// where one side initiates the interaction, e.g. QUIC (HTTP/3) and DNS. +const ( + // Server domain name if available without reverse DNS lookup; otherwise, IP + // address or Unix domain socket name. + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: 'example.com', '10.1.2.80', '/tmp/my.sock' + // Note: When observed from the client side, and when communicating through an + // intermediary, server.address SHOULD represent the server address behind any + // intermediaries, for example proxies, if it's available. + AttributeServerAddress = "server.address" + // Server port number. + // + // Type: int + // Requirement Level: Optional + // Stability: stable + // Examples: 80, 8080, 443 + // Note: When observed from the client side, and when communicating through an + // intermediary, server.port SHOULD represent the server port behind any + // intermediaries, for example proxies, if it's available. + AttributeServerPort = "server.port" +) + +// A service instance. +const ( + // The string ID of the service instance. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '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).Implementations, such as SDKs, are recommended to generate a random + // Version 1 or Version 4 RFC + // 4122 UUID, but are free to use an inherent unique ID as the source of + // this value if stability is desirable. In that case, the ID SHOULD be used as + // source of a UUID Version 5 and + // SHOULD use the following UUID as the namespace: 4d63009a-8d0f-11ee- + // aad7-4c796ed8e320.UUIDs are typically recommended, as only an opaque value for + // the purposes of identifying a service instance is + // needed. Similar to what can be seen in the man page for the + // /etc/machine-id file, the underlying + // data, such as pod name and namespace should be treated as confidential, being + // the user's choice to expose it + // or not via another resource attribute.For applications running behind an + // application server (like unicorn), we do not recommend using one identifier + // for all processes participating in the application. Instead, it's recommended + // each division (e.g. a worker + // thread in unicorn) to have its own instance.id.It's not recommended for a + // Collector to set service.instance.id if it can't unambiguously determine the + // service instance that is generating that telemetry. For instance, creating an + // UUID based on pod.name will + // likely be wrong, as the Collector might not know from which container within + // that pod the telemetry originated. + // However, Collectors can set the service.instance.id if they can unambiguously + // determine the service instance + // for that telemetry. This is typically the case for scraping receivers, as they + // know the target address and + // port. + AttributeServiceInstanceID = "service.instance.id" + // Logical name of the service. + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // 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" + // 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 version string of the service API or implementation. The format is not + // defined by these conventions. + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: '2.0.0', 'a01dbef8a' + AttributeServiceVersion = "service.version" +) + +// Session is defined as the period of time encompassing all activities +// performed by the application and the actions executed by the end user. +// Consequently, a Session is represented as a collection of Logs, Events, and +// Spans emitted by the Client Application throughout the Session's duration. +// Each Session is assigned a unique identifier, which is included as an +// attribute in the Logs, Events, and Spans generated during the Session's +// lifecycle. +// When a session reaches end of life, typically due to user inactivity or +// session timeout, a new session identifier will be assigned. The previous +// session identifier may be provided by the instrumentation so that telemetry +// backends can link the two sessions. +const ( + // A unique id to identify a session. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '00112233-4455-6677-8899-aabbccddeeff' + AttributeSessionID = "session.id" + // The previous session.id for this user, when known. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '00112233-4455-6677-8899-aabbccddeeff' + AttributeSessionPreviousID = "session.previous_id" +) + +// These attributes may be used to describe the sender of a network +// exchange/packet. These should be used when there is no client/server +// relationship between the two sides, or when that relationship is unknown. +// This covers low-level network interactions (e.g. packet tracing) where you +// don't know if there was a connection or which side initiated it. This also +// covers unidirectional UDP flows and peer-to-peer communication where the +// "user-facing" surface of the protocol / API doesn't expose a clear notion of +// client and server. +const ( + // Source address - domain name if available without reverse DNS lookup; + // otherwise, IP address or Unix domain socket name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'source.example.com', '10.1.2.80', '/tmp/my.sock' + // Note: When observed from the destination side, and when communicating through + // an intermediary, source.address SHOULD represent the source address behind any + // intermediaries, for example proxies, if it's available. + AttributeSourceAddress = "source.address" + // Source port number + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 3389, 2888 + AttributeSourcePort = "source.port" +) + +// Attributes for telemetry SDK. +const ( + // The language of the telemetry SDK. + // + // Type: Enum + // Requirement Level: Required + // Stability: stable + AttributeTelemetrySDKLanguage = "telemetry.sdk.language" + // The name of the telemetry SDK as defined above. + // + // Type: string + // Requirement Level: Required + // Stability: stable + // 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: stable + // Examples: '1.2.3' + AttributeTelemetrySDKVersion = "telemetry.sdk.version" + // 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" +) + +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" +) + +// 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" +) + +// Semantic convention attributes in the TLS namespace. +const ( + // String indicating the cipher used during the current connection. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'TLS_RSA_WITH_3DES_EDE_CBC_SHA', + // 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256' + // Note: The values allowed for tls.cipher MUST be one of the Descriptions of the + // registered TLS Cipher Suits. + AttributeTLSCipher = "tls.cipher" + // PEM-encoded stand-alone certificate offered by the client. This is usually + // mutually-exclusive of client.certificate_chain since this value also exists in + // that list. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'MII...' + AttributeTLSClientCertificate = "tls.client.certificate" + // Array of PEM-encoded certificates that make up the certificate chain offered by + // the client. This is usually mutually-exclusive of client.certificate since that + // value should be the first certificate in the chain. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'MII...', 'MI...' + AttributeTLSClientCertificateChain = "tls.client.certificate_chain" + // Certificate fingerprint using the MD5 digest of DER-encoded version of + // certificate offered by the client. For consistency with other hash values, this + // value should be formatted as an uppercase hash. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC' + AttributeTLSClientHashMd5 = "tls.client.hash.md5" + // Certificate fingerprint using the SHA1 digest of DER-encoded version of + // certificate offered by the client. For consistency with other hash values, this + // value should be formatted as an uppercase hash. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '9E393D93138888D288266C2D915214D1D1CCEB2A' + AttributeTLSClientHashSha1 = "tls.client.hash.sha1" + // Certificate fingerprint using the SHA256 digest of DER-encoded version of + // certificate offered by the client. For consistency with other hash values, this + // value should be formatted as an uppercase hash. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0' + AttributeTLSClientHashSha256 = "tls.client.hash.sha256" + // Distinguished name of subject of the issuer of the x.509 certificate presented + // by the client. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'CN=Example Root CA, OU=Infrastructure Team, DC=example, DC=com' + AttributeTLSClientIssuer = "tls.client.issuer" + // A hash that identifies clients based on how they perform an SSL/TLS handshake. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'd4e5b18d6b55c71272893221c96ba240' + AttributeTLSClientJa3 = "tls.client.ja3" + // Date/Time indicating when client certificate is no longer considered valid. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2021-01-01T00:00:00.000Z' + AttributeTLSClientNotAfter = "tls.client.not_after" + // Date/Time indicating when client certificate is first considered valid. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '1970-01-01T00:00:00.000Z' + AttributeTLSClientNotBefore = "tls.client.not_before" + // Also called an SNI, this tells the server which hostname to which the client is + // attempting to connect to. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry.io' + AttributeTLSClientServerName = "tls.client.server_name" + // Distinguished name of subject of the x.509 certificate presented by the client. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'CN=myclient, OU=Documentation Team, DC=example, DC=com' + AttributeTLSClientSubject = "tls.client.subject" + // Array of ciphers offered by the client during the client hello. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: '"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + // "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "..."' + AttributeTLSClientSupportedCiphers = "tls.client.supported_ciphers" + // String indicating the curve used for the given cipher, when applicable + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'secp256r1' + AttributeTLSCurve = "tls.curve" + // Boolean flag indicating if the TLS negotiation was successful and transitioned + // to an encrypted tunnel. + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + // Examples: True + AttributeTLSEstablished = "tls.established" + // String indicating the protocol being tunneled. Per the values in the IANA + // registry, this string should be lower case. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'http/1.1' + AttributeTLSNextProtocol = "tls.next_protocol" + // Normalized lowercase protocol name parsed from original string of the + // negotiated SSL/TLS protocol version + // + // Type: Enum + // Requirement Level: Optional + // Stability: experimental + AttributeTLSProtocolName = "tls.protocol.name" + // Numeric part of the version parsed from the original string of the negotiated + // SSL/TLS protocol version + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '1.2', '3' + AttributeTLSProtocolVersion = "tls.protocol.version" + // Boolean flag indicating if this TLS connection was resumed from an existing TLS + // negotiation. + // + // Type: boolean + // Requirement Level: Optional + // Stability: experimental + // Examples: True + AttributeTLSResumed = "tls.resumed" + // PEM-encoded stand-alone certificate offered by the server. This is usually + // mutually-exclusive of server.certificate_chain since this value also exists in + // that list. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'MII...' + AttributeTLSServerCertificate = "tls.server.certificate" + // Array of PEM-encoded certificates that make up the certificate chain offered by + // the server. This is usually mutually-exclusive of server.certificate since that + // value should be the first certificate in the chain. + // + // Type: string[] + // Requirement Level: Optional + // Stability: experimental + // Examples: 'MII...', 'MI...' + AttributeTLSServerCertificateChain = "tls.server.certificate_chain" + // Certificate fingerprint using the MD5 digest of DER-encoded version of + // certificate offered by the server. For consistency with other hash values, this + // value should be formatted as an uppercase hash. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC' + AttributeTLSServerHashMd5 = "tls.server.hash.md5" + // Certificate fingerprint using the SHA1 digest of DER-encoded version of + // certificate offered by the server. For consistency with other hash values, this + // value should be formatted as an uppercase hash. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '9E393D93138888D288266C2D915214D1D1CCEB2A' + AttributeTLSServerHashSha1 = "tls.server.hash.sha1" + // Certificate fingerprint using the SHA256 digest of DER-encoded version of + // certificate offered by the server. For consistency with other hash values, this + // value should be formatted as an uppercase hash. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0' + AttributeTLSServerHashSha256 = "tls.server.hash.sha256" + // Distinguished name of subject of the issuer of the x.509 certificate presented + // by the client. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'CN=Example Root CA, OU=Infrastructure Team, DC=example, DC=com' + AttributeTLSServerIssuer = "tls.server.issuer" + // A hash that identifies servers based on how they perform an SSL/TLS handshake. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'd4e5b18d6b55c71272893221c96ba240' + AttributeTLSServerJa3s = "tls.server.ja3s" + // Date/Time indicating when server certificate is no longer considered valid. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '2021-01-01T00:00:00.000Z' + AttributeTLSServerNotAfter = "tls.server.not_after" + // Date/Time indicating when server certificate is first considered valid. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '1970-01-01T00:00:00.000Z' + AttributeTLSServerNotBefore = "tls.server.not_before" + // Distinguished name of subject of the x.509 certificate presented by the server. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'CN=myserver, OU=Documentation Team, DC=example, DC=com' + AttributeTLSServerSubject = "tls.server.subject" +) + +const ( + // ssl + AttributeTLSProtocolNameSsl = "ssl" + // tls + AttributeTLSProtocolNameTLS = "tls" +) + +// Attributes describing URL. +const ( + // Domain extracted from the url.full, such as "opentelemetry.io". + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'www.foo.bar', 'opentelemetry.io', '3.12.167.2', + // '[1080:0:0:0:8:800:200C:417A]' + // Note: In some cases a URL may refer to an IP and/or port directly, without a + // domain name. In this case, the IP address would go to the domain field. If the + // URL contains a literal IPv6 address enclosed by [ and ], the [ and ] characters + // should also be captured in the domain field. + AttributeURLDomain = "url.domain" + // The file extension extracted from the url.full, excluding the leading dot. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'png', 'gz' + // Note: The file extension is only set if it exists, as not every url has a file + // extension. When the file name has multiple extensions example.tar.gz, only the + // last one should be captured gz, not tar.gz. + AttributeURLExtension = "url.extension" + // The URI fragment component + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: 'SemConv' + AttributeURLFragment = "url.fragment" + // Absolute URL describing a network resource according to RFC3986 + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: 'https://www.foo.bar/search?q=OpenTelemetry#SemConv', '//localhost' + // Note: For network calls, URL usually has + // scheme://host[:port][path][?query][#fragment] format, where the fragment is not + // transmitted over HTTP, but if it is known, it SHOULD be included nevertheless. + // url.full MUST NOT contain credentials passed via URL in form of + // https://username:password@www.example.com/. In such case username and password + // SHOULD be redacted and attribute's value SHOULD be + // https://REDACTED:REDACTED@www.example.com/. + // url.full SHOULD capture the absolute URL when it is available (or can be + // reconstructed). Sensitive content provided in url.full SHOULD be scrubbed when + // instrumentations can identify it. + AttributeURLFull = "url.full" + // Unmodified original URL as seen in the event source. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'https://www.foo.bar/search?q=OpenTelemetry#SemConv', + // 'search?q=OpenTelemetry' + // Note: In network monitoring, the observed URL may be a full URL, whereas in + // access logs, the URL is often just represented as a path. This field is meant + // to represent the URL as it was observed, complete or not. + // url.original might contain credentials passed via URL in form of + // https://username:password@www.example.com/. In such case password and username + // SHOULD NOT be redacted and attribute's value SHOULD remain the same. + AttributeURLOriginal = "url.original" + // The URI path component + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: '/search' + // Note: Sensitive content provided in url.path SHOULD be scrubbed when + // instrumentations can identify it. + AttributeURLPath = "url.path" + // Port extracted from the url.full + // + // Type: int + // Requirement Level: Optional + // Stability: experimental + // Examples: 443 + AttributeURLPort = "url.port" + // The URI query component + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: 'q=OpenTelemetry' + // Note: Sensitive content provided in url.query SHOULD be scrubbed when + // instrumentations can identify it. + AttributeURLQuery = "url.query" + // The highest registered url domain, stripped of the subdomain. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'example.com', 'foo.co.uk' + // Note: This value can be determined precisely with the public suffix list. For + // example, the registered domain for foo.example.com is example.com. Trying to + // approximate this by simply taking the last two labels will not work well for + // TLDs such as co.uk. + AttributeURLRegisteredDomain = "url.registered_domain" + // The URI scheme component identifying the used protocol. + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: 'https', 'ftp', 'telnet' + AttributeURLScheme = "url.scheme" + // The subdomain portion of a fully qualified domain name includes all of the + // names except the host name under the registered_domain. In a partially + // qualified domain, or if the qualification level of the full name cannot be + // determined, subdomain contains all of the names below the registered domain. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'east', 'sub2.sub1' + // Note: The subdomain portion of www.east.mydomain.co.uk is east. If the domain + // has multiple levels of subdomain, such as sub2.sub1.example.com, the subdomain + // field should contain sub2.sub1, with no trailing period. + AttributeURLSubdomain = "url.subdomain" + // The effective top level domain (eTLD), also known as the domain suffix, is the + // last part of the domain name. For example, the top level domain for example.com + // is com. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'com', 'co.uk' + // Note: This value can be determined precisely with the public suffix list. + AttributeURLTopLevelDomain = "url.top_level_domain" +) + +// Describes user-agent attributes. +const ( + // Name of the user-agent extracted from original. Usually refers to the browser's + // name. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'Safari', 'YourApp' + // Note: Example of extracting browser's name from original string. In the case of + // using a user-agent for non-browser products, such as microservices with + // multiple names/versions inside the user_agent.original, the most significant + // name SHOULD be selected. In such a scenario it should align with + // user_agent.version + AttributeUserAgentName = "user_agent.name" + // Value of the HTTP User-Agent header sent by the client. + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // Examples: 'CERN-LineMode/2.15 libwww/2.17b3', 'Mozilla/5.0 (iPhone; CPU iPhone + // OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) + // Version/14.1.2 Mobile/15E148 Safari/604.1', 'YourApp/1.0.0 grpc-java- + // okhttp/1.27.2' + AttributeUserAgentOriginal = "user_agent.original" + // Version of the user-agent extracted from original. Usually refers to the + // browser's version + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: '14.1.2', '1.0.0' + // Note: Example of extracting browser's version from original string. In the case + // of using a user-agent for non-browser products, such as microservices with + // multiple names/versions inside the user_agent.original, the most significant + // version SHOULD be selected. In such a scenario it should align with + // user_agent.name + AttributeUserAgentVersion = "user_agent.version" +) + +func GetAttribute_groupSemanticConventionAttributeNames() []string { + return []string{ + AttributeEventName, + AttributeLogRecordUID, + AttributeLogIostream, + AttributeLogFileName, + AttributeLogFileNameResolved, + AttributeLogFilePath, + AttributeLogFilePathResolved, + AttributePoolName, + AttributeState, + AttributeAspnetcoreRateLimitingResult, + AttributeAspnetcoreDiagnosticsHandlerType, + AttributeAspnetcoreRateLimitingPolicy, + AttributeAspnetcoreRequestIsUnhandled, + AttributeAspnetcoreRoutingIsFallback, + AttributeSignalrConnectionStatus, + AttributeSignalrTransport, + AttributeJvmBufferPoolName, + AttributeJvmMemoryPoolName, + AttributeJvmMemoryType, + AttributeProcessCPUState, + AttributeSystemDevice, + AttributeSystemCPULogicalNumber, + AttributeSystemCPUState, + AttributeSystemMemoryState, + AttributeSystemPagingDirection, + AttributeSystemPagingState, + AttributeSystemPagingType, + AttributeSystemFilesystemMode, + AttributeSystemFilesystemMountpoint, + AttributeSystemFilesystemState, + AttributeSystemFilesystemType, + AttributeSystemNetworkState, + AttributeSystemProcessStatus, + AttributeAndroidOSAPILevel, + AttributeAWSDynamoDBAttributeDefinitions, + AttributeAWSDynamoDBAttributesToGet, + AttributeAWSDynamoDBConsistentRead, + AttributeAWSDynamoDBConsumedCapacity, + AttributeAWSDynamoDBCount, + AttributeAWSDynamoDBExclusiveStartTable, + AttributeAWSDynamoDBGlobalSecondaryIndexUpdates, + AttributeAWSDynamoDBGlobalSecondaryIndexes, + AttributeAWSDynamoDBIndexName, + AttributeAWSDynamoDBItemCollectionMetrics, + AttributeAWSDynamoDBLimit, + AttributeAWSDynamoDBLocalSecondaryIndexes, + AttributeAWSDynamoDBProjection, + AttributeAWSDynamoDBProvisionedReadCapacity, + AttributeAWSDynamoDBProvisionedWriteCapacity, + AttributeAWSDynamoDBScanForward, + AttributeAWSDynamoDBScannedCount, + AttributeAWSDynamoDBSegment, + AttributeAWSDynamoDBSelect, + AttributeAWSDynamoDBTableCount, + AttributeAWSDynamoDBTableNames, + AttributeAWSDynamoDBTotalSegments, + AttributeBrowserBrands, + AttributeBrowserLanguage, + AttributeBrowserMobile, + AttributeBrowserPlatform, + AttributeClientAddress, + AttributeClientPort, + AttributeCloudAccountID, + AttributeCloudAvailabilityZone, + AttributeCloudPlatform, + AttributeCloudProvider, + AttributeCloudRegion, + AttributeCloudResourceID, + AttributeCloudeventsEventID, + AttributeCloudeventsEventSource, + AttributeCloudeventsEventSpecVersion, + AttributeCloudeventsEventSubject, + AttributeCloudeventsEventType, + AttributeCodeColumn, + AttributeCodeFilepath, + AttributeCodeFunction, + AttributeCodeLineNumber, + AttributeCodeNamespace, + AttributeCodeStacktrace, + AttributeContainerCommand, + AttributeContainerCommandArgs, + AttributeContainerCommandLine, + AttributeContainerCPUState, + AttributeContainerID, + AttributeContainerImageID, + AttributeContainerImageName, + AttributeContainerImageRepoDigests, + AttributeContainerImageTags, + AttributeContainerName, + AttributeContainerRuntime, + AttributeDBCassandraConsistencyLevel, + AttributeDBCassandraCoordinatorDC, + AttributeDBCassandraCoordinatorID, + AttributeDBCassandraIdempotence, + AttributeDBCassandraPageSize, + AttributeDBCassandraSpeculativeExecutionCount, + AttributeDBCassandraTable, + AttributeDBCosmosDBClientID, + AttributeDBCosmosDBConnectionMode, + AttributeDBCosmosDBContainer, + AttributeDBCosmosDBOperationType, + AttributeDBCosmosDBRequestCharge, + AttributeDBCosmosDBRequestContentLength, + AttributeDBCosmosDBStatusCode, + AttributeDBCosmosDBSubStatusCode, + AttributeDBElasticsearchClusterName, + AttributeDBInstanceID, + AttributeDBMongoDBCollection, + AttributeDBMSSQLInstanceName, + AttributeDBName, + AttributeDBOperation, + AttributeDBRedisDBIndex, + AttributeDBSQLTable, + AttributeDBStatement, + AttributeDBSystem, + AttributeDBUser, + AttributeDeploymentEnvironment, + AttributeDBConnectionString, + AttributeDBElasticsearchNodeName, + AttributeDBJDBCDriverClassname, + AttributeHTTPFlavor, + AttributeHTTPMethod, + AttributeHTTPRequestContentLength, + AttributeHTTPResponseContentLength, + AttributeHTTPScheme, + AttributeHTTPStatusCode, + AttributeHTTPTarget, + AttributeHTTPURL, + AttributeHTTPUserAgent, + AttributeMessagingKafkaDestinationPartition, + AttributeNetHostName, + AttributeNetHostPort, + AttributeNetPeerName, + AttributeNetPeerPort, + AttributeNetProtocolName, + AttributeNetProtocolVersion, + AttributeNetSockFamily, + AttributeNetSockHostAddr, + AttributeNetSockHostPort, + AttributeNetSockPeerAddr, + AttributeNetSockPeerName, + AttributeNetSockPeerPort, + AttributeNetTransport, + AttributeSystemProcessesStatus, + AttributeDestinationAddress, + AttributeDestinationPort, + AttributeDeviceID, + AttributeDeviceManufacturer, + AttributeDeviceModelIdentifier, + AttributeDeviceModelName, + AttributeDiskIoDirection, + AttributeDNSQuestionName, + AttributeEnduserID, + AttributeEnduserRole, + AttributeEnduserScope, + AttributeErrorType, + AttributeExceptionEscaped, + AttributeExceptionMessage, + AttributeExceptionStacktrace, + AttributeExceptionType, + AttributeFaaSColdstart, + AttributeFaaSCron, + AttributeFaaSDocumentCollection, + AttributeFaaSDocumentName, + AttributeFaaSDocumentOperation, + AttributeFaaSDocumentTime, + AttributeFaaSInstance, + AttributeFaaSInvocationID, + AttributeFaaSInvokedName, + AttributeFaaSInvokedProvider, + AttributeFaaSInvokedRegion, + AttributeFaaSMaxMemory, + AttributeFaaSName, + AttributeFaaSTime, + AttributeFaaSTrigger, + AttributeFaaSVersion, + AttributeFeatureFlagKey, + AttributeFeatureFlagProviderName, + AttributeFeatureFlagVariant, + AttributeFileDirectory, + AttributeFileExtension, + AttributeFileName, + AttributeFilePath, + AttributeFileSize, + AttributeGCPCloudRunJobExecution, + AttributeGCPCloudRunJobTaskIndex, + AttributeGCPGceInstanceHostname, + AttributeGCPGceInstanceName, + AttributeHostArch, + AttributeHostCPUCacheL2Size, + AttributeHostCPUFamily, + AttributeHostCPUModelID, + AttributeHostCPUModelName, + AttributeHostCPUStepping, + AttributeHostCPUVendorID, + AttributeHostID, + AttributeHostImageID, + AttributeHostImageName, + AttributeHostImageVersion, + AttributeHostIP, + AttributeHostMac, + AttributeHostName, + AttributeHostType, + AttributeHTTPConnectionState, + AttributeHTTPRequestBodySize, + AttributeHTTPRequestMethod, + AttributeHTTPRequestMethodOriginal, + AttributeHTTPRequestResendCount, + AttributeHTTPRequestSize, + AttributeHTTPResponseBodySize, + AttributeHTTPResponseSize, + AttributeHTTPResponseStatusCode, + AttributeHTTPRoute, + AttributeK8SClusterName, + AttributeK8SClusterUID, + AttributeK8SContainerName, + AttributeK8SContainerRestartCount, + AttributeK8SCronJobName, + AttributeK8SCronJobUID, + AttributeK8SDaemonSetName, + AttributeK8SDaemonSetUID, + AttributeK8SDeploymentName, + AttributeK8SDeploymentUID, + AttributeK8SJobName, + AttributeK8SJobUID, + AttributeK8SNamespaceName, + AttributeK8SNodeName, + AttributeK8SNodeUID, + AttributeK8SPodName, + AttributeK8SPodUID, + AttributeK8SReplicaSetName, + AttributeK8SReplicaSetUID, + AttributeK8SStatefulSetName, + AttributeK8SStatefulSetUID, + AttributeMessagingBatchMessageCount, + AttributeMessagingClientID, + AttributeMessagingDestinationAnonymous, + AttributeMessagingDestinationName, + AttributeMessagingDestinationPartitionID, + AttributeMessagingDestinationTemplate, + AttributeMessagingDestinationTemporary, + AttributeMessagingDestinationPublishAnonymous, + AttributeMessagingDestinationPublishName, + AttributeMessagingEventhubsConsumerGroup, + AttributeMessagingEventhubsMessageEnqueuedTime, + AttributeMessagingGCPPubsubMessageOrderingKey, + AttributeMessagingKafkaConsumerGroup, + AttributeMessagingKafkaMessageKey, + AttributeMessagingKafkaMessageOffset, + AttributeMessagingKafkaMessageTombstone, + AttributeMessagingMessageBodySize, + AttributeMessagingMessageConversationID, + AttributeMessagingMessageEnvelopeSize, + AttributeMessagingMessageID, + AttributeMessagingOperation, + AttributeMessagingRabbitmqDestinationRoutingKey, + AttributeMessagingRabbitmqMessageDeliveryTag, + AttributeMessagingRocketmqClientGroup, + AttributeMessagingRocketmqConsumptionModel, + AttributeMessagingRocketmqMessageDelayTimeLevel, + AttributeMessagingRocketmqMessageDeliveryTimestamp, + AttributeMessagingRocketmqMessageGroup, + AttributeMessagingRocketmqMessageKeys, + AttributeMessagingRocketmqMessageTag, + AttributeMessagingRocketmqMessageType, + AttributeMessagingRocketmqNamespace, + AttributeMessagingServicebusDestinationSubscriptionName, + AttributeMessagingServicebusDispositionStatus, + AttributeMessagingServicebusMessageDeliveryCount, + AttributeMessagingServicebusMessageEnqueuedTime, + AttributeMessagingSystem, + AttributeNetworkCarrierIcc, + AttributeNetworkCarrierMcc, + AttributeNetworkCarrierMnc, + AttributeNetworkCarrierName, + AttributeNetworkConnectionSubtype, + AttributeNetworkConnectionType, + AttributeNetworkIoDirection, + AttributeNetworkLocalAddress, + AttributeNetworkLocalPort, + AttributeNetworkPeerAddress, + AttributeNetworkPeerPort, + AttributeNetworkProtocolName, + AttributeNetworkProtocolVersion, + AttributeNetworkTransport, + AttributeNetworkType, + AttributeOciManifestDigest, + AttributeOSBuildID, + AttributeOSDescription, + AttributeOSName, + AttributeOSType, + AttributeOSVersion, + AttributeProcessCommand, + AttributeProcessCommandArgs, + AttributeProcessCommandLine, + AttributeProcessExecutableName, + AttributeProcessExecutablePath, + AttributeProcessOwner, + AttributeProcessParentPID, + AttributeProcessPID, + AttributeProcessRuntimeDescription, + AttributeProcessRuntimeName, + AttributeProcessRuntimeVersion, + AttributeRPCConnectRPCErrorCode, + AttributeRPCGRPCStatusCode, + AttributeRPCJsonrpcErrorCode, + AttributeRPCJsonrpcErrorMessage, + AttributeRPCJsonrpcRequestID, + AttributeRPCJsonrpcVersion, + AttributeRPCMethod, + AttributeRPCService, + AttributeRPCSystem, + AttributeServerAddress, + AttributeServerPort, + AttributeServiceInstanceID, + AttributeServiceName, + AttributeServiceNamespace, + AttributeServiceVersion, + AttributeSessionID, + AttributeSessionPreviousID, + AttributeSourceAddress, + AttributeSourcePort, + AttributeTelemetrySDKLanguage, + AttributeTelemetrySDKName, + AttributeTelemetrySDKVersion, + AttributeTelemetryDistroName, + AttributeTelemetryDistroVersion, + AttributeThreadID, + AttributeThreadName, + AttributeTLSCipher, + AttributeTLSClientCertificate, + AttributeTLSClientCertificateChain, + AttributeTLSClientHashMd5, + AttributeTLSClientHashSha1, + AttributeTLSClientHashSha256, + AttributeTLSClientIssuer, + AttributeTLSClientJa3, + AttributeTLSClientNotAfter, + AttributeTLSClientNotBefore, + AttributeTLSClientServerName, + AttributeTLSClientSubject, + AttributeTLSClientSupportedCiphers, + AttributeTLSCurve, + AttributeTLSEstablished, + AttributeTLSNextProtocol, + AttributeTLSProtocolName, + AttributeTLSProtocolVersion, + AttributeTLSResumed, + AttributeTLSServerCertificate, + AttributeTLSServerCertificateChain, + AttributeTLSServerHashMd5, + AttributeTLSServerHashSha1, + AttributeTLSServerHashSha256, + AttributeTLSServerIssuer, + AttributeTLSServerJa3s, + AttributeTLSServerNotAfter, + AttributeTLSServerNotBefore, + AttributeTLSServerSubject, + AttributeURLDomain, + AttributeURLExtension, + AttributeURLFragment, + AttributeURLFull, + AttributeURLOriginal, + AttributeURLPath, + AttributeURLPort, + AttributeURLQuery, + AttributeURLRegisteredDomain, + AttributeURLScheme, + AttributeURLSubdomain, + AttributeURLTopLevelDomain, + AttributeUserAgentName, + AttributeUserAgentOriginal, + AttributeUserAgentVersion, + } +} diff --git a/semconv/v1.25.0/generated_event.go b/semconv/v1.25.0/generated_event.go new file mode 100644 index 00000000000..9ce1307afe1 --- /dev/null +++ b/semconv/v1.25.0/generated_event.go @@ -0,0 +1,105 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Code generated from semantic convention specification. DO NOT EDIT. + +package semconv + +// This event represents an occurrence of a lifecycle transition on the iOS +// platform. +const ( + // This attribute represents the state the application has transitioned into at + // the occurrence of the event. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + // Note: The iOS lifecycle states are defined in the UIApplicationDelegate + // documentation, and from which the OS terminology column values are derived. + AttributeIosState = "ios.state" +) + +const ( + // The app has become `active`. Associated with UIKit notification `applicationDidBecomeActive` + AttributeIosStateActive = "active" + // The app is now `inactive`. Associated with UIKit notification `applicationWillResignActive` + AttributeIosStateInactive = "inactive" + // The app is now in the background. This value is associated with UIKit notification `applicationDidEnterBackground` + AttributeIosStateBackground = "background" + // The app is now in the foreground. This value is associated with UIKit notification `applicationWillEnterForeground` + AttributeIosStateForeground = "foreground" + // The app is about to terminate. Associated with UIKit notification `applicationWillTerminate` + AttributeIosStateTerminate = "terminate" +) + +// This event represents an occurrence of a lifecycle transition on the Android +// platform. +const ( + // This attribute represents the state the application has transitioned into at + // the occurrence of the event. + // + // Type: Enum + // Requirement Level: Required + // Stability: experimental + // Note: The Android lifecycle states are defined in Activity lifecycle callbacks, + // and from which the OS identifiers are derived. + AttributeAndroidState = "android.state" +) + +const ( + // Any time before Activity.onResume() or, if the app has no Activity, Context.startService() has been called in the app for the first time + AttributeAndroidStateCreated = "created" + // Any time after Activity.onPause() or, if the app has no Activity, Context.stopService() has been called when the app was in the foreground state + AttributeAndroidStateBackground = "background" + // Any time after Activity.onResume() or, if the app has no Activity, Context.startService() has been called when the app was in either the created or background states + AttributeAndroidStateForeground = "foreground" +) + +// 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" +) + +func GetEventSemanticConventionAttributeNames() []string { + return []string{ + AttributeIosState, + AttributeAndroidState, + AttributeMessageCompressedSize, + AttributeMessageID, + AttributeMessageType, + AttributeMessageUncompressedSize, + } +} diff --git a/semconv/v1.25.0/generated_resource.go b/semconv/v1.25.0/generated_resource.go new file mode 100644 index 00000000000..7b355e40661 --- /dev/null +++ b/semconv/v1.25.0/generated_resource.go @@ -0,0 +1,242 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Code generated from semantic convention specification. DO NOT EDIT. + +package semconv + +// Resources used by AWS Elastic Container Service (ECS). +const ( + // The ID of a running ECS task. The ID MUST be extracted from task.arn. + // + // Type: string + // Requirement Level: Conditionally Required - If and only if `task.arn` is + // populated. + // Stability: experimental + // Examples: '10838bed-421f-43ef-870a-f43feacbbb5b', + // '23ebb8ac-c18f-46c6-8bbe-d55d0e37cfbd' + AttributeAWSECSTaskID = "aws.ecs.task.id" + // 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 a running ECS task. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'arn:aws:ecs:us- + // west-1:123456789123:task/10838bed-421f-43ef-870a-f43feacbbb5b', + // 'arn:aws:ecs:us-west-1:123456789123:task/my-cluster/task- + // id/23ebb8ac-c18f-46c6-8bbe-d55d0e37cfbd' + AttributeAWSECSTaskARN = "aws.ecs.task.arn" + // The family name of the ECS task definition used to create the ECS task. + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Examples: 'opentelemetry-family' + AttributeAWSECSTaskFamily = "aws.ecs.task.family" + // The revision for the task definition used to create the ECS task. + // + // 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" +) + +// 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" +) + +// Resource describing the packaged software running the application code. Web +// engines are typically executed using process.runtime. +const ( + // The name of the web engine. + // + // Type: string + // Requirement Level: Required + // Stability: experimental + // Examples: 'WildFly' + AttributeWebEngineName = "webengine.name" + // 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 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: stable + // 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: stable + // Examples: '1.0.0' + AttributeOTelScopeVersion = "otel.scope.version" +) + +// Span attributes used by non-OTLP exporters to represent OpenTelemetry +// Scope's concepts. +const ( + // None + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: use the `otel.scope.name` attribute. + // Examples: 'io.opentelemetry.contrib.mongodb' + AttributeOTelLibraryName = "otel.library.name" + // None + // + // Type: string + // Requirement Level: Optional + // Stability: experimental + // Deprecated: use the `otel.scope.version` attribute. + // Examples: '1.0.0' + AttributeOTelLibraryVersion = "otel.library.version" +) + +func GetResourceSemanticConventionAttributeNames() []string { + return []string{ + AttributeAWSECSTaskID, + AttributeAWSECSClusterARN, + AttributeAWSECSContainerARN, + AttributeAWSECSLaunchtype, + AttributeAWSECSTaskARN, + AttributeAWSECSTaskFamily, + AttributeAWSECSTaskRevision, + AttributeAWSEKSClusterARN, + AttributeAWSLogGroupARNs, + AttributeAWSLogGroupNames, + AttributeAWSLogStreamARNs, + AttributeAWSLogStreamNames, + AttributeHerokuAppID, + AttributeHerokuReleaseCommit, + AttributeHerokuReleaseCreationTimestamp, + AttributeWebEngineName, + AttributeWebEngineDescription, + AttributeWebEngineVersion, + AttributeOTelScopeName, + AttributeOTelScopeVersion, + AttributeOTelLibraryName, + AttributeOTelLibraryVersion, + } +} diff --git a/semconv/v1.25.0/generated_trace.go b/semconv/v1.25.0/generated_trace.go new file mode 100644 index 00000000000..b214a9f4fb0 --- /dev/null +++ b/semconv/v1.25.0/generated_trace.go @@ -0,0 +1,245 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Code generated from semantic convention specification. DO NOT EDIT. + +package semconv + +// 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" +) + +// 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" +) + +// 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 doesn't depend in any way on the result of the child Span + AttributeOpentracingRefTypeFollowsFrom = "follows_from" +) + +// 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: stable + AttributeOTelStatusCode = "otel.status_code" + // Description of the Status if it has a value, otherwise not set. + // + // Type: string + // Requirement Level: Optional + // Stability: stable + // 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" +) + +// 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 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" +) + +func GetTraceSemanticConventionAttributeNames() []string { + return []string{ + AttributePeerService, + AttributeAWSLambdaInvokedARN, + AttributeOpentracingRefType, + AttributeOTelStatusCode, + AttributeOTelStatusDescription, + AttributeAWSRequestID, + AttributeAWSS3Bucket, + AttributeAWSS3CopySource, + AttributeAWSS3Delete, + AttributeAWSS3Key, + AttributeAWSS3PartNumber, + AttributeAWSS3UploadID, + AttributeGraphqlDocument, + AttributeGraphqlOperationName, + AttributeGraphqlOperationType, + } +} diff --git a/semconv/v1.25.0/schema.go b/semconv/v1.25.0/schema.go new file mode 100644 index 00000000000..3739fe9ef81 --- /dev/null +++ b/semconv/v1.25.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.25.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.25.0" diff --git a/service/go.mod b/service/go.mod index 602137b3bbc..3e31d3b760b 100644 --- a/service/go.mod +++ b/service/go.mod @@ -5,50 +5,48 @@ go 1.21 require ( 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 + github.com/prometheus/client_model v0.6.1 + github.com/prometheus/common v0.53.0 + github.com/shirou/gopsutil/v3 v3.24.3 + github.com/stretchr/testify v1.9.0 go.opencensus.io v0.24.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.opentelemetry.io/collector v0.100.0 + go.opentelemetry.io/collector/component v0.100.0 + go.opentelemetry.io/collector/config/confignet v0.100.0 + go.opentelemetry.io/collector/config/configtelemetry v0.100.0 + go.opentelemetry.io/collector/confmap v0.100.0 + go.opentelemetry.io/collector/connector v0.100.0 + go.opentelemetry.io/collector/consumer v0.100.0 + go.opentelemetry.io/collector/exporter v0.100.0 + go.opentelemetry.io/collector/extension v0.100.0 + go.opentelemetry.io/collector/extension/zpagesextension v0.100.0 + go.opentelemetry.io/collector/featuregate v1.7.0 + go.opentelemetry.io/collector/pdata v1.7.0 + go.opentelemetry.io/collector/pdata/testdata v0.100.0 + go.opentelemetry.io/collector/processor v0.100.0 + go.opentelemetry.io/collector/receiver v0.100.0 + go.opentelemetry.io/collector/semconv v0.100.0 + go.opentelemetry.io/contrib/config v0.6.0 + go.opentelemetry.io/contrib/propagators/b3 v1.26.0 + go.opentelemetry.io/otel v1.26.0 + go.opentelemetry.io/otel/bridge/opencensus v1.26.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/sdk v1.26.0 + go.opentelemetry.io/otel/sdk/metric v1.26.0 + go.opentelemetry.io/otel/trace v1.26.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 - gonum.org/v1/gonum v0.14.0 + gonum.org/v1/gonum v0.15.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // 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 @@ -57,13 +55,12 @@ require ( 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/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // 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.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.1 // 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 @@ -75,17 +72,20 @@ require ( 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.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 + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.opentelemetry.io/contrib/zpages v0.51.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.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 + google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -97,6 +97,8 @@ replace go.opentelemetry.io/collector/component => ../component replace go.opentelemetry.io/collector/pdata => ../pdata +replace go.opentelemetry.io/collector/pdata/testdata => ../pdata/testdata + replace go.opentelemetry.io/collector/extension/zpagesextension => ../extension/zpagesextension replace go.opentelemetry.io/collector/extension => ../extension diff --git a/service/go.sum b/service/go.sum index a888ca2c937..db17fdf1402 100644 --- a/service/go.sum +++ b/service/go.sum @@ -2,8 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT 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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/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/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -41,16 +41,12 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W 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/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -59,8 +55,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= 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= @@ -71,8 +67,8 @@ 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.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8= -github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es= +github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM= +github.com/knadh/koanf/v2 v2.1.1/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= @@ -95,16 +91,16 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:Om 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.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/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= +github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= 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/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE= +github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg= 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= @@ -112,58 +108,60 @@ github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnj 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/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 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= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/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/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.opentelemetry.io/contrib/config v0.6.0 h1:M1SRD1Z15XHPGk61tMLI1up77XT5FdrqQSRrlH0fYuk= +go.opentelemetry.io/contrib/config v0.6.0/go.mod h1:t+/kzmRWLN7J+4F/dD4fFvlYCmCO63WYwy/B00IC++c= +go.opentelemetry.io/contrib/propagators/b3 v1.26.0 h1:wgFbVA+bK2k+fGVfDOCOG4cfDAoppyr5sI2dVlh8MWM= +go.opentelemetry.io/contrib/propagators/b3 v1.26.0/go.mod h1:DDktFXxA+fyItAAM0Sbl5OBH7KOsCTjvbBdPKtoIf/k= +go.opentelemetry.io/contrib/zpages v0.51.0 h1:psVr4JTWd0qtISPj9EA6AODGJ09bvsOxWiuKqiGdSCA= +go.opentelemetry.io/contrib/zpages v0.51.0/go.mod h1:PKtp+NEp1gTTLmFHpynYgYCSkKtisPntOb9S1mQjFKg= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/bridge/opencensus v1.26.0 h1:DZzxj9QjznMVoehskOJnFP2gsTCWtDTFBDvFhPAY7nc= +go.opentelemetry.io/otel/bridge/opencensus v1.26.0/go.mod h1:rJiX0KrF5m8Tm1XE8jLczpAv5zUaDcvhKecFG0ZoFG4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 h1:+hm+I+KigBy3M24/h1p/NHkUx/evbLH0PNcjpMyCHc4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0/go.mod h1:NjC8142mLvvNT6biDpaMjyz78kyEHIwAJlSX0N9P5KI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 h1:HGZWGmCVRCVyAs2GQaiHQPbDHo+ObFWeUEOd+zDnp64= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0/go.mod h1:SaH+v38LSCHddyk7RGlU9uZyQoRrKao6IBnJw6Kbn+c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 h1:1u/AyyOqAWzy+SkPxDpahCNZParHV8Vid1RnI2clyDE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0/go.mod h1:z46paqbJ9l7c9fIPCXTqTGwhQZ5XoTIsfeFYWboizjs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 h1:Waw9Wfpo/IXzOI8bCB7DIk+0JZcqqsyn1JFnAc+iam8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0/go.mod h1:wnJIG4fOqyynOnnQF/eQb4/16VlX2EJAHhHgqIqWfAo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 h1:1wp/gyxsuYtuE/JFxsQRtcCDtMrO2qMvlfXALU5wkzI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0/go.mod h1:gbTHmghkGgqxMomVQQMur1Nba4M0MQ8AYThXDUjsJ38= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 h1:5fnmgteaar1VcAA69huatudPduNFz7guRtCmfZCooZI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0/go.mod h1:lsPccfZiz1cb1AhBPmicWM2E4F1VynFXEvD8SEBS4TM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 h1:0W5o9SzoR15ocYHEQfvfipzcNog1lBxOLfnex91Hk6s= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0/go.mod h1:zVZ8nz+VSggWmnh6tTsJqXQ7rU4xLwRtna1M4x5jq58= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= 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= @@ -174,8 +172,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk 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-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= 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= @@ -190,8 +188,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL 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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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= @@ -206,9 +204,9 @@ 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.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/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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= @@ -225,26 +223,26 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= -gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= +gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= +gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= 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 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/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 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.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= -google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 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= @@ -254,10 +252,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 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/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= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.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/service/host.go b/service/host.go index 870e0bfc446..ce8dc530d40 100644 --- a/service/host.go +++ b/service/host.go @@ -14,6 +14,12 @@ import ( "go.opentelemetry.io/collector/service/internal/graph" ) +// TODO: remove as part of https://github.com/open-telemetry/opentelemetry-collector/issues/7370 for service 1.0 +type getExporters interface { + GetExporters() map[component.DataType]map[component.ID]component.Component +} + +var _ getExporters = (*serviceHost)(nil) var _ component.Host = (*serviceHost)(nil) type serviceHost struct { diff --git a/service/internal/capabilityconsumer/capabilities_test.go b/service/internal/capabilityconsumer/capabilities_test.go index 73ce2b577a0..69e9f17249f 100644 --- a/service/internal/capabilityconsumer/capabilities_test.go +++ b/service/internal/capabilityconsumer/capabilities_test.go @@ -12,7 +12,7 @@ import ( "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" - "go.opentelemetry.io/collector/internal/testdata" + "go.opentelemetry.io/collector/pdata/testdata" ) func TestLogs(t *testing.T) { diff --git a/service/internal/graph/graph.go b/service/internal/graph/graph.go index 04643a37526..525c269a6de 100644 --- a/service/internal/graph/graph.go +++ b/service/internal/graph/graph.go @@ -53,6 +53,8 @@ type Graph struct { telemetry servicetelemetry.TelemetrySettings } +// Build builds a full pipeline graph. +// Build also validates the configuration of the pipelines and does the actual initialization of each Component in the Graph. func Build(ctx context.Context, set Settings) (*Graph, error) { pipelines := &Graph{ componentGraph: simple.NewDirectedGraph(), @@ -73,18 +75,22 @@ func Build(ctx context.Context, set Settings) (*Graph, error) { return pipelines, pipelines.buildComponents(ctx, set) } -// Creates a node for each instance of a component and adds it to the graph +// Creates a node for each instance of a component and adds it to the graph. +// Validates that connectors are configured to export and receive correctly. func (g *Graph) createNodes(set Settings) error { - // Build a list of all connectors for easy reference + // Build a list of all connectors for easy reference. connectors := make(map[component.ID]struct{}) - // Keep track of connectors and where they are used. (map[connectorID][]pipelineID) + // Keep track of connectors and where they are used. (map[connectorID][]pipelineID). connectorsAsExporter := make(map[component.ID][]component.ID) connectorsAsReceiver := make(map[component.ID][]component.ID) + // Build each pipelineNodes struct for each pipeline by parsing the pipelineCfg. + // Also populates the connectors, connectorsAsExporter and connectorsAsReceiver maps. for pipelineID, pipelineCfg := range set.PipelineConfigs { pipe := g.pipelines[pipelineID] for _, recvID := range pipelineCfg.Receivers { + // Checks if this receiver is a connector or a regular receiver. if set.ConnectorBuilder.IsConfigured(recvID) { connectors[recvID] = struct{}{} connectorsAsReceiver[recvID] = append(connectorsAsReceiver[recvID], pipelineID) @@ -138,6 +144,7 @@ func (g *Graph) createNodes(set Settings) error { for expType := range expTypes { for recType := range recTypes { + // Typechecks the connector's receiving and exporting datatypes. if connectorStability(connFactory, expType, recType) != component.StabilityLevelUndefined { expTypes[expType] = true recTypes[recType] = true @@ -241,12 +248,15 @@ func (g *Graph) createConnector(exprPipelineID, rcvrPipelineID, connID component return connNode } +// Iterates through the pipelines and creates edges between components. func (g *Graph) createEdges() { for _, pg := range g.pipelines { + // Draw edges from each receiver to the capability node. for _, receiver := range pg.receivers { g.componentGraph.SetEdge(g.componentGraph.NewEdge(receiver, pg.capabilitiesNode)) } + // Iterates through processors, chaining them together. starts with the capabilities node. var from, to graph.Node from = pg.capabilitiesNode for _, processor := range pg.processors { @@ -254,6 +264,8 @@ func (g *Graph) createEdges() { g.componentGraph.SetEdge(g.componentGraph.NewEdge(from, to)) from = processor } + // Always inserts a fanout node before any exporters. If there is only one + // exporter, the fanout node is still created and acts as a noop. to = pg.fanOutNode g.componentGraph.SetEdge(g.componentGraph.NewEdge(from, to)) @@ -263,6 +275,9 @@ func (g *Graph) createEdges() { } } +// Uses the already built graph g to instantiate the actual components for each component of each pipeline. +// Handles calling the factories for each component - and hooking up each component to the next. +// Also calculates whether each pipeline mutates data so the receiver can know whether it needs to clone the data. func (g *Graph) buildComponents(ctx context.Context, set Settings) error { nodes, err := topo.Sort(g.componentGraph) if err != nil { @@ -282,6 +297,7 @@ func (g *Graph) buildComponents(ctx context.Context, set Settings) error { case *receiverNode: err = n.buildComponent(ctx, telemetrySettings, set.BuildInfo, set.ReceiverBuilder, g.nextConsumers(n.ID())) case *processorNode: + // nextConsumers is guaranteed to be length 1. Either it is the next processor or it is the fanout node for the exporters. err = n.buildComponent(ctx, telemetrySettings, set.BuildInfo, set.ProcessorBuilder, g.nextConsumers(n.ID())[0]) case *exporterNode: err = n.buildComponent(ctx, telemetrySettings, set.BuildInfo, set.ExporterBuilder) diff --git a/service/internal/graph/graph_test.go b/service/internal/graph/graph_test.go index 9ae936b5d05..eddd3098153 100644 --- a/service/internal/graph/graph_test.go +++ b/service/internal/graph/graph_test.go @@ -23,7 +23,7 @@ import ( "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/exporter" "go.opentelemetry.io/collector/exporter/exportertest" - "go.opentelemetry.io/collector/internal/testdata" + "go.opentelemetry.io/collector/pdata/testdata" "go.opentelemetry.io/collector/processor" "go.opentelemetry.io/collector/processor/processortest" "go.opentelemetry.io/collector/receiver" diff --git a/service/internal/proctelemetry/config.go b/service/internal/proctelemetry/config.go index 9d315b48cdb..0a9a8b08d82 100644 --- a/service/internal/proctelemetry/config.go +++ b/service/internal/proctelemetry/config.go @@ -21,15 +21,11 @@ import ( "go.opentelemetry.io/otel/bridge/opencensus" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" - "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" - "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" otelprom "go.opentelemetry.io/otel/exporters/prometheus" "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" - "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/sdk/instrumentation" sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" - sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/collector/processor/processorhelper" semconv "go.opentelemetry.io/collector/semconv/v1.18.0" @@ -63,7 +59,6 @@ var ( } errNoValidMetricExporter = errors.New("no valid metric exporter") - errNoValidSpanExporter = errors.New("no valid span exporter") ) func InitMetricReader(ctx context.Context, reader config.MetricReader, asyncErrorChannel chan error) (sdkmetric.Reader, *http.Server, error) { @@ -86,47 +81,6 @@ func InitMetricReader(ctx context.Context, reader config.MetricReader, asyncErro return nil, nil, fmt.Errorf("unsupported metric reader type %v", reader) } -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( - stdouttrace.WithPrettyPrint(), - ) - if err != nil { - return nil, err - } - return initBatchSpanProcessor(processor.Batch, exp) - } - if processor.Batch.Exporter.OTLP != nil { - var err error - var exp sdktrace.SpanExporter - switch processor.Batch.Exporter.OTLP.Protocol { - case protocolProtobufHTTP: - exp, err = initOTLPHTTPSpanExporter(ctx, processor.Batch.Exporter.OTLP) - case protocolProtobufGRPC: - exp, err = initOTLPgRPCSpanExporter(ctx, processor.Batch.Exporter.OTLP) - default: - return nil, fmt.Errorf("unsupported protocol %q", processor.Batch.Exporter.OTLP.Protocol) - } - if err != nil { - return nil, err - } - return initBatchSpanProcessor(processor.Batch, exp) - } - return nil, errNoValidSpanExporter - } - return nil, fmt.Errorf("unsupported span processor type %v", processor) -} - -func InitTracerProvider(res *resource.Resource, options []sdktrace.TracerProviderOption) (*sdktrace.TracerProvider, error) { - opts := []sdktrace.TracerProviderOption{ - sdktrace.WithResource(res), - } - - opts = append(opts, options...) - return sdktrace.NewTracerProvider(opts...), nil -} - func InitOpenTelemetry(res *resource.Resource, options []sdkmetric.Option, disableHighCardinality bool) (*sdkmetric.MeterProvider, error) { opts := []sdkmetric.Option{ sdkmetric.WithResource(res), @@ -340,104 +294,3 @@ func initOTLPHTTPExporter(ctx context.Context, otlpConfig *config.OTLPMetric) (s return otlpmetrichttp.New(ctx, opts...) } - -func initOTLPgRPCSpanExporter(ctx context.Context, otlpConfig *config.OTLP) (sdktrace.SpanExporter, error) { - opts := []otlptracegrpc.Option{} - - if len(otlpConfig.Endpoint) > 0 { - u, err := url.ParseRequestURI(normalizeEndpoint(otlpConfig.Endpoint)) - if err != nil { - return nil, err - } - opts = append(opts, otlptracegrpc.WithEndpoint(u.Host)) - if u.Scheme == "http" { - opts = append(opts, otlptracegrpc.WithInsecure()) - } - } - - if otlpConfig.Compression != nil { - switch *otlpConfig.Compression { - case "gzip": - opts = append(opts, otlptracegrpc.WithCompressor(*otlpConfig.Compression)) - case "none": - break - default: - return nil, fmt.Errorf("unsupported compression %q", *otlpConfig.Compression) - } - } - if otlpConfig.Timeout != nil && *otlpConfig.Timeout > 0 { - opts = append(opts, otlptracegrpc.WithTimeout(time.Millisecond*time.Duration(*otlpConfig.Timeout))) - } - if len(otlpConfig.Headers) > 0 { - opts = append(opts, otlptracegrpc.WithHeaders(otlpConfig.Headers)) - } - - return otlptracegrpc.New(ctx, opts...) -} - -func initOTLPHTTPSpanExporter(ctx context.Context, otlpConfig *config.OTLP) (sdktrace.SpanExporter, error) { - opts := []otlptracehttp.Option{} - - if len(otlpConfig.Endpoint) > 0 { - u, err := url.ParseRequestURI(normalizeEndpoint(otlpConfig.Endpoint)) - if err != nil { - return nil, err - } - opts = append(opts, otlptracehttp.WithEndpoint(u.Host)) - - if u.Scheme == "http" { - opts = append(opts, otlptracehttp.WithInsecure()) - } - if len(u.Path) > 0 { - opts = append(opts, otlptracehttp.WithURLPath(u.Path)) - } - } - if otlpConfig.Compression != nil { - switch *otlpConfig.Compression { - case "gzip": - opts = append(opts, otlptracehttp.WithCompression(otlptracehttp.GzipCompression)) - case "none": - opts = append(opts, otlptracehttp.WithCompression(otlptracehttp.NoCompression)) - default: - return nil, fmt.Errorf("unsupported compression %q", *otlpConfig.Compression) - } - } - if otlpConfig.Timeout != nil && *otlpConfig.Timeout > 0 { - opts = append(opts, otlptracehttp.WithTimeout(time.Millisecond*time.Duration(*otlpConfig.Timeout))) - } - if len(otlpConfig.Headers) > 0 { - opts = append(opts, otlptracehttp.WithHeaders(otlpConfig.Headers)) - } - - return otlptracehttp.New(ctx, opts...) -} - -func initBatchSpanProcessor(bsp *config.BatchSpanProcessor, exp sdktrace.SpanExporter) (sdktrace.SpanProcessor, error) { - opts := []sdktrace.BatchSpanProcessorOption{} - if bsp.ExportTimeout != nil { - if *bsp.ExportTimeout < 0 { - return nil, fmt.Errorf("invalid export timeout %d", *bsp.ExportTimeout) - } - opts = append(opts, sdktrace.WithExportTimeout(time.Millisecond*time.Duration(*bsp.ExportTimeout))) - } - if bsp.MaxExportBatchSize != nil { - if *bsp.MaxExportBatchSize < 0 { - return nil, fmt.Errorf("invalid batch size %d", *bsp.MaxExportBatchSize) - } - opts = append(opts, sdktrace.WithMaxExportBatchSize(*bsp.MaxExportBatchSize)) - } - if bsp.MaxQueueSize != nil { - if *bsp.MaxQueueSize < 0 { - return nil, fmt.Errorf("invalid queue size %d", *bsp.MaxQueueSize) - } - opts = append(opts, sdktrace.WithMaxQueueSize(*bsp.MaxQueueSize)) - } - if bsp.ScheduleDelay != nil { - if *bsp.ScheduleDelay < 0 { - return nil, fmt.Errorf("invalid schedule delay %d", *bsp.ScheduleDelay) - } - opts = append(opts, sdktrace.WithBatchTimeout(time.Millisecond*time.Duration(*bsp.ScheduleDelay))) - } - return sdktrace.NewBatchSpanProcessor(exp, opts...), nil - -} diff --git a/service/internal/proctelemetry/config_test.go b/service/internal/proctelemetry/config_test.go index 6f7bbc16dfe..5228b0ead44 100644 --- a/service/internal/proctelemetry/config_test.go +++ b/service/internal/proctelemetry/config_test.go @@ -352,360 +352,3 @@ func TestMetricReader(t *testing.T) { }) } } - -func TestSpanProcessor(t *testing.T) { - testCases := []struct { - name string - processor config.SpanProcessor - args any - err error - }{ - { - name: "no processor", - err: errors.New("unsupported span processor type { }"), - }, - { - name: "batch processor invalid exporter", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - Exporter: config.SpanExporter{}, - }, - }, - err: errNoValidSpanExporter, - }, - { - name: "batch processor invalid batch size console exporter", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxExportBatchSize: intPtr(-1), - Exporter: config.SpanExporter{ - Console: config.Console{}, - }, - }, - }, - err: errors.New("invalid batch size -1"), - }, - { - name: "batch processor invalid export timeout console exporter", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - ExportTimeout: intPtr(-2), - Exporter: config.SpanExporter{ - Console: config.Console{}, - }, - }, - }, - err: errors.New("invalid export timeout -2"), - }, - { - name: "batch processor invalid queue size console exporter", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxQueueSize: intPtr(-3), - Exporter: config.SpanExporter{ - Console: config.Console{}, - }, - }, - }, - err: errors.New("invalid queue size -3"), - }, - { - name: "batch processor invalid schedule delay console exporter", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - ScheduleDelay: intPtr(-4), - Exporter: config.SpanExporter{ - Console: config.Console{}, - }, - }, - }, - err: errors.New("invalid schedule delay -4"), - }, - { - name: "batch processor console exporter", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxExportBatchSize: intPtr(0), - ExportTimeout: intPtr(0), - MaxQueueSize: intPtr(0), - ScheduleDelay: intPtr(0), - Exporter: config.SpanExporter{ - Console: config.Console{}, - }, - }, - }, - }, - { - name: "batch/otlp-exporter-invalid-protocol", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxExportBatchSize: intPtr(0), - ExportTimeout: intPtr(0), - MaxQueueSize: intPtr(0), - ScheduleDelay: intPtr(0), - Exporter: config.SpanExporter{ - OTLP: &config.OTLP{ - Protocol: *strPtr("http/invalid"), - }, - }, - }, - }, - err: errors.New("unsupported protocol \"http/invalid\""), - }, - { - name: "batch/otlp-grpc-exporter-no-endpoint", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxExportBatchSize: intPtr(0), - ExportTimeout: intPtr(0), - MaxQueueSize: intPtr(0), - ScheduleDelay: intPtr(0), - Exporter: config.SpanExporter{ - OTLP: &config.OTLP{ - Protocol: "grpc/protobuf", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - }, - { - name: "batch/otlp-grpc-exporter", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxExportBatchSize: intPtr(0), - ExportTimeout: intPtr(0), - MaxQueueSize: intPtr(0), - ScheduleDelay: intPtr(0), - Exporter: config.SpanExporter{ - OTLP: &config.OTLP{ - Protocol: "grpc/protobuf", - Endpoint: "http://localhost:4317", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - }, - { - name: "batch/otlp-grpc-exporter-no-scheme", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxExportBatchSize: intPtr(0), - ExportTimeout: intPtr(0), - MaxQueueSize: intPtr(0), - ScheduleDelay: intPtr(0), - Exporter: config.SpanExporter{ - OTLP: &config.OTLP{ - Protocol: "grpc/protobuf", - Endpoint: "localhost:4317", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - }, - { - name: "batch/otlp-grpc-invalid-endpoint", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxExportBatchSize: intPtr(0), - ExportTimeout: intPtr(0), - MaxQueueSize: intPtr(0), - ScheduleDelay: intPtr(0), - Exporter: config.SpanExporter{ - OTLP: &config.OTLP{ - Protocol: "grpc/protobuf", - Endpoint: " ", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - err: &url.Error{Op: "parse", URL: "http:// ", Err: url.InvalidHostError(" ")}, - }, - { - name: "batch/otlp-grpc-invalid-compression", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxExportBatchSize: intPtr(0), - ExportTimeout: intPtr(0), - MaxQueueSize: intPtr(0), - ScheduleDelay: intPtr(0), - Exporter: config.SpanExporter{ - OTLP: &config.OTLP{ - Protocol: "grpc/protobuf", - Endpoint: "localhost:4317", - Compression: strPtr("invalid"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - err: errors.New("unsupported compression \"invalid\""), - }, - { - name: "batch/otlp-http-exporter", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxExportBatchSize: intPtr(0), - ExportTimeout: intPtr(0), - MaxQueueSize: intPtr(0), - ScheduleDelay: intPtr(0), - Exporter: config.SpanExporter{ - OTLP: &config.OTLP{ - Protocol: "http/protobuf", - Endpoint: "http://localhost:4318", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - }, - { - name: "batch/otlp-http-exporter-with-path", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxExportBatchSize: intPtr(0), - ExportTimeout: intPtr(0), - MaxQueueSize: intPtr(0), - ScheduleDelay: intPtr(0), - Exporter: config.SpanExporter{ - OTLP: &config.OTLP{ - Protocol: "http/protobuf", - Endpoint: "http://localhost:4318/path/123", - Compression: strPtr("none"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - }, - { - name: "batch/otlp-http-exporter-no-endpoint", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxExportBatchSize: intPtr(0), - ExportTimeout: intPtr(0), - MaxQueueSize: intPtr(0), - ScheduleDelay: intPtr(0), - Exporter: config.SpanExporter{ - OTLP: &config.OTLP{ - Protocol: "http/protobuf", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - }, - { - name: "batch/otlp-http-exporter-no-scheme", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxExportBatchSize: intPtr(0), - ExportTimeout: intPtr(0), - MaxQueueSize: intPtr(0), - ScheduleDelay: intPtr(0), - Exporter: config.SpanExporter{ - OTLP: &config.OTLP{ - Protocol: "http/protobuf", - Endpoint: "localhost:4318", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - }, - { - name: "batch/otlp-http-invalid-endpoint", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxExportBatchSize: intPtr(0), - ExportTimeout: intPtr(0), - MaxQueueSize: intPtr(0), - ScheduleDelay: intPtr(0), - Exporter: config.SpanExporter{ - OTLP: &config.OTLP{ - Protocol: "http/protobuf", - Endpoint: " ", - Compression: strPtr("gzip"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - err: &url.Error{Op: "parse", URL: "http:// ", Err: url.InvalidHostError(" ")}, - }, - { - name: "batch/otlp-http-invalid-compression", - processor: config.SpanProcessor{ - Batch: &config.BatchSpanProcessor{ - MaxExportBatchSize: intPtr(0), - ExportTimeout: intPtr(0), - MaxQueueSize: intPtr(0), - ScheduleDelay: intPtr(0), - Exporter: config.SpanExporter{ - OTLP: &config.OTLP{ - Protocol: "http/protobuf", - Endpoint: "localhost:4318", - Compression: strPtr("invalid"), - Timeout: intPtr(1000), - Headers: map[string]string{ - "test": "test1", - }, - }, - }, - }, - }, - err: errors.New("unsupported compression \"invalid\""), - }, - } - for _, tt := range testCases { - t.Run(tt.name, func(t *testing.T) { - 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/resource/config_test.go b/service/internal/resource/config_test.go index ab8f8e816c3..38fcba1a139 100644 --- a/service/internal/resource/config_test.go +++ b/service/internal/resource/config_test.go @@ -8,8 +8,11 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" + sdkresource "go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/pdata/pcommon" + semconv "go.opentelemetry.io/collector/semconv/v1.18.0" ) const ( @@ -101,3 +104,67 @@ func TestNew(t *testing.T) { } } + +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. + pcommonRes := pcommon.NewResource() + for _, keyValue := range res.Attributes() { + pcommonRes.Attributes().PutStr(string(keyValue.Key), keyValue.Value.AsString()) + } + return pcommonRes +} + +func TestBuildResource(t *testing.T) { + buildInfo := component.NewDefaultBuildInfo() + + // Check default config + var resMap map[string]*string + otelRes := New(buildInfo, resMap) + res := pdataFromSdk(otelRes) + + assert.Equal(t, res.Attributes().Len(), 3) + value, ok := res.Attributes().Get(semconv.AttributeServiceName) + assert.True(t, ok) + assert.Equal(t, buildInfo.Command, value.AsString()) + value, ok = res.Attributes().Get(semconv.AttributeServiceVersion) + assert.True(t, ok) + assert.Equal(t, buildInfo.Version, value.AsString()) + + _, ok = res.Attributes().Get(semconv.AttributeServiceInstanceID) + assert.True(t, ok) + + // Check override by nil + resMap = map[string]*string{ + semconv.AttributeServiceName: nil, + semconv.AttributeServiceVersion: nil, + semconv.AttributeServiceInstanceID: nil, + } + otelRes = New(buildInfo, resMap) + res = pdataFromSdk(otelRes) + + // Attributes should not exist since we nil-ified all. + assert.Equal(t, res.Attributes().Len(), 0) + + // Check override values + strPtr := func(v string) *string { return &v } + resMap = map[string]*string{ + semconv.AttributeServiceName: strPtr("a"), + semconv.AttributeServiceVersion: strPtr("b"), + semconv.AttributeServiceInstanceID: strPtr("c"), + } + otelRes = New(buildInfo, resMap) + res = pdataFromSdk(otelRes) + + assert.Equal(t, res.Attributes().Len(), 3) + value, ok = res.Attributes().Get(semconv.AttributeServiceName) + assert.True(t, ok) + assert.Equal(t, "a", value.AsString()) + value, ok = res.Attributes().Get(semconv.AttributeServiceVersion) + assert.True(t, ok) + assert.Equal(t, "b", value.AsString()) + value, ok = res.Attributes().Get(semconv.AttributeServiceInstanceID) + assert.True(t, ok) + assert.Equal(t, "c", value.AsString()) +} diff --git a/service/internal/status/status.go b/service/internal/status/status.go index 21790b1061f..e1d524906e5 100644 --- a/service/internal/status/status.go +++ b/service/internal/status/status.go @@ -121,17 +121,6 @@ func (r *Reporter) Ready() { 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, @@ -148,14 +137,6 @@ func (r *Reporter) ReportStatus( } } -// 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() diff --git a/service/internal/testcomponents/example_connector.go b/service/internal/testcomponents/example_connector.go index 75c5145cf7b..a521389cf80 100644 --- a/service/internal/testcomponents/example_connector.go +++ b/service/internal/testcomponents/example_connector.go @@ -9,10 +9,10 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/connector" "go.opentelemetry.io/collector/consumer" - "go.opentelemetry.io/collector/internal/testdata" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/collector/pdata/testdata" ) var connType = component.MustNewType("exampleconnector") diff --git a/service/internal/testcomponents/example_router_test.go b/service/internal/testcomponents/example_router_test.go index 23f94854b2a..2f44e04902d 100644 --- a/service/internal/testcomponents/example_router_test.go +++ b/service/internal/testcomponents/example_router_test.go @@ -15,7 +15,7 @@ import ( "go.opentelemetry.io/collector/connector/connectortest" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" - "go.opentelemetry.io/collector/internal/testdata" + "go.opentelemetry.io/collector/pdata/testdata" ) func TestExampleRouter(t *testing.T) { diff --git a/service/service.go b/service/service.go index febff396417..902454c78f1 100644 --- a/service/service.go +++ b/service/service.go @@ -9,6 +9,7 @@ import ( "fmt" "runtime" + "go.opentelemetry.io/otel/metric" sdkresource "go.opentelemetry.io/otel/sdk/resource" "go.uber.org/multierr" "go.uber.org/zap" @@ -33,7 +34,7 @@ import ( "go.opentelemetry.io/collector/service/telemetry" ) -// Settings holds configuration for building a new service. +// Settings holds configuration for building a new Service. type Settings struct { // BuildInfo provides collector start information. BuildInfo component.BuildInfo @@ -71,6 +72,7 @@ type Service struct { collectorConf *confmap.Conf } +// New creates a new Service, its telemetry, and Components. func New(ctx context.Context, set Settings, cfg Config) (*Service, error) { disableHighCard := obsreportconfig.DisableHighCardinalityMetricsfeatureGate.IsEnabled() extendedConfig := obsreportconfig.UseOtelWithSDKConfigurationForInternalTelemetryFeatureGate.IsEnabled() @@ -91,23 +93,26 @@ func New(ctx context.Context, set Settings, cfg Config) (*Service, error) { if err != nil { return nil, fmt.Errorf("failed to get logger: %w", err) } + + // Fetch data for internal telemetry like instance id and sdk version to provide for internal telemetry. res := resource.New(set.BuildInfo, cfg.Telemetry.Resource) pcommonRes := pdataFromSdk(res) logger := tel.Logger() + logger.Info("Setting up own telemetry...") 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) } + + logsAboutMeterProvider(logger, cfg.Telemetry.Metrics, mp, extendedConfig) srv.telemetrySettings = servicetelemetry.TelemetrySettings{ Logger: logger, MeterProvider: mp, @@ -133,6 +138,27 @@ func New(ctx context.Context, set Settings, cfg Config) (*Service, error) { return srv, nil } +func logsAboutMeterProvider(logger *zap.Logger, cfg telemetry.MetricsConfig, mp metric.MeterProvider, extendedConfig bool) { + if cfg.Level == configtelemetry.LevelNone || (cfg.Address == "" && len(cfg.Readers) == 0) { + logger.Info( + "Skipped telemetry setup.", + zap.String(zapKeyTelemetryAddress, cfg.Address), + zap.Stringer(zapKeyTelemetryLevel, cfg.Level), + ) + return + } + + if len(cfg.Address) != 0 && extendedConfig { + logger.Warn("service::telemetry::metrics::address is being deprecated in favor of service::telemetry::metrics::readers") + } + + if lmp, ok := mp.(interface { + LogAboutServers(logger *zap.Logger, cfg telemetry.MetricsConfig) + }); ok { + lmp.LogAboutServers(logger, cfg) + } +} + // 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. @@ -224,6 +250,7 @@ func (srv *Service) Shutdown(ctx context.Context) error { return errs } +// Creates extensions and then builds the pipeline graph. func (srv *Service) initExtensionsAndPipeline(ctx context.Context, set Settings, cfg Config) error { var err error extensionsSettings := extensions.Settings{ diff --git a/service/telemetry.go b/service/telemetry.go index c7aab098747..365ea3d23c5 100644 --- a/service/telemetry.go +++ b/service/telemetry.go @@ -37,26 +37,16 @@ type meterProvider struct { type meterProviderSettings struct { res *resource.Resource - logger *zap.Logger cfg telemetry.MetricsConfig asyncErrorChannel chan error } -func newMeterProvider(set meterProviderSettings, disableHighCardinality bool, extendedConfig bool) (metric.MeterProvider, error) { +func newMeterProvider(set meterProviderSettings, disableHighCardinality 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, set.cfg.Address), - zap.String(zapKeyTelemetryLevel, set.cfg.Level.String()), - ) return noopmetric.NewMeterProvider(), nil } - 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") - } host, port, err := net.SplitHostPort(set.cfg.Address) if err != nil { return nil, err @@ -94,11 +84,7 @@ func newMeterProvider(set meterProviderSettings, disableHighCardinality bool, ex } if server != nil { mp.servers = append(mp.servers, server) - set.logger.Info( - "Serving metrics", - zap.String(zapKeyTelemetryAddress, server.Addr), - zap.String(zapKeyTelemetryLevel, set.cfg.Level.String()), - ) + } opts = append(opts, sdkmetric.WithReader(r)) } @@ -111,6 +97,17 @@ func newMeterProvider(set meterProviderSettings, disableHighCardinality bool, ex return mp, nil } +// LogAboutServers logs about the servers that are serving metrics. +func (mp *meterProvider) LogAboutServers(logger *zap.Logger, cfg telemetry.MetricsConfig) { + for _, server := range mp.servers { + logger.Info( + "Serving metrics", + zap.String(zapKeyTelemetryAddress, server.Addr), + zap.Stringer(zapKeyTelemetryLevel, cfg.Level), + ) + } +} + // Shutdown the meter provider and all the associated resources. // The type signature of this method matches that of the sdkmetric.MeterProvider. func (mp *meterProvider) Shutdown(ctx context.Context) error { diff --git a/service/telemetry/otel_trace_sampler.go b/service/telemetry/otel_trace_sampler.go deleted file mode 100644 index 25928bfe31e..00000000000 --- a/service/telemetry/otel_trace_sampler.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package telemetry // import "go.opentelemetry.io/collector/service/telemetry" - -import ( - sdktrace "go.opentelemetry.io/otel/sdk/trace" -) - -type recordSampler struct{} - -func (r recordSampler) ShouldSample(sdktrace.SamplingParameters) sdktrace.SamplingResult { - return sdktrace.SamplingResult{Decision: sdktrace.RecordOnly} -} - -func (r recordSampler) Description() string { - return "Always record sampler" -} - -func alwaysRecord() sdktrace.Sampler { - rs := &recordSampler{} - return sdktrace.ParentBased( - rs, - sdktrace.WithRemoteParentSampled(sdktrace.AlwaysSample()), - sdktrace.WithRemoteParentNotSampled(rs), - sdktrace.WithLocalParentSampled(sdktrace.AlwaysSample()), - sdktrace.WithRemoteParentSampled(rs)) -} diff --git a/service/telemetry/telemetry.go b/service/telemetry/telemetry.go index d557d1e957e..008a50c07ea 100644 --- a/service/telemetry/telemetry.go +++ b/service/telemetry/telemetry.go @@ -7,6 +7,7 @@ import ( "context" "errors" + "go.opentelemetry.io/contrib/config" "go.opentelemetry.io/contrib/propagators/b3" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/propagation" @@ -17,8 +18,6 @@ import ( "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 ( @@ -33,7 +32,7 @@ var ( type Telemetry struct { logger *zap.Logger - tracerProvider *sdktrace.TracerProvider + tracerProvider trace.TracerProvider } func (t *Telemetry) TracerProvider() trace.TracerProvider { @@ -46,9 +45,13 @@ func (t *Telemetry) Logger() *zap.Logger { func (t *Telemetry) Shutdown(ctx context.Context) error { // TODO: Sync logger. - return multierr.Combine( - t.tracerProvider.Shutdown(ctx), - ) + if tp, ok := t.tracerProvider.(*sdktrace.TracerProvider); ok { + return multierr.Combine( + tp.Shutdown(ctx), + ) + } + // should this return an error? + return nil } // Settings holds configuration for building Telemetry. @@ -64,29 +67,36 @@ func New(ctx context.Context, set Settings, cfg Config) (*Telemetry, error) { return nil, err } - 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)) - } + sdk, err := config.NewSDK( + config.WithContext(ctx), + config.WithOpenTelemetryConfiguration( + config.OpenTelemetryConfiguration{ + TracerProvider: &config.TracerProvider{ + Processors: cfg.Traces.Processors, + // TODO: once https://github.com/open-telemetry/opentelemetry-configuration/issues/83 is resolved, + // configuration for sampler should be done here via something like the following: + // + // Sampler: &config.Sampler{ + // ParentBased: &config.SamplerParentBased{ + // LocalParentSampled: &config.Sampler{ + // AlwaysOn: config.SamplerAlwaysOn{}, + // }, + // LocalParentNotSampled: &config.Sampler{ + // RecordOnly: config.SamplerRecordOnly{}, + // }, + // RemoteParentSampled: &config.Sampler{ + // AlwaysOn: config.SamplerAlwaysOn{}, + // }, + // RemoteParentNotSampled: &config.Sampler{ + // RecordOnly: config.SamplerRecordOnly{}, + // }, + // }, + // }, + }, + }, + ), + ) - res := resource.New(set.BuildInfo, cfg.Resource) - tp, err := proctelemetry.InitTracerProvider(res, opts) if err != nil { return nil, err } @@ -97,7 +107,10 @@ func newTracerProvider(ctx context.Context, set Settings, cfg Config) (*sdktrace return nil, err } - return tp, nil + return &Telemetry{ + logger: logger, + tracerProvider: sdk.TracerProvider(), + }, nil } func textMapPropagatorFromConfig(props []string) (propagation.TextMapPropagator, error) { diff --git a/service/telemetry/telemetry_test.go b/service/telemetry/telemetry_test.go index b01b3c7d8c8..c72d8c75e55 100644 --- a/service/telemetry/telemetry_test.go +++ b/service/telemetry/telemetry_test.go @@ -9,6 +9,9 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/trace" + "go.opentelemetry.io/otel/trace/noop" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -115,3 +118,26 @@ func TestSampledLogger(t *testing.T) { }) } } + +func TestTelemetryShutdown(t *testing.T) { + tests := []struct { + name string + provider trace.TracerProvider + wantErr error + }{ + { + name: "No provider", + }, + { + name: "Non-SDK provider", + provider: noop.NewTracerProvider(), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + telemetry := Telemetry{tracerProvider: tt.provider} + err := telemetry.Shutdown(context.Background()) + require.Equal(t, tt.wantErr, err) + }) + } +} diff --git a/service/telemetry_test.go b/service/telemetry_test.go index 37bd3d82b28..2377a077052 100644 --- a/service/telemetry_test.go +++ b/service/telemetry_test.go @@ -11,13 +11,11 @@ import ( 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" "go.opencensus.io/stats/view" "go.opentelemetry.io/contrib/config" "go.opentelemetry.io/otel/metric" - "go.uber.org/zap" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configtelemetry" @@ -37,63 +35,6 @@ const ( counterName = "test_counter" ) -func TestBuildResource(t *testing.T) { - buildInfo := component.NewDefaultBuildInfo() - - // Check default config - cfg := telemetry.Config{} - otelRes := resource.New(buildInfo, cfg.Resource) - res := pdataFromSdk(otelRes) - - assert.Equal(t, res.Attributes().Len(), 3) - value, ok := res.Attributes().Get(semconv.AttributeServiceName) - assert.True(t, ok) - assert.Equal(t, buildInfo.Command, value.AsString()) - value, ok = res.Attributes().Get(semconv.AttributeServiceVersion) - assert.True(t, ok) - assert.Equal(t, buildInfo.Version, value.AsString()) - - _, ok = res.Attributes().Get(semconv.AttributeServiceInstanceID) - assert.True(t, ok) - - // Check override by nil - cfg = telemetry.Config{ - Resource: map[string]*string{ - semconv.AttributeServiceName: nil, - semconv.AttributeServiceVersion: nil, - semconv.AttributeServiceInstanceID: nil, - }, - } - otelRes = resource.New(buildInfo, cfg.Resource) - res = pdataFromSdk(otelRes) - - // Attributes should not exist since we nil-ified all. - assert.Equal(t, res.Attributes().Len(), 0) - - // Check override values - strPtr := func(v string) *string { return &v } - cfg = telemetry.Config{ - Resource: map[string]*string{ - semconv.AttributeServiceName: strPtr("a"), - semconv.AttributeServiceVersion: strPtr("b"), - semconv.AttributeServiceInstanceID: strPtr("c"), - }, - } - otelRes = resource.New(buildInfo, cfg.Resource) - res = pdataFromSdk(otelRes) - - assert.Equal(t, res.Attributes().Len(), 3) - value, ok = res.Attributes().Get(semconv.AttributeServiceName) - assert.True(t, ok) - assert.Equal(t, "a", value.AsString()) - value, ok = res.Attributes().Get(semconv.AttributeServiceVersion) - assert.True(t, ok) - assert.Equal(t, "b", value.AsString()) - value, ok = res.Attributes().Get(semconv.AttributeServiceInstanceID) - assert.True(t, ok) - assert.Equal(t, "c", value.AsString()) -} - func TestTelemetryInit(t *testing.T) { type metricValue struct { value float64 @@ -299,11 +240,10 @@ func TestTelemetryInit(t *testing.T) { } set := meterProviderSettings{ res: resource.New(component.NewDefaultBuildInfo(), tc.cfg.Resource), - logger: zap.NewNop(), cfg: tc.cfg.Metrics, asyncErrorChannel: make(chan error), } - mp, err := newMeterProvider(set, tc.disableHighCard, tc.extendedConfig) + mp, err := newMeterProvider(set, tc.disableHighCard) require.NoError(t, err) defer func() { if prov, ok := mp.(interface{ Shutdown(context.Context) error }); ok { diff --git a/versions.yaml b/versions.yaml index 7c0074f9ad1..0c8cf222c6a 100644 --- a/versions.yaml +++ b/versions.yaml @@ -3,13 +3,14 @@ module-sets: stable: - version: v1.3.0 + version: v1.7.0 modules: - go.opentelemetry.io/collector/featuregate - go.opentelemetry.io/collector/pdata - go.opentelemetry.io/collector/config/configopaque + - go.opentelemetry.io/collector/config/configcompression beta: - version: v0.96.0 + version: v0.100.0 modules: - go.opentelemetry.io/collector - go.opentelemetry.io/collector/cmd/builder @@ -23,7 +24,6 @@ module-sets: - 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 @@ -37,6 +37,7 @@ module-sets: - go.opentelemetry.io/collector/exporter - go.opentelemetry.io/collector/exporter/debugexporter - go.opentelemetry.io/collector/exporter/loggingexporter + - go.opentelemetry.io/collector/exporter/nopexporter - go.opentelemetry.io/collector/exporter/otlpexporter - go.opentelemetry.io/collector/exporter/otlphttpexporter - go.opentelemetry.io/collector/extension @@ -45,13 +46,16 @@ module-sets: - go.opentelemetry.io/collector/extension/zpagesextension - go.opentelemetry.io/collector/extension/memorylimiterextension - go.opentelemetry.io/collector/otelcol + - go.opentelemetry.io/collector/pdata/testdata - go.opentelemetry.io/collector/processor - go.opentelemetry.io/collector/processor/batchprocessor - go.opentelemetry.io/collector/processor/memorylimiterprocessor - go.opentelemetry.io/collector/receiver + - go.opentelemetry.io/collector/receiver/nopreceiver - go.opentelemetry.io/collector/receiver/otlpreceiver - go.opentelemetry.io/collector/semconv - go.opentelemetry.io/collector/service + - go.opentelemetry.io/collector/filter excluded-modules: - go.opentelemetry.io/collector/cmd/otelcorecol

=|#7mWyVaI#RDTa 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%0A(Wv%#*sl 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 %;Lq@kGpojO{R-*xnf(Z|n!qSafqfj)t}PA@E< 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 z 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